[英]Can I iterate over a C++11 std::tuple with openmp?
我有以下代碼來迭代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_each
使用OpenMP循環,以同樣的方式,我可以使用OpenMP的上for
。 有沒有辦法讓這成為可能?
注意:您可以修改上述代碼或使用您自己的for_each
任何其他版本。
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
構造末尾的隱式屏障處等待時,將開始從任務隊列中拉出任務並並行執行它們,直到隊列為空。 為清楚起見,明確給出了任務使用的所有變量的共享類。
應該共享t
和f
引用的對象,並且引用本身(實際上是實現引用的指針)應該是firstprivate。 另一方面,OpenMP標准禁止引用類型為firstprivate,不同的編譯器供應商傾向於以不同方式實現該標准。 英特爾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正確地確定p
應該是firstprivate
但是然后進入標准中的禁止並且給出編譯時錯誤。
如果將任務修改為:
#pragma omp task shared(p)
{
...
}
它可以正常使用GCC但是任務打印錯誤的初始值p
然后導致英特爾C ++編譯器和PGI的C ++編譯器出現分段錯誤。
去搞清楚!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.