次の単純なコードは、gcc 4.7.0 で期待される結果をもたらしません。これは正しいですか、それともバグですか?
unsigned count_err(std::vector<unsigned> const&num, unsigned mask)
{
unsigned c=0;
// enables to reuse the lambda later (not in this simple example)
auto f = [&] (unsigned i) { if(i&mask) ++c; };
#pragma omp parallel for reduction(+:c)
for(unsigned i=0; i<num.size(); ++i)
f(num[i]);
return c;
}
c
これはゼロを返します:ラムダ関数からの削減は行われません。ところで、結果はシリアル関数によって返されると予想していました
unsigned count_ser(std::vector<unsigned> const&num, unsigned mask)
{
unsigned c=0;
auto f = [&] (unsigned i) { if(i&mask) ++c; };
std::for_each(num.begin(),num.end(),f);
return c;
}
次の実装では、期待される結果が得られます (どちらの場合も、リダクション変数のインクリメントを行うコード定義は並列領域に移動されます)。
unsigned count_ok1(std::vector<unsigned> const&num, unsigned mask)
{
unsigned c=0;
auto f = [&] (unsigned i) -> bool { return i&mask; };
#pragma omp parallel for reduction(+:c)
for(unsigned i=0; i<num.size(); ++i)
if(f(num[i])) ++c;
return c;
}
unsigned count_ok2(std::vector<unsigned> const&num, unsigned mask)
{
unsigned c=0;
#pragma omp parallel reduction(+:c)
{
auto f = [&] (unsigned i) { if(i&mask) ++c; };
#pragma omp for
for(unsigned i=0; i<num.size(); ++i)
f(num[i]);
}
return c;
}
count_err()
異なる結果をもたらすという事実は、コンパイラのバグですか、それとも正しいですか?