Program Tip

! = 연산자가 OpenMP에서 허용되지 않는 이유는 무엇입니까?

programtip 2020. 11. 5. 18:51
반응형

! = 연산자가 OpenMP에서 허용되지 않는 이유는 무엇입니까?


다음 코드를 컴파일하려고했습니다.

#pragma omp parallel shared (j)
{
   #pragma omp for schedule(dynamic)
   for(i = 0; i != j; i++)
   {
    // do something
   }
}

이 오류가 발생합니다 : error : invalid controls predicate .

나는 openMP 참조 가이드를 확인하고 병렬에 대해 "만"다음 연산자 중 하나를 허용한다고 말합니다. <<=>> =.

허용하지 않는 이유를 이해할 수 없습니다 i != j. openMP는 각 스레드에 할당 된 반복 횟수를 미리 계산해야하므로 정적 일정인지 이해할 수있었습니다. 그러나 예를 들어 이러한 제한이 왜 그런지 이해할 수 없습니다. 단서가 있습니까?


편집 : for(i = 0; i != 100; i++)비록 내가 "<"또는 "<="를 넣을 수 있지만.


.

이 주제에 대해 OpenMP 개발자에게 이메일을 보냈습니다. 답은 다음과 같습니다.

signed int의 경우 랩 어라운드 동작은 정의되지 않습니다. 을 허용 !=하면 프로그래머는 예상치 못한 트립 카운트를 얻을 수 있습니다. 문제는 컴파일러가 루프의 트립 횟수를 계산하는 코드를 생성 할 수 있는지 여부입니다.

다음과 같은 간단한 루프의 경우 :

for( i = 0; i < n; ++i )

컴파일러는 n> = 0경우 'n'반복이 있고 n <0 인 경우 0 반복이 있는지 확인할 수 있습니다.

다음과 같은 루프의 경우 :

for( i = 0; i != n; ++i ) 

다시 말하지만, 컴파일러는 n> = 0경우 'n'반복이 있는지 확인할 수 있어야합니다 . n <0 이면 얼마나 많은 반복이 있는지 알 수 없습니다.

다음과 같은 루프의 경우 :

for( i = 0; i < n; i += 2 )

컴파일러는 트립 수 (루프 반복 카운트)를 계산하는 코드를 생성 할 수있는 층 ((N + 1) / 2) 만약 N> = 0 , 0 의 경우 N <0 .

다음과 같은 루프의 경우 :

for( i = 0; i != n; i += 2 )

컴파일러는 'i'가 'n'을 누를 지 여부를 결정할 수 없습니다. 'n'이 홀수이면 어떻게 되나요?

다음과 같은 루프의 경우 :

for( i = 0; i < n; i += k )

컴파일러는 루프가 카운트 업해야 함을 알고 있기 때문에 컴파일러가 트립 카운트를 floor ((n + k-1) / k) 로 계산하는 코드를 생성 할 수 있습니다. n> = 0이면 0 이고, n <0이면 0입니다 . 이 경우 k <0 이면 합법적 인 OpenMP 프로그램이 아닙니다.

다음과 같은 루프의 경우 :

for( i = 0; i != n; i += k )

컴파일러는 내가 카운트 업인지 다운인지조차 알지 못합니다. 'i'가 'n'을 누를 지 여부는 알 수 없습니다. 무한 루프 일 수 있습니다.

크레딧 : OpenMP ARB


모양과 달리 schedule(dynamic)동적 요소 수에서는 작동하지 않습니다. 오히려 스레드에 반복 블록을 할당하는 것이 동적입니다. 정적 스케줄링을 사용하면이 할당은 작업 공유 구성의 시작 부분에서 미리 계산됩니다. 동적 스케줄링을 통해 반복 블록은 선착순으로 스레드에 제공됩니다.

OpenMP 표준은 작업 공유 구조가 발견되면 반복 횟수가 미리 계산된다는 점이 매우 분명합니다. 따라서 루프 카운터는 루프 본문 내에서 수정되지 않을 수 있습니다 (OpenMP 3.1 사양, §2.5.1-루프 구성) :

연결된 각 루프의 반복 횟수는 가장 바깥 쪽 루프에 들어가기 전에 계산됩니다. 연관된 루프를 실행하면 반복 횟수를 계산하는 데 사용되는 값이 변경되면 동작이 지정되지 않습니다.

축소 된 루프의 반복 횟수를 계산하는 데 사용되는 정수 유형 (또는 Fortran의 경우 종류)이 구현 정의됩니다.

작업 공유 루프에는 0,1, ..., N-1 번호가 매겨진 논리적 반복이 있습니다. 여기서 N은 루프 반복 횟수이고 논리적 번호 매기기는 연관된 루프가 실행 된 경우 반복이 실행되는 순서를 나타냅니다. 단일 스레드로. schedule절은 연관된 루프의 반복이 청크라고하는 연속적인 비어 있지 않은 서브 세트로 분할되는 방법과 이러한 청크가 팀의 스레드간에 분배되는 방법을 지정합니다. 각 스레드는 암시 적 작업의 컨텍스트에서 할당 된 청크를 실행합니다. 수 chunk_size의 발현이 루프 구조에서 비공개로되어있는 변수의 원래 목록 항목을 이용하여 평가된다. 이 표현식 평가의 부작용이 어떤 순서로 또는 몇 번으로 발생하는지 여부는 지정되지 않습니다. 변수 사용schedule 루프 구문의 절 표현식은 모든 둘러싸는 구문의 변수에 대한 암시 적 참조를 발생시킵니다.

이러한 관계형 연산자 제한의 근거는 매우 간단합니다. 루프의 방향에 대한 명확한 표시를 제공하고 반복 횟수를 쉽게 계산할 수 있으며 C / C ++ 및 Fortran에서 OpenMP 작업 공유 지시문과 유사한 의미를 제공합니다. . 또한 다른 관계형 연산은 루프가 어떻게 진행되는지 이해하기 위해 루프 본문을 면밀히 검사해야합니다. 이는 많은 경우에 수용 할 수없고 구현을 번거롭게 만듭니다.

OpenMP 3.0 task은 반복 횟수를 알 수없는 루프의 병렬화를 허용 하는 명시 적 구조를 도입했습니다 . 하지만 문제가 있습니다. 작업은 심각한 오버 헤드를 유발하고 루프 반복 당 하나의 작업은 이러한 반복이 실행되는 데 시간이 많이 걸리는 경우에만 의미가 있습니다. 그렇지 않으면 오버 헤드가 실행 시간을 지배합니다.


대답은 간단합니다. OpenMP는 스레드 팀의 조기 종료를 허용하지 않습니다. == 또는! =를 사용하면 OpenMP는 루프가 중지되는시기를 확인할 수 없습니다. 1. 하나 이상의 스레드가 고유하지 않은 종료 조건에 도달 할 수 있습니다. 2. OpenMP는 조건을 감지하지 못할 수있는 다른 스레드를 종료 할 방법이 없습니다.


성명서를 보면

for(i = 0; i != j; i++)

문 대신 사용

for(i = 0; i < j; i++)

I would be left wondering why the programmer had made that choice, never mind that it can mean the same thing. It may be that OpenMP is making a hard syntactic choice in order to force a certain clarity of code.

Here's code which raises challenges for the use of != and may help explain why it isn't allowed.

#include <cstdio>

int main(){
    int j=10;
   #pragma omp parallel for
   for(int i = 0; i < j; i++){
    printf("%d\n",i++);
   }
}

notice that i is incremented in both the for statement as well as within the loop itself leading to the possibility (but not the guarantee) of an infinite loop.

If the predicate is < then the loop's behavior can still be well-defined in a parallel context without the compiler having to check within the loop for changes to i and determining how those changes will affect the loop's bounds.

If the predicate is != then the loop's behavior is no longer well-defined and it may be infinite in extent, preventing easy parallel subdivision.


I think there is perhaps no good reason other than having extended existing functionality to get this far.

IIRC originally these had to be static so that it could determine at compile time how to generate the loop code... it could just be a hangover from that.

참고URL : https://stackoverflow.com/questions/13312679/why-is-the-operator-not-allowed-with-openmp

반응형