2012-08-13 3 views
1

대한 증가 I는 새로운 요소를 추가 p.l 때문에 DoSomething() 내부 p.n 증가하는 것도 가능하다 이제이 parallel for 루프의 OpenMP : 루프 반복 횟수

struct p 
{ 
    int n; 
    double *l; 
} 

#pragma omp parallel for default(none) private(i) shared(p) 
for (i = 0; i < p.n; ++i) 
{ 
    DoSomething(p, i); 
} 

있다. 이 요소들을 병렬 방식으로 처리하고 싶습니다. OpenMP 설명서에 의하면 parallel for은 목록과 함께 사용할 수 없으므로 DoSomething()은이 p.l의 새 요소를 순차적으로 처리 된 다른 목록에 추가 한 다음 p.l과 다시 결합합니다. 이 해결 방법이 마음에 들지 않습니다. 누구든지이 일을하는 더 깨끗한 방법을 알고 있습니까?

+0

얼마나 많은 작업이 있을지 알지 못하고 OpenMP가 작업을 생성한다고 어떻게 예상합니까? 요소가없는 요소에서 작업은 어떻게해야합니까? 그건 불가능한 일입니다. – bitmask

+0

모든 작업이 끝나면 조건을 다시 확인하고 새 요소가 생성되면 더 많은 작업을 시작하십시오. – Patrik

답변

3

동적 실행을 지원하는 구조가 OpenMP 3.0에 추가되었으며 task 구조입니다. 작업은 대기열에 추가 된 다음 가능한 한 동시에 실행됩니다. 샘플 코드는 다음과 같습니다.

#pragma omp parallel private(i) 
{ 
    #pragma omp single 
    for (i = 0; i < p.n; ++i) 
    { 
     #pragma omp task 
     DoSomething(p, i); 
    } 
} 

이렇게하면 새 병렬 영역이 생성됩니다. 스레드 중 하나가 for 루프를 실행하고 i의 각 값에 대해 새 OpenMP 태스크를 작성합니다. 각기 다른 DoSomething() 호출은 작업으로 변환되어 나중에 유휴 스레드 내에서 실행됩니다. 그러나 문제가 있습니다 : 작업 중 하나가 p.l에 새 값을 추가하면 작성자 스레드가 이미 for 루프를 종료 한 후에 발생할 수 있습니다. 이것은 작업 동기화 구조와 같은 외부 루프를 사용하여 고정 할 수있다 :

#pragma omp single 
{ 
    i = 0; 
    while (i < p.n) 
    { 
     for (; i < p.n; ++i) 
     { 
     #pragma omp task 
     DoSomething(p, i); 
     } 
     #pragma omp taskwait 
     #pragma omp flush 
    } 
} 

taskwait 구조는 모든 작업이 실행되는 대기 때까지 스레드가 대기 할 수 있습니다. 새로운 요소가 목록에 추가되면 while의 조건이 다시 true로 설정되고 새로운 작업 생성 라운드가 발생합니다. flush 구조는 스레드 사이에서 메모리보기를 동기화하는 것으로 가정됩니다. 최적화 된 레지스터 변수를 공유 스토리지의 값으로 업데이트하십시오.

OpenMP 3.0은 OpenMP 2.0에서 멈춘 MSVC를 제외한 모든 최신 C 컴파일러에서 지원됩니다.

+0

한 번해볼 가치가 있습니다. 당신의 대답이 내가 원하는 것에 가장 가깝기 때문에 시도해 보겠습니다. – Patrik

+0

어딘가에 #pragma omp 병렬이 필요하지 않습니까? – Patrik

+0

두 번째 코드 예제는 내부 '단일'구문 만 제공합니다. 여전히 외부 '평행'영역이 필요합니다. –