【发布时间】:2017-02-08 10:29:42
【问题描述】:
我在准备用 C++ 实现类似 python 的",".join(vector) 函数时发现了这一点。我想比较消除用于避免在字符串开头放置额外的',' 的内部if first element 条件是否有意义。我写了以下函数:
long long test1() // 38332ms
{
long long k = 0;
for (long long i = 0; i < 10000000000; ++i)
{
if (i != 0)
{
k += 2;
}
k += 1;
}
return k;
}
long long test2() // 45272ms
{
long long k = 0;
k += 1;
for (long long i = 1; i < 10000000000; ++i)
{
k += 2; // in the real code it might be impossible to merge
k += 1; // those operations
}
return k;
}
我使用简化的代码使条件跳转更有意义。我期望分支预测会最小化差异。令我惊讶的是,第一个功能表现得更好。我正在测试 VS2015 下的调试设置。编译器没有执行任何优化 - 我检查了程序集。我也尝试过移动一些东西——移动函数定义、调用顺序、限制常量。比例大致相同。
可能的解释是什么?
编辑: 我没有分析这个特定的场景,而是试图得到一些关于这种行为的可能原因的通用答案。我的猜测是 CPU 在分支预测期间执行某种启发式算法,并且在我的特定情况下,我的特定 CPU 更擅长在 test1 中预测此分支。这只是我的直觉,所以我在徘徊它是否正确。考虑到我的猜测,有人可以考虑一下吗?
【问题讨论】:
-
假设
llong是long long int安全吗? -
你的计时码是什么样的?
-
您对此进行了多少次实验?有很多因素会影响从运行到运行的完成时间
-
我在基于 Haswell 的服务器上使用 gcc 4.8.5 在 Linux 上看到了相同的效果。对函数重新排序、更改常量等非常强大。查看汇编输出,唯一的区别是处理
test中的特殊情况的 3 条额外指令。最好的猜测是,这是一个深奥的架构特定的指令对齐和/或指令缓存问题。有趣的是,gcc在使用-O3编译时使test2免费,但它不会优化掉test。 -
十次运行。测试 2 始终延长约 6/10 秒。 GCC 4.8.1。没有优化。 AMD A10 处理器
标签: c++ loops cpu-architecture branch-prediction