我知道CPU可以重新排序
之类的指令load A
load B
但CPU会重新排序以下代码吗? (换句话说,在另一个核心上运行的第二个线程会以相反的顺序看到结果吗?)
some_array[array_index] = new_value;
++array_index;
我猜它会从不,因为第二行依赖于第一行。我是对的吗?
答案 0 :(得分:6)
不,你错了。
编译器和CPU完全可以自由地优化和重新排序代码,只要结果对于任何保证的行为都是相同的。其他线程将无法保证以任何特定顺序进行修改。因此,例如,CPU和编译器可以自由地实现与此代码相同的代码:
++array_index;
some_array[array_index - 1] = new_value;
甚至:
tmp = array_index;
++array_index;
some_array[tmp] = new_value;
由于没有违反保证,编译器和CPU可以自由地进行这些优化。这是一件好事,因为它们可以使代码显着加快。
如果您需要更多保证,可以使用适当的工具(锁,障碍,原子等)来获取它们。但是没有理由不关心这些东西的代码应该被拒绝这样的优化。
这是你出错的地方:
我猜它永远不会因为第二行依赖于第一行。我是对的吗?
只有当CPU和编译器都无法找出依赖关系并解开它时。但这在这里显而易见。通过计算出依赖关系,它们可以按任意顺序执行,编译器和CPU实际上确实可以找出这些类型的依赖关系(除此之外甚至更复杂),因为如果我们的软件 更慢,那么他们没有。
但即使依赖是不可撤销的,也不要求实际的写入以任何特定的顺序对其他线程可见。它们可以位于CPU的写入发布缓冲区中,并以任何顺序执行。另一个线程也可能重新排序读取,CPU正在进行预读。