[英]Slow std::vector vs [] in C++ - Why?
我对 C++ 有点生疏——20 年前就用过它。 我试图理解为什么 std::vector 在以下代码中比本机数组慢得多。 谁能给我解释一下? 我更喜欢使用标准库,但不会以这种性能损失为代价:
向量:
const int grid_e_rows = 50;
const int grid_e_cols = 50;
int H(std::vector<std::vector<int>> &sigma) {
int h = 0;
for (int r = 0; r < grid_e_rows; ++r) {
int r2 = (r + 1) % grid_e_rows;
for (int c = 0; c < grid_e_cols; ++c) {
int c2 = (c + 1) % grid_e_cols;
h += 1 * sigma[r][c] * sigma[r][c2] + 1 * sigma[r][c] * sigma[r2][c];
}
}
return -h;
}
int main() {
auto start = std::chrono::steady_clock::now();
std::vector<std::vector<int>> sigma_a(grid_e_rows, std::vector<int>(grid_e_cols));
for (int i=0;i<600000;i++)
H(sigma_a);
auto end = std::chrono::steady_clock::now();
std::cout << "Calculation completed in " << std::chrono::duration_cast<std::chrono::seconds>(end - start).count()
<< " seconds";
return 0;
}
输出是:
Calculation completed in 23 seconds
大批:
const int grid_e_rows = 50;
const int grid_e_cols = 50;
typedef int (*Sigma)[grid_e_rows][grid_e_cols];
int H(Sigma sigma) {
int h = 0;
for (int r = 0; r < grid_e_rows; ++r) {
int r2 = (r + 1) % grid_e_rows;
for (int c = 0; c < grid_e_cols; ++c) {
int c2 = (c + 1) % grid_e_cols;
h += 1 * (*sigma)[r][c] * (*sigma)[r][c2] + 1 * (*sigma)[r][c] * (*sigma)[r2][c];
}
}
return -h;
}
int main() {
auto start = std::chrono::steady_clock::now();
int sigma_a[grid_e_rows][grid_e_cols];
for (int i=0;i<600000;i++)
H(&sigma_a);
auto end = std::chrono::steady_clock::now();
std::cout << "Calculation completed in " << std::chrono::duration_cast<std::chrono::seconds>(end - start).count()
<< " seconds";
return 0;
}
输出是:
Calculation completed in 6 seconds
任何帮助,将不胜感激。
首先,您正在为初始化计时。 对于数组情况,没有(数组完全未初始化)。 在向量情况下,向量被初始化为零,然后复制到每一行中。
但主要原因是缓存位置。 数组情况是一个50*50
整数块,它们在内存中都是连续的,它们可以轻松地放入 L1D 缓存中。 在向量情况下,每一行都是动态分配的,这意味着它们的地址几乎肯定不是连续的,而是分布在整个程序的地址空间中。 访问一个不会将相邻的行拉入缓存。
此外,由于行相对较小,缓存空间会浪费在相邻的不相关数据上,这意味着即使您已经接触了所有内容以将其拉入内存,它也可能不再适合 L1。 最后,访问模式的线性度要低得多,它可能超出了硬件预取器的预测能力。
您没有进行优化编译。
相比:
为了让您了解优化器可能会为您做什么,请考虑对vector
情况的vector
的H()
函数进行以下修改。
int H(std::vector<std::vector<int>> &arg) {
int h = 0;
auto sigma = arg.data();
for (int r = 0; r < grid_e_rows; ++r) {
int r2 = (r + 1) % grid_e_rows;
auto sr = sigma[r].data();
auto sr2 = sigma[r2].data();
for (int c = 0; c < grid_e_cols; ++c) {
int c2 = (c + 1) % grid_e_cols;
h += 1 * sr[c] * sr[c2] + 1 * sr[c] * sr2[c];
}
}
return -h;
}
你会发现,如果没有优化,这个版本的运行性能会更接近你的阵列版本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.