我正在检查互斥锁,信号量,spin_locks内存障碍等等,我只是来execution reorder
。我在维基读到了一些内容,但它对我来说真的没有任何意义,重新排序执行优化问题?这不是打破代码吗?有什么限制。它在这个维基页面Java Memory Model
在现代平台上,代码通常不按编写顺序执行。它由编译器,处理器和内存子系统重新排序,以实现最大性能。在多处理器体系结构中,各个处理器可能有自己的本地缓存,与主存储器不同步。
特别是多线程概念它带来了性能,但它会使你的程序不稳定或不存在。你必须非常小心。因此,由于特定的性能原因,这不是复杂性,而重新排序的代码看起来很可怕。
答案 0 :(得分:1)
作为重新排序的好方案,请考虑以下事项:
A = B / C; => read B, C + compute + write to A
D = E + F; => read E, F + compute + write to D
翻译为:
read B, C
compute B/C
write result to A
read E, F
compute E+F
write result to D
可以重新排序为:
read B, C, E, F ==> force reads as soon as possible
compute B / C => slow operation (could do something usefull such as read E, F in the meanwhile)
compute E + F
write A, write D => defer writes as late as possible
这不会破坏单线程排序保证并实现更好的执行吞吐量。
此外,here概念描述得非常好。
答案 1 :(得分:0)
不打破代码吗?
优化仅限于不违反语言保证的更改。关键是许多语言没有完全指定行为。当两个线程执行x = 1
和x = 2
时,结果不完全指定。
由于特定的性能原因,这不是复杂性,而且重新排序的代码看起来很可怕。
过度复杂还是过度复杂取决于您的目标。有些语言非常安全,有些语言非常宽松。所有语言都为您提供编写安全程序的工具。工具各不相同,难以使其工作。此外,性能也各不相同。
答案 2 :(得分:0)
以下是可能重新排序的代码示例:
extern bool b;
extern int x;
extern int y;
extern int z;
void foo() {
z = x;
if (b)
y = x;
}
所谓的想法如下:首先将全局z
设置为某个内容,如果设置了b
,则同时设置y
。假设有另一个线程,它以某种方式查询z
,一旦它成为它想要的,它就设置b
- 从而允许foo()
分配y
。
这段代码当然有很多问题,但我会专注于重新排序。代码生成以下程序集:
foo():
cmpb $0, b(%rip)
movl x(%rip), %eax
movl %eax, z(%rip)
je .L1
movl %eax, y(%rip)
.L1:
rep ret
如您所见,首先检查b!将x
复制到z
,然后执行跳转。执行已经重新排序 - 在完成赋值之前检查布尔标志,并且整个想法都被破坏了。 (它会被打破,所以这个例子只是一个重新排序的插图)。