【发布时间】:2011-10-06 15:46:24
【问题描述】:
以下三段代码实现的效果完全相同。然而,当在 GCC 4.5.2 上使用 -O3 编译时,大量迭代的时间差异很大。
1 - 正常分支,使用多个条件,最佳时间 1.0:
// a, b, c, d are set to random values 0-255 before each iteration.
if (a < 16 or b < 32 or c < 64 or d < 128) result += a+b+c+d;
2 - 分支,手动使用按位或检查条件,最佳时间 0.92:
if (a < 16 | b < 32 | c < 64 | d < 128) result += a+b+c+d;
3 - 最后,在没有分支的情况下得到相同的结果,最佳时间 0.85:
result += (a+b+c+d) * (a < 16 | b < 32 | c < 64 | d < 128);
当作为我制作的基准程序的内部循环运行时,上述时间是每种方法的最佳时间。 random() 在每次运行前都以相同的方式播种。
在我做这个基准测试之前,我认为 GCC 会优化掉这些差异。尤其是第二个例子让我摸不着头脑。谁能解释一下为什么 GCC 不把这样的代码变成等效的更快的代码?
编辑:修复了一些错误,并明确了随机数是无论如何创建和使用的,以免被优化掉。他们总是在原始基准中,我只是把我放在这里的代码搞砸了。
这是一个实际基准函数的示例:
boost::random::mt19937 rng;
boost::random::uniform_int_distribution<> ranchar(0, 255);
double quadruple_or(uint64_t runs) {
uint64_t result = 0;
rng.seed(0);
boost::chrono::high_resolution_clock::time_point start =
boost::chrono::high_resolution_clock::now();
for (; runs; runs--) {
int a = ranchar(rng);
int b = ranchar(rng);
int c = ranchar(rng);
int d = ranchar(rng);
if (a < 16 or b < 32 or c < 64 or d < 128) result += a;
if (d > 16 or c > 32 or b > 64 or a > 128) result += b;
if (a < 96 or b < 53 or c < 199 or d < 177) result += c;
if (d > 66 or c > 35 or b > 99 or a > 77) result += d;
}
// Force gcc to not optimize away result.
std::cout << "Result check " << result << std::endl;
boost::chrono::duration<double> sec =
boost::chrono::high_resolution_clock::now() - start;
return sec.count();
}
【问题讨论】:
-
什么是
or?您的第一个示例似乎不是有效的 C。 -
它(至少)是
||的 C++ 同义词。 -
@Mark B - 是吗?从什么时候开始?
-
@HeathHunnicutt: Apparently, since forever. 它们还作为一组在 C89 之后添加的宏存在(似乎不是 C99,这很奇怪)。
-
@Heath Hunnicutt C++98 C.2.2.2
The tokens and, and_eq, bitand, bitor, compl, not_eq, not, or, or_eq, xor, and xor_eq are keywords in this International Standard (2.11). They do not appear as macro names defined in <ciso646>。另请参阅 2.5/2/table 2,其中显示了直接备用令牌映射。
标签: c++ optimization gcc