【发布时间】:2012-07-01 20:11:32
【问题描述】:
这是在阅读Mysticial 对问题的精彩回答时想到的一个问题:why is it faster to process a sorted array than an unsorted array?
所涉及类型的上下文:
const unsigned arraySize = 32768;
int data[arraySize];
long long sum = 0;
在他的回答中,他解释说英特尔编译器 (ICC) 对此进行了优化:
for (int i = 0; i < 100000; ++i)
for (int c = 0; c < arraySize; ++c)
if (data[c] >= 128)
sum += data[c];
...变成与此等价的东西:
for (int c = 0; c < arraySize; ++c)
if (data[c] >= 128)
for (int i = 0; i < 100000; ++i)
sum += data[c];
优化器认识到这些是等价的,因此是exchanging the loops,将分支移到内部循环之外。很聪明!
但它为什么不这样做呢?
for (int c = 0; c < arraySize; ++c)
if (data[c] >= 128)
sum += 100000 * data[c];
希望 Mysticial(或其他任何人)能给出同样出色的答案。我以前从未了解过其他问题中讨论的优化,所以我非常感谢。
【问题讨论】:
-
这可能只有英特尔知道。我不知道它运行优化传递的顺序是什么。显然,它不会在循环交换后运行循环折叠通道。
-
此优化仅在数据数组中包含的值不可变时才有效。例如,如果每次读取 data[0] 时将 memory mapped 发送到输入/输出设备,则会产生不同的值...
-
这是什么数据类型,整数还是浮点数?浮点数中的重复加法与乘法的结果截然不同。
-
@Thomas:如果数据是
volatile,那么循环交换也是无效的优化。 -
GNAT(带有 GCC 4.6 的 Ada 编译器)不会在 O3 切换循环,但如果切换循环,它会将其转换为乘法。
标签: c performance compiler-optimization