我不是一个训练有素的计算机科学家,所以我不知道所有或大多数有关编译等方面的细节,但是我一直认为我的c程序已编译为机器代码,可以使用gcc -S标志进行查看。

我还认为我的代码与机器代码越接近,计算机执行起来就越快。所以我决定测试一下。

我编写了两个测试文件来计算一个简单的算术问题。

// test1.c
int main(int argc, char* argv[]){
    int x = 4243;
    int y = 3235;
    int z = 613*x + 725*y;
    return 0;
}

// test2.c
int main(int argc, char* argv[]){
    int x = 4243;
    int y = 3235;
    int z = ( ( ( ( ( ( ( x << 3 ) + x ) << 1 ) + x ) << 3 ) + x ) << 2 ) + x +
      ( ( ( ( ( ( ( ( ( y << 2 ) + y ) << 1 ) + y ) << 2 ) + y ) << 2 ) + y ) << 2 ) + y;
    return 0;
}

我知道我使这个例子复杂了很多,但是当我用一个简单的例子进行尝试时,区别并不明显。

现在,如果我使用gcc -S标志进行编译,则机器代码对于test1.s是31行,对于test2.s是47行。

有什么可能的解释?是否假设较少的机器代码行意味着更快的执行速度有缺陷? .s文件在创建二进制文件之前是否会用于任何用途?我的玩具测试假吗?

感谢您的任何见解

最佳答案

曾经有一段时间,CPU非常简单且不复杂,而像您上面尝试的那样的移位技巧实际上会比CPU的内置乘法指令产生更好的性能。 (以程序长度为代价:一系列移位指令可能会也可能不会比单个乘法指令快,但肯定会更长。)我相信这种情况一直持续到80286年。

甚至曾经有一段时间(还记得Z80,有人吗?),CPU如此简单以至于它们甚至没有内置的乘法指令,因此我们不得不调用例程以对数字进行乘法,并且这些例程当然会包含循环迭代次数将是被乘数的位数,因此这些移位技巧将在那时产生更好得多的性能。 (同样,这将以程序长度为代价:与执行两个或多个移位操作相比,调用乘法例程需要更少的字节。)

但是如今,这种情况已不再成立。您的(大概是现代的)CPU当然具有一个内置的乘法指令,该指令通常在很少的时钟周期内执行(small, as in, 3),因此使用它必然比将乘法分解为多个移位要快(且更小)。操作,每个操作名义上都在一个时钟周期内执行。

我说“名义上”是因为使用预取,流水线处理,缓存等,甚至您可以事先知道任何给定指令将需要多少个时钟周期的想法不再成立。

因此,简而言之,就是:“学会停止担心和爱炸弹”。

关于c++ - 为什么显式移位算法会导致更大的.s文件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29444662/

10-14 18:42