【问题标题】:Are some compiler optimizations invalid in the presence of multiple threads?在存在多个线程的情况下,某些编译器优化是否无效?
【发布时间】:2017-11-15 12:03:15
【问题描述】:

例如,假设我们有如下代码,其中d 是一个字典或其他数据结构,其索引并不重要:

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

优化编译器是否可以有效地将最后一行更改为return z + x

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

【问题讨论】:

  • 是的。让另一个线程修改值而不提供必要的同步是 UB。
  • @HansPassant +1 并且它必须是 UB,因为获取值 d[a] 可能需要几条指令,并且如果在中间中断会返回一半修改的数据
  • 直接支持线程(而不是作为附加组件)的语言必须在此处定义整个语义。将其作为插件的语言通常会提供某种插件同步或屏障操作,然后必须提供一种方法来确保编译器不会进行无效优化。例如,考虑提供线程本地存储的语言(您可以在其中声明 d 本身,也许 d 的所有存储项目都是线程本地的,因此优化是有效的)。
  • 只要这个问题被标记为[与语言无关],就无法提供有意义的答案。这是“太宽泛”的定义。每种语言都有不同的规范,可以或不能解释这一点,因此每种语言都允许优化器做不同的事情。

标签: multithreading compiler-construction language-agnostic compiler-optimization


【解决方案1】:

问题合并了多个问题。

1 : 线程

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

2:即使在确保没有线程的情况下,您具体提到的那种优化看起来也很困难。全面概括 ["non-trivial indexing"] :它要求优化器识别表达式之间的相等性。我怀疑大多数编译器都没有这样做,因为它需要运行时间。

【讨论】:

  • “因此编译器可能不知道存在多少线程。” 这怎么可能是真的?是编译器生成代码来创建线程,因此它当然知道有多少线程。 “这种优化……看起来很难……它需要优化器识别表达式之间的相等性。” 呃,C 和 C++ 编译器经常执行这样的优化。它并不像你想象的那么难,一旦你内联了样板代码并将所有内容折叠成抽象语法树。
  • @[Cody Gray] 编译器(至少是一个 C/C++ 编译器 - 不知道 JIT 编译器)无法判断正在运行的线程数,因为这仅在运行时才知道。
  • 这没有任何意义,@valiano。编译器必须发出启动线程的代码,因此它确切地知道已经启动了多少线程。您是在谈论不同应用程序中的线程吗?如果是这样,我看不出这与这个问题有什么关系。
  • @[Cody Gray] 编译器一次为一个函数发出代码,将内联放在一边。即使它知道在某个函数中启动的线程数,它也不能使用此信息来编译其他函数(即使可以,函数也可以在不同的时间编译,驻留在不同的库中,...)。编译器为线程做的所有事情就是生成汇编代码以符合您的线程和同步 C/C++ 代码 - 从这个意义上说,它不会添加任何自己的“智慧”。
  • @CodyGray,针对不同的输入执行程序的不同分支。在不同的分支上,线程的数量可能不同。
猜你喜欢
  • 2016-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 2020-11-11
  • 2019-12-27
  • 1970-01-01
相关资源
最近更新 更多