我有一个这样的函数(只显示重要部分) :
double CompareShifted(const std::vector<uint16_t>& l, const std::vector<uint16_t> &curr, int shift, int shiftY) {
...
for(std::size_t i=std::max(0,-shift);i<max;i++) {
if ((curr[i] < 479) && (l[i + shift] < 479)) {
nontopOverlap++;
}
...
}
...
}
像这样编写,这个函数在我的机器上花费了大约34毫秒。在将条件更改为 bool 乘法(使代码看起来像这样)之后:
double CompareShifted(const std::vector<uint16_t>& l, const std::vector<uint16_t> &curr, int shift, int shiftY) {
...
for(std::size_t i=std::max(0,-shift);i<max;i++) {
if ((curr[i] < 479) * (l[i + shift] < 479)) {
nontopOverlap++;
}
...
}
...
}
执行时间减少到19毫秒。
使用的编译器是 GCC 5.4.0和 -O3
,在检查了 用 Godbolt.org 生成的代码之后,我发现第一个示例生成了一个跳转,而第二个不生成。我决定试试 GCC 6.2.0,它在使用第一个示例时也会生成一个跳转指令,但 GCC 7似乎不再生成这样的指令了。
找到这种加速代码的方法是相当可怕的,而且花了相当长的时间。为什么编译器会这样?它是否是有意的,是否是程序员应该注意的东西?还有其他类似的东西吗?