对这个类进行基准测试:
struct Sieve {
std::vector<bool> isPrime;
Sieve (int n = 1) {
isPrime.assign (n+1, true);
isPrime[0] = isPrime[1] = false;
for (int i = 2; i <= (int)sqrt((double)n); ++i)
if (isPrime[i])
for (int j = i*i; j <= n; j += i)
isPrime[j] = false;
}
};
当为大量调用构造函数时,使用 64 位二进制与 32 位版本(发布版本)相比,我的性能(CPU 时间)差了 3 倍以上,例如
Sieve s(100000000);
我测试过sizeof(bool)
,它1
适用于两个版本。当我用64 位和 32 位版本替换vector<bool>
时,性能变得相同。vector<char>
这是为什么?
以下是S(100000000)
(发布模式,首先是 32 位,其次是 64 位)的运行时间:
vector<bool>
0.97s 3.12s
vector<char>
0.99s 0.99s
vector<int>
1.57s 1.59s
我还用 VS2010 进行了健全性测试(由 Wouter Huysentruit 的响应提示),结果为 0.98s 0.88s。所以VS2012的实现有问题。
我向Microsoft Connect提交了错误报告
编辑
下面的许多答案评论了使用int
索引的缺陷。这可能是真的,但即使是大巫师本人for (int i = 0; i < v.size(); ++i)
也在他的书中使用了一个标准,所以这样的模式应该不会导致显着的性能损失。此外,这个问题是在 Going Native 2013 会议期间提出的,C++ 大师的主持小组评论了他们早期建议使用size_t
for indexing 和 as a return type of size()
as 错误。他们说:“对不起,我们还年轻……”
这个问题的标题可以改写为:从 VS2010 升级到 VS2012 时,此代码的性能下降超过 3 倍。
编辑
我粗略地尝试查找索引的内存对齐,i
并j
发现这个检测版本:
struct Sieve {
vector<bool> isPrime;
Sieve (int n = 1) {
isPrime.assign (n+1, true);
isPrime[0] = isPrime[1] = false;
for (int i = 2; i <= sqrt((double)n); ++i) {
if (i == 17) cout << ((int)&i)%16 << endl;
if (isPrime[i])
for (int j = i*i; j <= n; j += i) {
if (j == 4) cout << ((int)&j)%16 << endl;
isPrime[j] = false;
}
}
}
};
现在自动神奇地运行得很快(仅比 32 位版本慢 10%)。这种和 VS2010 的性能使得我们很难接受优化器在处理int
索引而不是size_t
.