수행 할 수있는 작업은 생산자 - 소비자가 1 단계에서 버퍼를 생성하고 2 단계에서 해당 버퍼를 소비하면서 결과를 전체 배열에 통합하는 것입니다. (통상 parallel
+ single
내부) 등
뭔가 :
const int buffer_size = 100000;
type global[buffer_size];
type buffer[2][buffer_size];
for(int i=0;i<10000;i++)
{
type *buf[buffer_size] = buffer[i % 2];
#pragma omp task depend(out: [buffer_size]buf)
{
<1. write to buf>
}
#pragma omp task depend(in: [buffer_size]buf) depend(inout: [buffer_size]global)
{
<2. update global using buf>
}
}
이 "지연"중 하나 개를 반복하여, 1 단계와 2 단계를 중첩 할 수 있도록, 즉, I = 1 것 반복 단계 1 동시에 2 단계의 반복 i = 0으로 실행하십시오. 반복 연산마다 하나의 버퍼가 필요하므로 각 동시 연산은 서로 독립적으로 발생할 수 있습니다.
이제는 간단한 procuder-consumer 관계이므로 buf (in
/out
)의 의미가 간단합니다. 현재 위치에서 버퍼를 업데이트 할 때 글로벌 주소가 inout
이되어야합니다. 현재 배열 (in
)을 가져오고 새 값을 할당합니다 (out
). 이것은 2 단계의 모든 작업이이 종속성으로 인해 직렬화된다는 것을 의미합니다. 즉, 최대 2 번의 반복이 겹칠 수 있으며 (2 개 이상의 버퍼를 사용할 필요가 없음) 의미합니다.
이것은 현재 OpenMP (4.5) 작업의 제한 사항입니다. 그러나이 문제를 해결할 수있는 a proposal for task reductions이 있습니다. 또 다른 방법은 전역을 shared
으로 선언하는 것입니다.이 경우 원자 적 조작을 사용하여 수정해야합니다.
target
절을 사용하여 GPU에서 작업 1을 실행할 수 있습니다. 오프로드 된 장치 (예 : GPU)의 데이터가 CPU에 복사되었는지 확인하십시오. 2 단계의 태스크 안에서, 병렬 for 구조 또는 태스크를 사용하여 2 단계 자체를 병렬 처리 할 수 있습니다.
실제로 두 가지가 필요합니다. 가능한 경우 단계 1을 2 단계와 병렬로 만들고 멀티 스레드 2 단계를 수행하십시오. b/w 1 단계와 2 단계를 병렬화하려면 몇 가지 동기화가 필요합니다. 따라서 2 단계에서 새 버퍼가 생성되고 1 단계에서 이전 버퍼를 덮어 쓸 수 있음을 알 수 있습니다. 2 단계는 1M 크기의 배열 요소를 요소로 처리하고 일부 조건을 충족하는 경우 추가해야하는 전역 버퍼 배열에서 적절한 위치를 찾기 위해 계산을 수행 한 다음 추가합니다 . – udyank