2017-12-08 22 views
0

현재 대형 데이터 세트에서 작동하는 코드가 있으며 끝에 배열이 생성됩니다. 이 배열은 전역 버퍼에 추가되어야하고 이것은 모두 루프 안에서 발생합니다. 예 :openmp에서 작업으로 알고리즘 설계

for(i=0;i<10000;i++) 
{ <1. do some processing, generate a 1M-sized array> 
    <2. update this array into global buffer> 
} 

작업 1은 GPU에서 발생, 나는 두 번째 부분은 CPU, 즉 한 스레드가 작업 1의 GPU를 제어하고, 1 개 버퍼가 준비되면 다른 모든 스레드가 작업을 2 할 위치에 평행하게 발생 할 처리를 위해. 기본 사례의 경우 하나의 버퍼 사본 (GPU 사본과 GPU 사본)을 사용하여 어떻게해야합니까?

+0

실제로 두 가지가 필요합니다. 가능한 경우 단계 1을 2 단계와 병렬로 만들고 멀티 스레드 2 단계를 수행하십시오. b/w 1 단계와 2 단계를 병렬화하려면 몇 가지 동기화가 필요합니다. 따라서 2 단계에서 새 버퍼가 생성되고 1 단계에서 이전 버퍼를 덮어 쓸 수 있음을 알 수 있습니다. 2 단계는 1M 크기의 배열 요소를 요소로 처리하고 일부 조건을 충족하는 경우 추가해야하는 전역 버퍼 배열에서 적절한 위치를 찾기 위해 계산을 수행 한 다음 추가합니다 . – udyank

답변

0

수행 할 수있는 작업은 생산자 - 소비자가 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 단계 자체를 병렬 처리 할 수 ​​있습니다.