2013-08-01 3 views
3

std::tuple을 반복 할 수 있도록 다음 코드를 제공합니다. 코드는 여기에서 here입니다.openmp로 C++ 11 std :: tuple을 반복 할 수 있습니까?

#include <tuple> 
#include <utility> 

template<std::size_t I = 0, typename FuncT, typename... Tp> 
inline typename std::enable_if<I == sizeof...(Tp), void>::type 
for_each(std::tuple<Tp...> &, FuncT) // Unused arguments are given no names. 
{ } 

template<std::size_t I = 0, typename FuncT, typename... Tp> 
inline typename std::enable_if<I < sizeof...(Tp), void>::type 
for_each(std::tuple<Tp...>& t, FuncT& f) 
{ 
    f(std::get<I>(t)); 
    for_each<I + 1, FuncT, Tp...>(t, f); 
} 

지금, 나는 내가 for에 OpenMP를 사용할 수 있습니다 같은 방법으로, OpenMP와 함께이 for_each 루프를 실행하고 싶습니다. 이것을 가능하게하는 속임수가 있습니까?

참고 : 위의 코드를 수정하거나 다른 버전의 for_each을 사용할 수 있습니다.

+3

'for_each' "루프"가 표시되지 않습니다. 나는 재귀를 보는데, 이것은 재귀가 아니다. –

+0

@ NicolBolas 재귀는 추상적 인 의미에서 루프라고 할 수 있습니다. – Johannes

답변

2

는 C++ 11 템플릿 구문은 나에게 매우 외국인이지만, 이와 하나로서 재귀 문제가 가장 명시 적으로 OpenMP의 작업을 사용하여 평행하게 만들어 :

template<std::size_t I = 0, typename FuncT, typename... Tp> 
inline typename std::enable_if<I < sizeof...(Tp), void>::type 
for_each(std::tuple<Tp...>& t, FuncT& f) 
{ 
    #pragma omp task firstprivate(I) shared(t,f) 
    { 
     f(std::get<I>(t)); 
    } 
    for_each<I + 1, FuncT, Tp...>(t, f); 
} 

... 

// Proper usage 
#pragma omp parallel 
{ 
    #pragma omp single 
    for_each(...); 
} 

중요한 부분은 최고 수준의 호출을하는 것입니다 parallel 영역 내에있는 single 구조 내의 for_each으로 변환한다. 따라서 오직 하나의 쓰레드 만이 for_each을 호출 할 것이고, 나중에 f(std::get<I>(t));이 명시 적 태스크로서 나중에 실행되도록 대기하게 될 것입니다. single 구조의 끝 부분에있는 암시 적 장벽을 기다리는 동안 다른 스레드는 작업 큐에서 작업을 시작하고 큐가 비어있을 때까지 병렬로 실행합니다. 작업에서 사용되는 모든 변수의 공유 클래스는 명확하게하기 위해 명시 적으로 제공됩니다.

tf 참조가 공유되어야하는 객체와 참조 자체 (기본적으로 참조를 구현하는 포인터)는 먼저 사위되어야합니다. 다른면에서 OpenMP 표준은 참조 유형이 처음부터 공개되지 못하도록하고 다른 컴파일러 공급 업체는 표준을 다르게 구현하는 경향이 있습니다. (잘못이다) 인텔 C++ 컴파일러는 다음 코드를 받아서는 작업 안에 정확한 결과를 제공하지만, 참조 된 변수가 민영화되어

void f(int& p) 
{ 
    #pragma omp task 
    { 
     cout << "p = " << p << endl; 
     p = 3; 
     cout << "p' = " << p << endl; 
    } 
} 

void f1() 
{ 
    int i = 5; 

    #pragma omp parallel 
    { 
     #pragma omp single 
     f(i); 
    } 
    cout << "i = " << i << endl; 
} 

PGI의 컴파일러는 정확한 결과를 제공하고 i을 민영화하지 않습니다. 반면에 GCC는 pfirstprivate이어야한다고 결정하지만 표준에서 금지를 실행하고 컴파일 타임 오류가 발생합니다.

사람이 읽을 수있는 작업을 수정하는 경우 : 인텔 C++ 컴파일러 및 PGI의 C++ 컴파일러 모두 세그먼트 오류가 발생합니다 다음

#pragma omp task shared(p) 
{ 
    ... 
} 

는 GCC 제대로 작동하지만 p의 작업 인쇄 잘못된 초기 값합니다.

이동하십시오!

+0

감사합니다. 이 컴파일러는 http://pastebin.com/3jzNMCpu를 컴파일 할 수 없지만 컴파일러는 firstprivate에 대해 불평하고 나는 '나는 문제가 아니었다 고 말한 것 같습니까? 무엇이 잘못 될 수 있습니까? – Johannes

+1

C++ 템플릿에 대한 나의 지식만큼이나,'I'와 같은 템플릿 인자는 변수가 아닌 리터럴 상수처럼 취급되기 때문에'firstprivate' (또는 어떤 종류의 데이터 공유 절). –