在理论上,C ++实现是否可以并行处理两个函数参数的评估?
给定以下函数调用:
f(g(), h())
因为函数参数的求值顺序是未指定的(就我所知,仍然是C ++ 11中的情况),理论上可以并行执行g()
和h()
吗?
这种平行化只能在g
和h
被认为是相当平凡的(在最明显的情况下,只访问他们身体本地的数据),以避免引入并发问题,但除此之外,我看不到什么禁止它。
那么,标准允许吗? 即使只通过as-if规则?
(在这个答案中 ,曼卡塞尔否认了这一点 ,但是他没有引用这个标准,而且我对[expr.call]
也没有显示出任何明显的措词。
要求来自[intro.execution]/15
:
…当调用一个函数时…在执行被调用函数的主体之前或之后,调用函数中的每个评估(包括其他函数调用)都没有被特定的sorting,所谓的函数[脚注: 换句话说,函数执行不会相互交错。 ]。
所以g()
的主体的任何执行都必须用h()
(因为h()
是调用函数中的一个expression式)的评估(即不重复g()
进行不确定的sorting。
这里的关键是g()
和h()
都是函数调用。
(当然,as-if规则意味着不可能完全排除这种可能性,但决不应该以某种可能影响程序可观察行为的方式发生,这种实现最多只会改变代码。)
只要你不知道,编译器做什么来评估这些函数完全取决于编译器。 显然,function的评估不能涉及任何访问共享的,可变的数据,因为这将引入数据竞赛。 基本的指导原则是“仿佛”规则和基本可观察的操作,即对volatile
数据的访问,I / O操作,对primefaces数据的访问等。相关部分是1.9 [intro.execution]。
除非编译器确切地知道g()
, h()
和他们所调用的任何东西。
这两个expression式是函数调用,可能有未知的副作用。 因此,将其并行化可能会导致数据竞争。 由于C ++标准不允许参数评估引起expression式的任何副作用的数据竞争,所以如果编译器知道没有这种数据竞争是可能的,则它们只能并行化它们。
这意味着通过遍历每个函数,看看它们究竟是做什么和/或调用什么,然后通过这些函数进行跟踪等。在一般情况下,这是不可行的。
简单的答案:当functionsorting时 ,即使不确定,两者之间也不可能出现竞争状态,如果它们是并行的,则不是这样。 即使是一对“平凡”的function也可以做到。
void g() { *p = *p + 1; } void h() { *p = *p - 1; }
如果p
是由g
和h
共享的名称,则以任意顺序连续调用g
和h
将导致p
指向的值不变。 如果它们是并行的,那么*p
的读取和它的分配可以在两者之间任意交错:
-
g
读取*p
并find值1。 -
f
读取*p
并且find值1。 -
g
写2到*p
。 -
f
,仍然使用前面读取的值1将0写入*p
。
因此,并行化时的行为是不同的。