【问题标题】:Delphi concurrency memory model?Delphi并发内存模型?
【发布时间】:2012-10-16 14:53:48
【问题描述】:

在 Delphi 中是否有类似 Java Memory Model 的东西?为了防止误解:我的意思不是“巨大/大/小”之类的东西,而是与其他线程更改的可见性有关的事情。

【问题讨论】:

  • @David Heffernan:如果事情这么简单,就不需要内存模型了。 amd64 架构不保证在没有特殊指令的情况下可以正常访问内存。在多核系统上,不能保证线程会永远看到运行在不同内核上的线程在内存中所做的任何更改,除非您正在使用volatile 或进行一些同步。这确实发生了,而且很常见。
  • x86 和 x64 有强内存模型:herbsutter.com/2012/08/02/… 至于volatile,我很清楚,虽然根据你使用的编译器,它有很多不同的含义。但是既然你说的是Delphi,这里就没有意义了。我的理解是,对于 volatile 的一些适当定义,Delphi 使非局部变量 volatile!
  • 如果 Intel/AMD “弱化” x86/x64 指令集的现有内存模型,地球上的每个应用程序和操作系统都会崩溃。它们只能“削弱”现有代码和编译器不使用的新指令或新执行模式的内存语义。英特尔和 AMD 非常了解“选择加入”。
  • 我不能评论当前的 Delphi 编译器的东西,但我可以非常坚持 Intel/AMD 硬件。 :>
  • @dthorpe 你能评论一下 D6 编译器吗?我知道当前的 32 位编译器在这个领域几乎没有区别。

标签: java delphi concurrency


【解决方案1】:

我会说 Delphi 内存模型与 C++ 内存模型相匹配。也就是说,编译器不知道多进程或多线程,也不为这些场景提供任何特殊支持。见"What is the C++ memory model for concurrency?"

Delphi 32 位编译器确实执行了诸如不变代码运动之类的优化,并且确实发出了旨在避免双流水线停滞的指令序列。但是,Delphi 编译器不包含指令调度程序或窥孔优化器,因此指令重新排序的机会微乎其微。 Delphi 优化在指令发出之前发生在 AST / IR 上。

可以注册局部变量,但是任何对需要内存地址的变量的源代码引用(例如将局部变量传递给 var 参数,或获取局部 var 的地址)都会强制编译器提交在使用地址之前将值注册到内存位置,或者可能会强制编译器完全放弃注册变量。

Delphi 32 位编译器在优化方面相当保守。优化带来的最大性能提升来自注册变量和中间结果,以及各种循环归纳技巧。

对全局符号或驻留在全局内存中的符号(例如对象字段)的操作未注册。没有“volatile”修饰符。

编译器代码生成模式依赖于 x86 架构规则,即在对齐地址处对全局内存进行寄存器大小的写入是原子的。大数据、字节数据或未对齐地址的写入可能会跨越高速缓存行,并且需要在单个写入指令中进行两次单独的写入操作。 Delphi 编译器(大部分)没有注意到这一点。

无论如何,如果您正在编写从不同线程访问共享内存的 Delphi 代码,您始终有责任决定哪些线程同步措施适合您的情况并实施它们。

【讨论】:

  • +1。丹尼,这是一个写得非常好的答案。做得很好!我希望我能多次投票的罕见场合之一。
  • +1,非常好的答案。不过,我想知道是否有任何计划/意图来改进 Delphi 关于进程和线程的内存模型。顺便说一句,有人知道 64 位编译器是否以同样的方式工作?
  • 谢谢。关于 64 位,@Guillem,据我所知,它采用了相同的注册策略。
  • 我无法说出计划或意图。自 2005 年以来,我一直处于圈外。
猜你喜欢
  • 1970-01-01
  • 2010-09-18
  • 2011-02-04
  • 1970-01-01
  • 2011-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多