2016-10-17 2 views
1

필자는 I/O 바운드 프로그램을 작성해야하며, I/O 스케줄러를 이전에 운영 체제 숙제로 사용하지 않은 것처럼 작동하게 만들지 만 어떻게해야하는지 잘 모릅니다. 커다란 텍스트 파일의 줄을 계산하는 간단한 C 프로그램을 작성하려고 시도했지만 너무 빠르게 실행되어 스케줄러의 효율성을 측정 할 수 없습니다. 이것은 내 학년의 25 % 가치가있다, 어떤 도움을 많이 주시면 감사하겠습니다.I/O 바운드 C 프로그램을 작성하려면 어떻게해야합니까?

+0

큰 파일을 사용하고 계십니까? –

+0

* I/O bound *는 하드 디스크 I/O *를 의미합니까, 아니면 다른 유형의 I/O를 사용할 수 있습니까? – user3386109

+0

@ user3386109 다른 유형의 I/O도 사용할 수 있습니다. 하드 디스크 I/O가 더 비싸다고 가정하고 있습니다. 여기서는 값 비싼 것이 필요합니다. – Fagundes

답변

0

이전 답변은 내 테스트에서 I/O 바인딩보다 더 많은 CPU 바운드로 나타납니다.

저수준의 캐시되지 않은 C 루틴을 사용하여 많은 파일을 열고 각 파일 내에서 미친 듯이 탐색하는 것이 좋습니다. 여기가 추구 수행하는 C 코드입니다 : 그것은 아주 잘 작동 내 시스템에서

find/-exec ./io_bound {} \; 2>/dev/null 

, 하나

#define _GNU_SOURCE 

#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h> 
#include <unistd.h> 

int main(int argc, char **argv) { 

    if (argc != 2) { 
     fprintf(stderr, "specify a file to read!\n"); 
     return EXIT_FAILURE; 
    } 

    int fd = open(argv[1], O_DIRECT); 
    if (fd < 0) { 
     perror("open error"); 
     return EXIT_FAILURE; 
    } 

    off_t size = lseek(fd, 0, SEEK_END); 

    for (int i = 0; i < 1000000; i++)                     
     lseek(fd, rand() % size, SEEK_SET); 

    close(fd); 

    return EXIT_SUCCESS; 
} 

을 그리고, 쉘에, 그것은을 통해 파일 시스템에있는 모든 파일을 찾아 실행 rcu_sched 작업을 발견 할 수 있습니다 :

top - 20:44:48 up 57 min, 1 user, load average: 0.84, 0.76, 0.59 
Tasks: 266 total, 2 running, 264 sleeping, 0 stopped, 0 zombie 
%Cpu0 : 10.0 us, 11.3 sy, 0.0 ni, 78.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st 
%Cpu1 : 10.3 us, 8.3 sy, 0.0 ni, 81.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st 
%Cpu2 : 15.3 us, 15.9 sy, 0.0 ni, 68.4 id, 0.3 wa, 0.0 hi, 0.0 si, 0.0 st 
%Cpu3 : 16.4 us, 14.7 sy, 0.0 ni, 68.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st 
KiB Mem : 16314192 total, 9431208 free, 3312716 used, 3570268 buff/cache 
KiB Swap: 15624188 total, 15624188 free,  0 used. 12630464 avail Mem 

    PID USER  PR NI VIRT RES SHR S %CPU %MEM  TIME+ COMMAND  
13087 gluckf 20 0 4224 784 708 R 3.3 0.0 0:00.10 io_bound  
    7 root  20 0  0  0  0 S 0.3 0.0 0:03.54 rcu_sched 
1586 root  20 0 455832 74824 62736 S 0.3 0.5 0:41.49 Xorg   
2160 gluckf 20 0 1389916 137096 52548 S 0.3 0.8 0:41.27 cinnamon  
2285 gluckf 20 0 498388 46752 28632 S 0.3 0.3 0:14.15 gnome-term+ 
+0

'lseek' 자체는 일반적으로 IO를 생성하지 않습니다. 그것은 [프로세스의 커널 파일 디스크립터 테이블에서 오프셋 값을 변경하는 것 같습니다] (http://lxr.free-electrons.com/source/fs/read_write.c?v=2.0.40#L19). –

+0

네가 맞아. 고마워. 각 임의의 위치에서 캐싱을 피하기 위해 몇 섹터를 읽으려고했으나 완전히 잊어 버렸습니다! 하지만 여기에 코드를 삽입하는 방법을 잘 모르겠습니다. – flg

+0

임의의 오프셋에서 512 바이트 버퍼를 읽으려면'pread()'를 사용하십시오 -'lseek()'는 필요하지 않습니다. 랜덤 오프셋을'~ (0x1FF)'(511의 보수)로 마스킹하여 512 바이트의 정렬 된 오프셋을 얻고, 무작위로 하나의 디스크 블록 (512 바이트 디스크 블록을 가정)을 잡을 수 있습니다. 그리고 실제로 * IO 바인딩이되도록하려면 다중 스레드로 수행하십시오. –

0

이 시도 :

find/| head -n 1000000 | xargs -P 10 wc >/dev/null 2>&1 

그것은 아주 나쁜해야합니다. xargs -P 옵션을 사용하면이 옵션이 병렬로 실행됩니다. 적합한 부하를 얻기 위해 옵션을 조정할 수 있습니다. wc은 각 파일을 소비하는 것 외에도 많은 일을하지 않으므로 주로 IO 바인딩되어야한다고 생각합니다. 물론 여전히 디스크 캐싱이 있습니다.

관련 문제