为什么 std::vector 比数组慢?
Why is std::vector slower than an array?
当我运行以下程序(启用优化)时,for
循环与std::vector
大约需要0.04秒,而for
循环与数组需要 0.0001 秒。
#include <iostream>
#include <vector>
#include <chrono>
int main()
{
int len = 800000;
int* Data = new int[len];
int arr[3] = { 255, 0, 0 };
std::vector<int> vec = { 255, 0, 0 };
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < len; i++) {
Data[i] = vec[0];
}
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
std::cout << "The vector took " << elapsed.count() << "seconds\n";
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < len; i++) {
Data[i] = arr[0];
}
finish = std::chrono::high_resolution_clock::now();
elapsed = finish - start;
std::cout << "The array took " << elapsed.count() << "seconds \n";
char s;
std::cin >> s;
delete[] Data;
}
该代码是我在编写 raycaster 时遇到的性能问题的简化版本。 len
变量对应原程序中循环需要运行(400像素*400像素*50最大渲染距离)多少次。由于复杂的原因(也许我不完全理解如何使用数组),我必须在实际的 raycaster 中使用向量而不是数组。然而,正如这个程序所展示的那样,这只会给我每秒 20 帧,而不是令人羡慕的每秒 10,000 帧,据称使用数组可以给我(显然,这只是一个简化的性能测试)。但不管这些数字有多准确,我仍然想尽可能地提高帧率。那么,为什么向量的执行速度比数组慢很多呢?有没有办法加快速度?谢谢你的帮助。如果还有其他我做的奇怪的事情可能会影响性能,请告诉我。在研究这个问题的答案之前我什至不知道优化,所以如果还有更多类似的东西可以提高性能,请告诉我(如果你解释这些设置在属性管理器而不是命令行,因为我还不知道如何使用命令行)
这是关于缓存的。我不知道它是如何详细工作的,但是 Data[]
在使用时被 cpu 所熟知。如果将计算顺序颠倒,您可以看到 'vector is faster'。
但实际上,您既没有测试 vector
也没有测试 array
。假设 vec[0]
位于 0x01
内存位置,arr[0]
位于 0xf1
。唯一的区别是从不同的单个内存地址读取一个单词。因此,您正在测试我可以多快将 值 分配给动态分配的 array
.
的元素
注意: std::chrono::high_resolution_clock
可能不足以测量滴答声。如cppreference所说,最好使用steady_clock
。
让我们观察一下how GCC optimizes this test program:
#include <vector>
int main()
{
int len = 800000;
int* Data = new int[len];
int arr[3] = { 255, 0, 0 };
std::vector<int> vec = { 255, 0, 0 };
for (int i = 0; i < len; i++) {
Data[i] = vec[0];
}
for (int i = 0; i < len; i++) {
Data[i] = arr[0];
}
delete[] Data;
}
编译器正确地注意到向量是常量,并将其删除。为两个循环生成完全相同的代码。因此,第一个循环使用数组还是向量应该无关紧要。
.L2:
movups XMMWORD PTR [rcx], xmm0
add rcx, 16
cmp rsi, rcx
jne .L2
使您的测试程序与众不同的是循环的顺序。评论指出when a third loop is added to the beginning,两个循环耗时相同
我希望在启用优化并禁用调试的情况下,使用现代编译器访问向量的速度大约与访问数组一样快。如果您的实际程序存在明显差异,则问题出在其他地方。
当我运行以下程序(启用优化)时,for
循环与std::vector
大约需要0.04秒,而for
循环与数组需要 0.0001 秒。
#include <iostream>
#include <vector>
#include <chrono>
int main()
{
int len = 800000;
int* Data = new int[len];
int arr[3] = { 255, 0, 0 };
std::vector<int> vec = { 255, 0, 0 };
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < len; i++) {
Data[i] = vec[0];
}
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
std::cout << "The vector took " << elapsed.count() << "seconds\n";
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < len; i++) {
Data[i] = arr[0];
}
finish = std::chrono::high_resolution_clock::now();
elapsed = finish - start;
std::cout << "The array took " << elapsed.count() << "seconds \n";
char s;
std::cin >> s;
delete[] Data;
}
该代码是我在编写 raycaster 时遇到的性能问题的简化版本。 len
变量对应原程序中循环需要运行(400像素*400像素*50最大渲染距离)多少次。由于复杂的原因(也许我不完全理解如何使用数组),我必须在实际的 raycaster 中使用向量而不是数组。然而,正如这个程序所展示的那样,这只会给我每秒 20 帧,而不是令人羡慕的每秒 10,000 帧,据称使用数组可以给我(显然,这只是一个简化的性能测试)。但不管这些数字有多准确,我仍然想尽可能地提高帧率。那么,为什么向量的执行速度比数组慢很多呢?有没有办法加快速度?谢谢你的帮助。如果还有其他我做的奇怪的事情可能会影响性能,请告诉我。在研究这个问题的答案之前我什至不知道优化,所以如果还有更多类似的东西可以提高性能,请告诉我(如果你解释这些设置在属性管理器而不是命令行,因为我还不知道如何使用命令行)
这是关于缓存的。我不知道它是如何详细工作的,但是 Data[]
在使用时被 cpu 所熟知。如果将计算顺序颠倒,您可以看到 'vector is faster'。
但实际上,您既没有测试 vector
也没有测试 array
。假设 vec[0]
位于 0x01
内存位置,arr[0]
位于 0xf1
。唯一的区别是从不同的单个内存地址读取一个单词。因此,您正在测试我可以多快将 值 分配给动态分配的 array
.
注意: std::chrono::high_resolution_clock
可能不足以测量滴答声。如cppreference所说,最好使用steady_clock
。
让我们观察一下how GCC optimizes this test program:
#include <vector>
int main()
{
int len = 800000;
int* Data = new int[len];
int arr[3] = { 255, 0, 0 };
std::vector<int> vec = { 255, 0, 0 };
for (int i = 0; i < len; i++) {
Data[i] = vec[0];
}
for (int i = 0; i < len; i++) {
Data[i] = arr[0];
}
delete[] Data;
}
编译器正确地注意到向量是常量,并将其删除。为两个循环生成完全相同的代码。因此,第一个循环使用数组还是向量应该无关紧要。
.L2:
movups XMMWORD PTR [rcx], xmm0
add rcx, 16
cmp rsi, rcx
jne .L2
使您的测试程序与众不同的是循环的顺序。评论指出when a third loop is added to the beginning,两个循环耗时相同
我希望在启用优化并禁用调试的情况下,使用现代编译器访问向量的速度大约与访问数组一样快。如果您的实际程序存在明显差异,则问题出在其他地方。