以下简单代码未提供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
从lambda函数的减少。顺便说一句,我期望结果是串行函数返回的结果
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()
给出了不同的结果编译器错误或正确吗?
答案 0 :(得分:7)
我认为这不是编译器错误。这是我的解释。我想在你的第一个例子中,lambdas持有对全局c
变量的引用。我们进入for循环时创建了c
的线程本地副本。因此线程正在递增相同的全局变量(没有任何同步)。当我们退出循环时,c
的线程局部副本(全部等于零,因为lambdas不知道它们)总结为0。count_ok2
版本有效,因为lambdas正在保留对本地c
份副本的引用。