0

例如,假设我们有像下面的代码,其中d是一个字典或其它数据结构针对索引是非平凡:在多线程的情况下,某些编译器优化是否无效?

x = d[a] 
y = d[b] 
z = (x + y) * (x + y) 
return z + d[a] 

可能会优化编译器的最后一行有效地改变到return z + x

如果是这样,这个优化在多线程的情况下是无效的吗?当该线程正在计算z的值时,如果另一个线程更改了d[a]的值(甚至是类型),会发生什么情况?

+1

是的。 UB有另一个线程修改值而不提供必要的同步。 –

+0

@HansPassant +1,它必须是UB,因为获取值d [a]可能需要几条指令,并且如果在中间被中断,将返回一半修改后的数据 –

+0

直接支持线程的语言(而不是作为附加组件)必须在这里定义整个语义。将它作为附加组件的语言通常会提供某种附加同步或屏障操作,然后必须提供一种方法来确保编译器不会进行无效优化。考虑一下,例如,提供线程本地存储的语言(你可以声明d本身,也许所有存储的项目都是线程本地的,因此优化是有效的)。 – torek

回答

0

这个问题合并了多个。

1:线程

在运行时创建。因此编译器可能不知道有多少线程存在。他们假定多个线程可以随时出现。因此,这组优化不受程序级别的线程数量的影响。但是,是的,它在编译器级受到影响。编译器必须考虑到数据竞争的威胁。至少对于较老的编程语言。在现代编程语言技术中,这个问题处理的是静态类型系统的强度[见Rust]functional purity

2:即使在确保没有穿线的情况下,您具体提到的优化类型看起来也很困难。在其完整的普遍性[“非平凡索引”中]:它要求优化器识别表达式之间的等式。我怀疑这在大多数编译器中并没有完成,因为它需要运行时间。

+0

*“因此,编译器可能不知道有多少线程存在。”*这怎么可能是真的?编译器生成代码来创建线程,因此它肯定知道有多少。 *“这种优化......看起来很难......它要求优化器识别表达式之间的等式。”*呃,C和C++编译器会定期执行这样的优化。它并不像你想象的那么困难,并不是你一旦将样板代码内联并将所有东西压缩到抽象语法树中。 –

+0

@ [Cody Gray]编译器(至少是C/C++编译器 - 不知道JIT编译器)不能分辨正在运行的线程的数量,因为这只在运行时才被知道。 – valiano

+0

@valiano,这没有任何意义。编译器必须发出启动线程的代码,因此它确切知道已启动了多少个线程。你是否正在讨论*不同应用程序中的线程*?如果是这样,我看不出与这个问题有什么关系。 –

相关问题