好的,所以出于性能原因,编译器可以自由地重新排序代码片段。让我们假设一些代码片段,直接翻译成机器代码,没有应用优化,如下所示:
machine_instruction_1
machine_instruction_2
machine_instruction_3
machine_instruction_4
machine_instruction_5但是,智能编译器决定原始顺序效率很低,并重新排序相同的代码,因此产生的机器指令的新顺序如下:
machine_instruction_5
machine_instruction_4
machine_instruction_3
machine_instruction_2
machine_instruction_1到目前一切尚好。
这里是棘手的部分开始。得到的机器指令将由cpu执行,只要保持代码逻辑,cpu就可以自由地对它们进行重新洗牌。由于我们正在处理两个“层”的指令重新排序:
是什么使编译时指令重新排序相关呢?cpu所看到的只是一系列原始机器指令,没有显示编译器先前执行的任何优化。如果cpu引入了自己的“层”重排序,它为什么不使编译器设置的指令顺序失效呢?基本上,是什么迫使cpu尊重编译器优化?编译时重新排序和运行时重新排序如何“合作”,后者如何补充前者?
发布于 2019-01-17 22:36:35
在考虑指令执行时,必须尊重的是程序的语义。任何命令都是正确的,只要这一点得到尊重。具体而言,这是由“依赖项”描述的,该“依赖关系”指示某些指令是否需要程序正确行为的给定顺序。例如,考虑以下程序
1 x <= y+3
2 z <= 2*x
3 w = 5*y
4 y = 2*a指令1和2是依赖的。如果他们的相对排序被修改,程序就不符合程序员的要求,任何重新排序都是被禁止的。由于不同的原因,在y被1和3使用之前,4不能不变地执行。有不同的依赖关系,包括在考虑控制流时。
编译器和硬件试图重新排序程序,以提高其效率,同时尊重依赖性。事实上,它们的行动是相辅相成的。
编译器可以考虑比处理器更大的重组,并使用更复杂的启发式方法来实现。编译器可以对程序有一个大的视图,并重新排序大部分代码。理论上,如果不存在依赖关系冲突,并且编译器认为它可以改进程序的执行,则可以在1000的距离上替换一个指令。它可以完全重组代码,展开循环等。相反,处理器有一个相对有限的预取指令窗口,可以考虑重新排序,而任何重新排列只能涉及封闭指令,并且基于一个周期内可行的简单方法。
但是处理器有很大的优势。它可以对随机事件进行动态重新排序和响应。在给定的时间,它考虑可以执行哪些指令与依赖项和数据可用性有关,并相应地重新排序代码。这是基于动态依赖关系的,例如,如果由于缓存丢失而无法获得前一个依赖项指令的结果,它将执行其他尊重依赖项的指令。同一程序在相同输入数据下连续运行会导致不同的排序,这取决于分支错误预测、缓存丢失等。
因此,编译器和处理器之间没有竞争,而是高效的协作。
https://stackoverflow.com/questions/54244337
复制相似问题