【发布时间】:2020-06-29 05:34:00
【问题描述】:
我已经让一个软件运行起来,现在我正在尝试对其进行调整以使其运行得更快。我也发现了一些令人震惊的东西——只是很奇怪。它不再相关,因为我切换到使用指针而不是索引数组(使用指针更快),但我仍然想知道发生了什么。
代码如下:
short mask_num_vals(short mask)
{
short count = 0;
for(short val=0;val<NUM_VALS;val++)
if(mask & val_masks[val])
count++;
return count;
}
这小段代码被多次调用。真正让我惊讶的是,这段代码的运行速度明显快于其前身,后者只是将“&”操作的两个参数颠倒过来。
现在,我原以为这两个版本在所有实际目的上都是相同的,而且它们确实产生了相同的结果。但是上面的版本更快——明显更快。它在使用它的整个代码的运行时间上产生了大约 5% 的差异。我尝试测量在上述函数中花费的时间量完全失败了 - 测量所用时间远远超过实际执行其余代码的时间。 (我猜是海森堡软件原理的一个版本。)
所以我的图片是,编译后的代码评估这两个参数,然后对它们进行按位“与”。谁在乎论点的顺序?显然编译器或计算机会这样做。
我完全不支持的猜想是编译后的代码必须为每个位评估“val_masks[val]”。如果“val_masks[val]”首先出现,它会为每一位评估它,如果“mask”首先出现,那么如果“mask”中的特定位为零,它就不会打扰“val_masks[val]”。我没有任何证据支持这个猜想;我只是想不出任何其他可能导致这种行为的东西。
这看起来有可能吗?这种行为对我来说似乎很奇怪,我认为这表明我对编译代码的工作方式和实际工作方式的看法有所不同。同样,不再那么相关了,因为我进一步改进了代码(使用指针而不是数组)。但我仍然想知道是什么原因造成的。
硬件是 Apple MacBook Pro 15 英寸 2018,MacOS 10.15.5。软件为 gcc 编译器,“gcc --version”产生如下输出。
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
使用命令“gcc -c -Wall 'C filename'”编译,与“gcc -o -Wall 'object filenames'”链接。
【问题讨论】:
-
尝试使用
gcc -O2编译这两个版本的代码,看看汇编没有区别。 -
几个问题:您使用的编译标志是什么?
NUM_VALS的值是多少?val_masks[]中的掩码是什么?这个数组是如何定义的? -
你可以用
gcc -S编译来查看程序集。 -
"我切换到使用指针而不是索引数组(使用指针更快)," - 这并不普遍。它更可能反映了您在编译代码时没有设置优化级别的事实——或者您有其他问题。编译器完全能够像使用指针一样优化索引。
标签: c operator-precedence bitwise-and