2014-11-29 2 views
0

루프를 순차적으로 반복하는 OpenMP 프로그램을 만들려고합니다. 스레드가 순차 프로그램을위한 것이 아니라는 것을 알았습니다. 단일 스레드에 비해 속도가 약간 빨라지거나 적어도 단일 스레드 프로그램과 비슷한 실행 시간을 유지하려고합니다.openmp 주문 중요 섹션

내 #pragma omp parallel 섹션에서 각 스레드는 큰 배열의 자체 섹션을 계산하고 그 부분의 합계를 가져옵니다. 이것들은 모두 병렬로 실행될 수 있습니다. 그런 다음 스레드가 순서대로 실행되도록하고 각 합계를 TotalSum IN ORDER에 추가합니다. 따라서 스레드 1은 스레드 0이 완료 될 때까지 기다려야합니다. 이 부분은 #pragma omp critical 섹션 안에 있습니다. 스레드 0 만 완료되고 프로그램이 종료된다는 것을 제외하고는 모두 정상적으로 실행됩니다. 다른 스레드가 폴링을 유지하도록하려면 어떻게해야합니까? sleep()과 while 루프를 시도했지만 스레드 0이 완료된 후에도 계속 종료됩니다.

각 스레드가 액세스하는 마스터 배열의 특정 범위를 추적해야하기 때문에 #pragma omp parallel을 사용하지 않습니다. 다음은 해당 코드 섹션의 단축 버전입니다.

//DONE and MasterArray are global arrays. DONE keeps track of all the threads that have completed 

int Function() 
{ 
    #pragma omp parallel 
    { 
    int ID = omp_get_thread_num 
    variables: start,end,i,j,temp(array) (all are initialized here) 
    j = 0; 

    for (i = start; i < end; i++) 
    { 
     if(i != start) 
       temp[j] = MasterArray[i]; 
     else 
       temp[j] = temp[j-1] + MasterArray[i]; 
     j++; 
    } 



    #pragma omp critical 
    {  
     while(DONE[ID] == 0 && ERROR == 0) { 

      int size = sizeof(temp)/sizeof(temp[0]);   

      if (ID == 0) { 
       Sum = temp[size]; 
       DONE[ID] = 1; 
       if (some situation) 
       ERROR = 1; //there's an error and we need to exit the function and program 
      } 
      else if (DONE[ID-1] == 1) { 
       Sum = temp[size]; 
       DONE[ID] = 1; 
       if (some situation) 
       ERROR = 1; //there's an error and we need to exit the function and program 
      } 
     } 
    } 
    } 
    if (ERROR == 1) 
     return(-1); 
    else 
     return(0); 
    } 

이 함수는 스레드 수를 초기화 한 후 main에서 호출됩니다. 병렬 부분이 완료되면 오류가 있는지 확인합니다. 오류가 발견되면 루프가 종료됩니다. 나는 여기서 무엇인가 잘못되었다는 것을 깨닫는다. 그러나 나는 그것이 무엇인지 알 수 없다. 그리고 지금 나는 단지 서클에 들어갔다. 어떤 도움이라도 좋을 것입니다. 다시, 제 문제는 스레드 0 만 실행 한 후에 함수가 종료되지만 오류가 플래그되지 않았기 때문입니다. 나는 그것을 pthreads에서도 실행하고 있지만, 실행하기가 더 간단합니다. 감사합니다.

답변

1

#pragma omp critical으로 스레드를 주문하려는 시도가 완전히 잘못되었습니다. 중요한 섹션에는 언제든지 스레드가 하나만있을 수 있으며 스레드가 중요한 섹션에 도착하는 순서는 결정되지 않습니다. 그래서 코드에서 일어날 수 있습니다. 스레드 # 2는 중요한 섹션에 먼저 들어가고 절대로 떠나지 않고 스레드 # 1이 완료 될 때까지 기다리고 나머지 스레드는 #pragma omp critical에서 대기합니다. 그리고 일부 스레드 (예 : 스레드 # 0은 중요한 부분을 올바른 순서로 완료하는 데 운이 좋고, 병렬 영역의 끝 부분에있는 암시 적 장벽을 기다리게됩니다. 즉,이 코드에서는 교착 상태가 거의 보장됩니다.

스레드를 주문하는 것이 훨씬 간단하고 자연 스럽다는 것을 제안합니다.

#pragma omp parallel 
{ 
    int ID = omp_get_thread_num(); 

    // Computations done by each thread 

    #pragma omp for ordered schedule(static,1) 
    for(int t=0; t<omp_get_num_threads(); ++t) 
    { 
     assert(t==ID); 
     #pragma omp ordered 
     { 
      // Do the stuff you want to be in order 
     } 
    } 
} 

따라서 영역의 스레드 수와 동일한 반복 수를 사용하여 병렬 루프를 만듭니다. schedule(static,1) 절은 스레드 ID 순서대로 스레드마다 하나씩 반복을 지정한다는 것을 명시 적으로 나타냅니다. ordered 절을 사용하면 루프 내부에서 정렬 된 섹션을 사용할 수 있습니다. 이제 루프 본문에 순서가 지정된 섹션 (#pragma omp ordered 다음 블록)을 넣고 iteration의 순서대로 실행됩니다.이 순서는 스레드 ID의 순서 (어설 션에 의해 보장 된 순서)이기도합니다.

자세한 내용은 다음 질문을 참조하십시오. How does the omp ordered clause work?

+0

제안에 감사드립니다. 나는 그것을 완료했으며 이제 모든 스레드를 성공적으로 완료합니다. 각 스레드의 로컬 변수에 대해 우려하고 있습니다. 변수가 임계 영역에 진입 할 때 기본적으로 각 스레드에 해당 변수가 비공개로 유지됩니까? 또는 for 루프에서 private 변수로 선언해야합니까? – user3938558

+0

확실하지는 않지만 병렬 영역에 대한 지역 변수와 개인 변수는 해당 지역의 작업 공유 구성 요소에서 비공개로 유지된다고 가정하십시오. 나는 OpenMP 사양에서 그걸 찾아 내려했지만 실패했다.아마도 이러한 변수를 루프에 대해 비공개로 선언하는 것은 아무런 해가 없습니다. 단지 안전한 측면에 있기만하면됩니다. –