为什么std::vector比数组慢



当我运行以下程序(启用优化(时,带有std::vectorfor循环大约需要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() << "secondsn";
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;
}

该代码是我在编写光线投射器时遇到的性能问题的简化版本。len变量对应于原始程序中循环需要运行的次数(400像素*400像素*50最大渲染距离(。由于复杂的原因(也许我不完全理解如何使用数组(,我不得不在实际的光线投射器中使用向量而不是数组。然而,正如这个程序所展示的,这只会给我每秒20帧的速度,而使用数组会给我带来令人羡慕的每秒10000帧的速度(显然,这只是一个简化的性能测试(。但不管这些数字有多准确,我仍然想尽可能提高我的帧速率。那么,为什么矢量的执行速度比数组慢得多呢?有没有办法加快速度?谢谢你的帮助。如果我还有什么奇怪的事情可能会影响我的表现,请告诉我。在研究这个问题的答案之前,我甚至不知道优化,所以如果还有其他类似的东西可以提高性能,请告诉我(我更希望你在属性管理器而不是命令行中解释这些设置的位置,因为我还不知道如何使用命令行(

让我们观察GCC如何优化这个测试程序:

#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

测试程序的不同之处在于循环的顺序。注释指出,当第三个循环添加到开头时,两个循环所花费的时间相同。

我预计,当启用优化并禁用调试时,使用现代编译器访问向量的速度将与访问数组的速度大致相同。如果你的实际程序中存在明显的差异,那么问题就出在其他地方。

这是关于缓存的。我不知道它是如何详细工作的,但Data[]在使用时越来越为cpu所知。如果你颠倒计算顺序,你可以看到"矢量更快"。

但实际上,您既没有在测试vector,也没有测试array。假设vec[0]位于0x01内存位置,arr[0]位于0xf1。唯一的区别是从不同的单一记忆地址中读取一个单词。因此,您正在测试我能以多快的速度将分配给动态分配的array的元素。

注意:std::chrono::high_resolution_clock可能不足以测量刻度。最好使用steady_clock作为cppreference所说的。

最新更新