2012-11-28 4 views
0

약 1000 개의 이미지를 읽고 그 내용에 대한 통계 요약을 만드는 프로그램이 있습니다. 각 이미지는 OpenMP를 사용하여 자체 스레드에서 처리되며, 스레드 수를 프로세서 수와 일치하도록 설정했습니다.리소스 사용량이 많은 프로그램이 중단되었습니다/리눅스가 충돌합니다

약 2 주 전까지 만해도 프로그램은 정상적으로 실행되었습니다. 그러나 이제는 프로그램을 두 번 이상 실행하면 시스템이 느려지고 결국 멈 춥니 다.

문제를 해결하기 위해 아래 나열된 간단한 코드를 작성하여 프로그램에서 수행하는 작업을 에뮬레이션합니다. 이 코드는 35 번째 줄에 몇 개의 파일 만 읽으려고 한 후 원래 프로그램처럼 내 시스템을 멈추게 할 것입니다.

프로그램을 실행하여 각 실패 후에 연속적으로 이전 커널로 되 돌리면 실패합니다 모든 3.6 커널은 버전 3.6.8까지입니다.

그러나 커널 3.5.6으로 돌아 가면 작동합니다.

test.cc :

1 #include <cstdio> 
    2 #include <iostream> 
    3 #include <vector> 
    4 #include <unistd.h> 
    5 
    6 using namespace std; 
    7 
    8 int main() 
    9 { 
10  // number of files 
11  const size_t N = 1000; 
12  // total system memory 
13  const size_t MEM = sysconf (_SC_PHYS_PAGES) * sysconf (_SC_PAGE_SIZE); 
14  // file size 
15  const size_t SZ = MEM/N; 
16 
17  // create temp filenames 
18  vector<string> fn (N); 
19  for (size_t i = 0; i < fn.size(); ++i) 
20   fn[i] = string (tmpnam (NULL)); 
21 
22  // write a bunch of files to disk 
23  for (size_t i = 0; i < fn.size(); ++i) 
24  { 
25   vector<char> a (SZ); 
26   FILE *fp = fopen (fn[i].c_str(), "wb"); 
27   fwrite (&a[0], a.size(), 1, fp); 
28   clog << fn[i] << " written" << endl; 
29  } 
30 
31  // read a bunch of files from disk 
32 #pragma omp parallel for 
33  for (size_t i = 0; i < fn.size(); ++i) 
34  { 
35   vector<char> a (SZ); 
36   FILE *fp = fopen (fn[i].c_str(), "rb"); 
37   fread (&a[0], a.size(), 1, fp); 
38   clog << fn[i] << " read" << endl; 
39  } 
40 
41  return 0; 
42 }  

메이크 :

1 a:$ 
    2  g++ -fopenmp -Wall -o test -g test.cc$ 
    3  ./test$ 

내 질문은 : 실패하는이 프로그램을 야기 커널 3.6에 대해 다른이지만에 실패하지 않는 무엇 버전 3.5?

답변

1

코드를 거치지 않고 프로세스에 몇 가지 제한을 설정하려면 리소스 사용을 제한하기 위해 cgroups을 살펴보십시오.

얼어 붙음 - 한 번에 GB의 데이터를 디스크에 읽고 쓰려고합니다. 오늘 하드 드라이브의 ~ 100MB/s의 속도를 감안할 때, 커널이 디스크로 캐시를 플러시하기로 결정할 때 정지가 예상됩니다. 이는 합리적으로 크기가 큰 데이터 청크를 읽는 즉시 발생합니다 (메모리를 많이 할당 했으므로 캐시 공간이 제한적입니다.)

mmap() 파일을 시도하거나 커널 I/O 스케줄러를 변경할 수 있습니다.

+0

커널 입출력 스케줄러 변경에 대한 의견은 유용합니다. 나는 그것을 시도 할 것이다. 커널이 디스크 캐시를 플러시하려고 할 때 딸꾹질한다고 생각할 수 있지만, 앞에서 말한 것처럼 전체 시스템이 정지합니다. 몇 시간 동안이 상태로 유지되고 결국 재부팅해야합니다.그것은 내 마음에 더 심각한 문제를 나타냅니다. – jsp

+0

@jsp 예 참으로. 'SysRq' 기능을 활성화하여 시스템에서 무슨 일이 일어나고 있는지 알면 도움이 될 것입니다. 또한 네트워크 콘솔을 사용 가능하게 설정하거나 사용 가능한 경우 직렬 케이블을 사용하여 검사를 위해 로그를 다른 컴퓨터로 전송할 수 있습니다. 커널 수준에서 문제가 발생하면 커널 로그에서이를 볼 수 있어야합니다. cgroup을 사용하면 문제를 쉽게 찾을 수 있습니다. 또는 가상 시스템에서 응용 프로그램을 실행하고 무엇이 정지되는지 확인하십시오 : VM 또는 호스트. – peterph

+0

운이 좋지 않은 IO 스케줄링 알고리즘을 변경해 보았습니다. 아마도 numlock이 응답하고 ssh를 사용하여 로그 파일을 검사 할 수 있기 때문에 '정지'라고 말하면 안됩니다./var/log/messages 나 ~/.xsession-errors에는 관심이 없습니다. 그것이이 상태에있을 때 특정 프로그램이 실행되고 다른 프로그램은 매우 느리게 실행되며 일부 프로그램은 전혀 응답하지 않습니다. 3.5.X 커널에서 이러한 증상이 나타나지 않는다는 것을 나타 내기 위해 원래 질문을 변경했습니다. 문제는 3.6.X 커널에서만 발생합니다. – jsp

0

(적어도 나는 것은 그들이있어) 나는 깊은 당신의 코드를 들여다하지 않은,하지만 난 나쁜 관행을 실현 :

  • 첫째, OpenMP의 루프 내부의 critical 섹션을 참조하십시오. 그것은 동기 부여의 요점이며 모든 반복에서 그것을 넣는 것은 나에게 문제가되는 것처럼 들린다. 각 스레드는 다른 스레드가 입력되지 않았 음을 확인해야하므로 스레드의 수와 함께 동기화가 도입하는 오버 헤드가 증가 할 수 있습니다.

  • 두 번째 : 나는 C++에 익숙하지 않지만 언제든지 vector<char> a (SZ)이 실행될 때마다 메모리가 할당되고 (블록 끝에서 해제 됨) 추측합니다. 내가 틀렸다면 실례합니다. SZ의 값을 미리 알고 있기 때문에 병렬 영역 앞에 스레드와 같은 수의 요소로 vector<vector<char> >을 할당하는 것이 좋습니다. 그런 다음 병렬 영역에서 각 스레드가 해당 vector<char>에 액세스하게 만듭니다.

+0

중요한 부분은 로그 메시지가 서로 겹쳐 쓰지 않도록하는 것입니다. 네가 원한다면 나는 그것을 제거 할 수있다. – jsp

+0

아, 네. 그래서 그 중요한 영역이없는 버전에서 성능을 테스트 한 것 같습니다. 그러나 리소스와 같은 루프 내에서 리소스를 할당하고 해제하는 것에주의하십시오. 가능한 모든 메모리를 한 번만 할당하고 루프 이후에 메모리를 확보하십시오. –

관련 문제