我有一个循环需要按特定顺序执行操作序列。我在这里所做的是多次手动展开循环:
loop
{
delta = get_delta();
sum1 += delta;
sum2 += delta;
sum3 += delta;
delta = get_delta();
sum1 += delta;
sum2 += delta;
sum3 += delta;
}
查看生成的汇编代码,有时编译器会将此循环优化为如下所示:
loop
{
delta1 = get_delta();
delta2 = get_delta();
delta_sum = delta1 + delta2;
sum1 += delta_sum;
sum2 += delta_sum;
sum3 += delta_sum;
}
我不希望这种情况发生,因为该行为并不完全复制循环展开。我一直在通过
__asm__
关键字研究内联汇编提示,但无法完全使其可靠地工作。我也不想使用 volatile
变量,因为这会导致从内存加载,而不是使用寄存器。在构建时将优化标志更改为 -O0
或 -O1
并不理想,因为这不能保证始终在不同的编译器版本等下产生一致的结果。
有谁知道我可以使用
__asm__
或类似的技巧,以便我可以完全按照源代码中编写的顺序展开循环,而不必编写汇编代码?
在尝试了各种
__asm__ volatile ()
语句和不同的编译器优化选项之后,很明显循环展开(无论是自动还是手动)都会产生太多副作用。编译器执行各种代码优化和消除,从而产生非常不同的代码结构。
为了通过定时循环获得一致的结果,应执行以下操作:
使用
_Pragma ("GCC unroll 1")
和 -fno-unroll-loops
完全禁用特定翻译单元的循环展开。
增加循环内的指令数量,以减少循环开销,从而使大量循环迭代的测量结果出现偏差。
不要使用
-O0
或类似的,这太粗糙了并且会禁用许多其他有用的优化。