什么是环路反转技术?
我正在浏览一个文档,其中讨论了Java的即时编译器(JIT)优化技术。其中之一是“循环反转”。该文件说:
将常规循环替换为循环。循环是在子句中设置的。这种替换导致跳转次数减少两次。
while
do-while
do-while
if
循环反转如何工作,如何优化我们的代码路径?
注意:如果有人能用Java代码的例子来解释,以及JIT如何将其优化为本机代码,以及为什么它在现代处理器中是最佳的,那就太好了。
我正在浏览一个文档,其中讨论了Java的即时编译器(JIT)优化技术。其中之一是“循环反转”。该文件说:
将常规循环替换为循环。循环是在子句中设置的。这种替换导致跳转次数减少两次。
while
do-while
do-while
if
循环反转如何工作,如何优化我们的代码路径?
注意:如果有人能用Java代码的例子来解释,以及JIT如何将其优化为本机代码,以及为什么它在现代处理器中是最佳的,那就太好了。
while (condition) {
...
}
工作流程:
if (condition) do {
...
} while (condition);
工作流程:
比较这两者,你可以很容易地看到,后者可能根本不做任何跳跃,只要循环中只有一个步骤,并且通常跳跃的次数将比迭代次数少一个。前者将不得不跳回去检查条件,只有当条件为假时才能跳出循环。
在现代流水线 CPU 架构上跳转可能非常昂贵:由于 CPU 在跳转之前完成了检查的执行,因此跳转之外的指令已经在流水线的中间。如果分支预测失败,则必须放弃所有这些处理。在重新请求管道时,进一步执行将延迟。
解释上述分支预测:对于每种条件跳转,CPU都有两条指令,每条指令包括对结果的押注。例如,您可以在循环结束时放置一条指令,说“如果不是零则跳转,则押注不是零”,因为除了最后一次迭代之外,必须在所有迭代中进行跳转。这样,CPU 开始使用跳转目标后面的指令泵送其管道,而不是跳转指令本身后面的指令。
请不要将此作为如何在源代码级别进行优化的示例。这将是完全错误的,因为从你的问题中已经很清楚,从第一种形式到第二种形式的转换是JIT编译器作为例行公事做的事情,完全是它自己完成的。
这可以优化始终至少执行一次的循环。
然后,常规循环将始终至少跳回到开头一次,并在结束时跳到末尾一次。运行一次的简单循环的示例:while
int i = 0;
while (i++ < 1) {
//do something
}
另一方面,循环将跳过第一个和最后一个跳转。下面是与上面的循环等效的循环,它将在没有跳转的情况下运行:do-while
int i = 0;
if (i++ < 1) {
do {
//do something
} while (i++ < 1);
}