std算法和副作用的并行实现

时间:2013-11-21 11:31:42

标签: c++ algorithm c++11

通过std::transform的标准文档,我注意到在C ++ 11之前,仿函数参数不需要有副作用,而从C ++ 11开始,要求的限制性就越来越少 - “ op和binary_op不应使迭代器或子范围无效,或修改范围中的元素“。参见

http://en.cppreference.com/w/cpp/algorithm/transform

和标准的第25.3.4节。 cppreference.com上的网页还提到“这些要求的目的是允许std::transform的并行或无序实现”。

我不明白这段代码在C ++ 11中是否合法:

std::vector<int> v(/* fill it with something */), v_transformed;
int foo = 0;
std::transform(v.begin(),v.end(),std::back_inserter(v_transformed),[&foo](const int &n) -> int {
    foo += 1;
    return n*2;
});

显然,如果std::transform在幕后并行化,我们将有多个并发调用foo += 1,这将是UB。但是仿函数本身似乎没有违反标准中规定的要求。

这个问题可以被要求用于其他标准算法(除了我认为std::for_each,它明确指出迭代将按顺序执行)。

我误解了什么吗?

3 个答案:

答案 0 :(得分:3)

当前定义算法的方式必须按顺序执行,除非实现可以证明并发执行它不会改变语义。我可以想象未来的算法明显允许同时执行,但它们将是不同的算法。

答案 1 :(得分:3)

据我了解C ++ 11规范,如果用户可以看到它们的效果,则所有标准库函数都必须按顺序执行所有操作。特别是,所有“变异序列操作”必须按顺序执行。

标准的相关部分是§17.6.5.9/ 8:

  

除非另有说明,否则C ++标准库函数应仅在当前线程内执行所有操作,如果这些操作具有对用户可见的效果(1.10)。

答案 2 :(得分:0)

因此,C ++ 11现在允许std::transform并行化,但这并不能保证您自己的代码可以并行化。现在,是的,我想你必须保护你的数据变量。我可以想象很多由此产生的MT错误,如果实现实际上实际上并列std::transform