以下是在x86-64上用C语言设置单个比特的两种方式:
inline void SetBitC(long *array, int bit) {
//Pure C version
*array |= 1<<bit;
}
inline void SetBitASM(long *array, int bit) {
// Using inline x86 assembly
asm("bts %1,%0" : "+r" (*array) : "g" (bit));
}
使用GCC 4.3版本和-O3 -march=core2
选项,C语言版本在使用常量bit
时需要花费90%更多的时间。(两个版本编译成完全相同的汇编代码,除了C语言版本使用or [1<<num],%rax
指令而不是bts [num],%rax
指令)
当使用变量bit
时,C语言版本性能表现更好,但仍然比内联汇编慢得多。
重置、切换和检查位具有类似的结果。
为什么GCC对于这样一个常见的操作优化得如此差?我在C语言版本中做错了些什么吗?
编辑:抱歉等待这么久,这里是我用于基准测试的代码。实际上它起初是一个简单的编程问题...
int main() {
// Get the sum of all integers from 1 to 2^28 with bit 11 always set
unsigned long i,j,c=0;
for (i=1; i<(1<<28); i++) {
j = i;
SetBit(&j, 10);
c += j;
}
printf("Result: %lu\n", c);
return 0;
}
gcc -O3 -march=core2 -pg test.c
./a.out
gprof
with ASM: 101.12 0.08 0.08 main
with C: 101.12 0.16 0.16 main
time ./a.out
也会给出类似的结果。
or
所需的时钟比通常更少的bts
少。 - Anon.