prosource

openmp의 collapse 절 이해

probook 2023. 6. 17. 09:28
반응형

openmp의 collapse 절 이해

저는 collapse 절이 있는 OpenMP 코드를 발견했는데, 이것은 저에게 새로운 것이었습니다.저는 그것이 무엇을 의미하는지 이해하려고 노력하고 있지만, 저는 그것의 의미를 완전히 이해하지 못했다고 생각합니다. 제가 찾은 한 가지 정의는 다음과 같습니다.

접기:중첩된 루프에서 하나의 큰 반복 공간으로 축소하고 일람표 절에 따라 분할할 루프 수를 지정합니다.연관된 모든 루프에서 반복의 순차적 실행은 축소된 반복 공간에서 반복의 순서를 결정합니다.

저는 그것이 무엇을 의미하는지 이해한다고 생각했기 때문에 다음과 같은 간단한 프로그램을 시도했습니다.

int i, j;
#pragma omp parallel for num_threads(2) private(j)
for (i = 0; i < 4; i++)
    for (j = 0; j <= i; j++)
        printf("%d %d %d\n", i, j, omp_get_thread_num());

제작한 것은

0 0 0
1 0 0
1 1 0
2 0 0
2 1 0
2 2 1
3 0 1
3 1 1
3 2 1
3 3 1

그리고 나서 다음을 추가했습니다.collapse(2) 가 나올 했는데, 은 같은 ②번이 나옵니다.0의 모래1가 마지막 열에 있습니다.하지만 나는

0 0 0
1 0 0
2 0 1
3 0 1

그래서 제 질문은 다음과 같습니다.

  1. 내 코드에서 무슨 일이 발생합니까?
  2. 에서 떤어상사합니까용야해서를 사용해야 ?collapse?
  3. 를 사용하는 것의 차이점을 보여주는 예를 제공할 수 있습니까?collapse사용하지 않는 것이 좋습니까?

코드의 문제는 내부 루프의 반복이 외부 루프에 의존한다는 것입니다. 및 사양에 collapse절:

연결된 루프를 실행하면 반복 횟수를 계산하는 데 사용되는 값이 변경되면 동작이 지정되지 않습니다.

예를 들어 사각 루프의 경우가 아닌 경우 축소를 사용할 수 있습니다.

#pragma omp parallel for private(j) collapse(2)
for (i = 0; i < 4; i++)
    for (j = 0; j < 100; j++)

사실 이것은 축소를 사용하는 시기를 보여주는 좋은 예입니다.외부 루프에는 네 번의 반복만 있습니다.4개 이상의 스레드가 있으면 일부 스레드가 낭비됩니다.그러나 접으면 스레드 수보다 훨씬 많을 가능성이 높은 400번의 반복으로 스레드가 분산됩니다.축소를 사용하는 또 다른 이유는 부하가 잘 분산되지 않은 경우입니다.네 번의 반복만 사용하고 네 번째 반복은 다른 스레드가 대기하는 데 대부분의 시간이 소요되었습니다.그러나 400회 반복을 사용하면 부하가 더 잘 분산될 가능성이 높습니다.

위의 코드에 대한 루프를 다음과 같이 손으로 융합할 수 있습니다.

#pragma omp parallel for
for(int n=0; n<4*100; n++) {
    int i = n/100; int j=n%100;

다음은 트리플 퓨즈 루프를 손으로 퓨즈를 사용하는 방법을 보여주는 입니다.

마지막으로, 여기 삼각 루프를 융합하는 방법을 보여주는 예가 있습니다.collapse에 대해 정의되지 않았습니다.


OPS 질문에서 직사각형 루프를 삼각 루프에 매핑하는 솔루션이 있습니다.OPS 삼각 루프를 퓨즈로 연결하는 데 사용할 수 있습니다.

//int n = 4;
for(int k=0; k<n*(n+1)/2; k++) {
    int i = k/(n+1), j = k%(n+1);
    if(j>i) i = n - i -1, j = n - j;
    printf("(%d,%d)\n", i,j);
}

이것은 n의 모든 값에 대해 작동합니다.

OPs 질문에 대한 지도는 다음과 같습니다.

(0,0),
(1,0), (1,1),
(2,0), (2,1), (2,2),
(3,0), (3,1), (3,2), (3,3),

로.

(0,0), (3,3), (3,2), (3,1), (3,0),
(1,0), (1,1), (2,2), (2,1), (2,0),

n의 홀수 값에 대해서는 맵이 정확히 직사각형은 아니지만 공식은 여전히 작동합니다.

예를 들어, n = 3은 다음에서 매핑됩니다.

(0,0),
(1,0), (1,1),
(2,0), (2,1), (2,2),

로.

(0,0), (2,2), (2,1), (2,0),
(1,0), (1,1),

이것을 테스트하기 위한 코드가 있습니다.

#include <stdio.h>
int main(void) {
    int n = 4;
    for(int i=0; i<n; i++) {
        for(int j=0; j<=i; j++) {
            printf("(%d,%d)\n", i,j);
        }
    }
    puts("");
    for(int k=0; k<n*(n+1)/2; k++) {
        int i = k/(n+1), j = k%(n+1);
        if(j>i) i = n - i - 1, j = n - j;
        printf("(%d,%d)\n", i,j);
    }
}

각 항목의 워크로드가 규칙적이거나 잘 분산되어 있다고 가정하여 증가하는 행에 대한 로드 균형을 조정하는 것이 목적이라면 행 인덱스를 반으로 접고 다음과 같은 작업을 수행하지 않는 것이 좋습니다.collapse조항?

#pragma omp for
for (int iy0=0; iy0<n; ++iy0){
  int iy = iy0;
  if (iy0 >= n/2) iy = n-1 -iy0 +n/2;
  for (int ix=iy+1; ix<n; ++ix){
    work(ix, iy);
  }
}

언급URL : https://stackoverflow.com/questions/28482833/understanding-the-collapse-clause-in-openmp

반응형