我执行了一个小测试来确定访问指针vs值向量向量的行为。事实证明,对于小型内存块而言,两者的表现同样出色,但是,对于大型内存块而言,则会有显着差异。向量指针vs向量值对大型内存块和小型内存块的性能损失
这种行为的解释是什么?
对于下面的代码,在我的电脑上执行,D = 0的差值约为35%,而对于D = 10它是不明显的。
int D = 0;
int K = 1 << (22 - D);
int J = 100 * (1 << D);
int sum = 0;
std::vector<int> a(K);
std::iota(a.begin(), a.end(), 0);
long start = clock();
for (int j = 0; j < J; ++j)
for (int i = 0; i < a.size(); ++i)
sum += a[i];
std::cout << double(clock() - start)/CLOCKS_PER_SEC << " " << sum << std::endl;
sum = 0;
std::vector<int*> b(a.size());
for (int i = 0; i < a.size(); ++i) b[i] = &a[i];
start = clock();
for (int j = 0; j < J; ++j)
for (int i = 0; i < b.size(); ++i)
sum += *b[i];
std::cout << double(clock() - start)/CLOCKS_PER_SEC << " " << sum << std::endl;
指针会导致间接寻址,从而导致额外的内存访问。以及更多的空间正在使用当然可能会溢出缓存。 – 2015-03-08 19:04:21
'sum + = a [i];'通过溢出有符号'int'的边界导致未定义的行为。 (并且另外发生相同的错误)。即使您认为这不应该成为问题,但使用不调用未定义行为的代码进行测试也是一个不错的主意。这可以通过改变为'unsigned int sum = 0;'(或其他一些无符号类型,尽管选择的类型可能会影响基准)来解决。 – 2015-03-08 19:39:45
如果您不处于最佳优化级别,基准并不意味着太多。如果使用“-O3”,则可能需要采取其他措施来防止优化循环。使'sum'变成'volatile'应该这样做,但是最好仔细检查生成的程序集以确保时序代码不被重新排序。你也可以使用C++ 11的[高分辨率时钟](http://stackoverflow.com/a/5524138/1505939)而不是'clock'。 – 2015-03-08 19:45:13