C++ std算法的并行实现及其副作用

C++ std算法的并行实现及其副作用,c++,algorithm,c++11,C++,Algorithm,C++11,翻阅std::transform的标准文档时,我注意到,在C++11之前,函子参数要求没有副作用,而从C++11开始,要求的限制性就降低了——“op和binary_op不得使迭代器或子范围无效,或修改范围中的元素”。看 以及本标准第25.3.4节。cppreference.com上的网页也提到“这些要求的目的是允许并行或无序实现std::transform” 我不明白这段代码在C++11中是否合法: std::vector<int> v(/* fill it with someth

翻阅
std::transform
的标准文档时,我注意到,在C++11之前,函子参数要求没有副作用,而从C++11开始,要求的限制性就降低了——“op和binary_op不得使迭代器或子范围无效,或修改范围中的元素”。看

以及本标准第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::vector v(/*用某物填充它*/),v_转换;
int-foo=0;
std::transform(v.begin()、v.end()、std::back_插入器(v_transformed),[&foo](const int&n)->int{
foo+=1;
返回n*2;
});
显然,如果
std::transform
在后台并行化,我们将有多个并发调用
foo+=1
,这将是UB。但是函子本身似乎没有违反标准中概述的要求

其他标准算法也可以问这个问题(除了我认为
std::for_each
,它明确指出迭代是按顺序执行的)


我误解了什么吗?

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

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

就我所理解的C++11规范而言,所有标准库函数都必须按顺序执行所有操作,如果它们的效果对用户可见。特别是,所有“突变序列操作”都必须按顺序执行

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

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


这在哪里保证?像OP一样,我找不到它,除了
for_each
(事实上,我觉得有必要为
for_each
指定它,这一直向我暗示,否则这不是一个要求)。我初步的理解是
for_each
可以有力地保证事情按照一定的顺序完成(我认为这也排除了并发实现),而对于其他算法,迭代可能是无序的和并发的。但鉴于对函子的要求有限,并发实现需要能够证明函子没有副作用(例如,可能它可以在标准库中明确专门化函子,如
std::plus
,等等).我刚刚使用gcc 4.8.2生成了这个程序集,没有使用任何优化和
-O2
巨大的差异几乎就是你的问题..但是作为NADMWid结束了:谢谢,这真的很有帮助!将答案标记为已接受。