Arj*_*ran 1 c bit-manipulation bitwise-operators compiler-optimization
我尝试使用我写的按位运算来比较算术加法和函数 - 发现后者几乎10x慢了.这种速度差异的原因是什么?由于我在循环中添加相同的数字,编译器是否会在第一种情况下将其重写为更优的东西?
使用算术运算:
int main()
{
clock_t begin = clock();
int x;
int i = 1000000000;
while(i--) {
x = 1147483000 + i;
}
printf("%d\n", x);
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("time spent = %f\n", time_spent);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
1147483000
time spent = 3.520000
Run Code Online (Sandbox Code Playgroud)
使用按位运算符:
内线while loop被替换为:
x = add(1147483000, i);
Run Code Online (Sandbox Code Playgroud)
这是add功能:
int add(int x, int y) {
while(y != 0) {
int carry = (x & y);
x = x ^ y;
y = carry << 1;
}
return x;
}
Run Code Online (Sandbox Code Playgroud)
输出:
1147483000
time spent = 32.940000
Run Code Online (Sandbox Code Playgroud)
你已经替换了这个:
x = 1147483000 + i;
Run Code Online (Sandbox Code Playgroud)
有了这个:
while(y != 0) {
int carry = (x & y);
x = x ^ y;
y = carry << 1;
}
Run Code Online (Sandbox Code Playgroud)
当然,你会得到一个巨大的减速!+两个整数是一条汇编指令。您的while循环执行许多指令,在软件中有效地模拟硬件在执行加法时所做的事情。
更详细地说,这就是全加器的样子。通过 32 位加法,ALU包含 32 个这个单元级联。这些硬件元素中的每一个都有非常非常小的延迟。电线的延迟可以忽略不计。因此,如果软件将两个 32 位数字相加,则只需要很少的时间。
另一方面,如果您尝试手动模拟加法,则会使 CPU 进入内存、提取和解码某些指令 32 次,这需要相当长的时间。

通常在非常少量的时钟周期中在硬件中执行整数运算.
您将无法在软件中接近这种性能.使用按位运算的实现涉及函数调用和循环.您执行的按位操作通常会花费与算术相似的时钟周期数.
您每次迭代执行三个按位运算.坦率地说,我很惊讶这里只有10倍.
我也想知道你的编译器设置是什么,特别是任何优化.一个好的编译器可以消除算术版本中的while循环.对于性能比较,您应该比较优化代码.看起来好像你可能没有这样做.
很难知道你想要在这里实现什么,但是不要期望超过硬件算术单元的性能.