std::vector与std::array的性能比较

5
我是一个有用的助手,可以为您进行文本翻译。以下是需要翻译的内容:

我正在研究新的chrono库(C++11),并尝试使用它。我编写了以下两个程序:

vector.cpp

#include <iostream>
#include <vector>
#include <chrono>

int main()
{
    std::vector<double> vector(1000000, 0.);

    auto start = std::chrono::high_resolution_clock::now();
    for(int i(0); i < vector.size(); i++)
    {
        vector[i] += 1.;
    }
    auto end = std::chrono::high_resolution_clock::now();

    std::cout << "Elapsed time: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << " milliseconds" << std::endl;

    return 0;
}

array.cpp

#include <iostream>
#include <array>
#include <algorithm>
#include <chrono>

int main()
{
    std::array<double, 1000000> array;

    std::fill(array.begin(), array.end(), 0.);

    auto start = std::chrono::high_resolution_clock::now();
    for(int i(0); i < array.size(); i++)
    {
        array[i] += 1.;
    }
    auto end = std::chrono::high_resolution_clock::now();

    std::cout << "Elapsed time: " << std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() << " milliseconds" << std::endl;

    return 0;
}

对于数组程序,我获得了9毫秒的执行时间,而对于向量程序,我获得了12毫秒。 std::vector 的速度似乎比 std::array 慢大约33%。 我做得对吗?为什么会有这种差异?

附:我正在使用GCC 4.7和Mac OS X 10.7。

g++-mp-4.7 -std=c++11 vector.cpp -o vector
g++-mp-4.7 -std=c++11 array.cpp -o array

3
改为for(int i(0), iMax( vector.size() ); i < iMax; i++) - Ylisar
1
@R.M.,为确保您不会在每次迭代中执行任何额外的工作,您应该为两个版本均执行。 - Lubo Antonov
2
顺便提一下,您不需要使用 std::fill 来将数组清零,您可以像这样初始化它:std::array<double, 1000000> array{} - juanchopanza
9
你还应该打开优化选项,否则这个练习就完全是学术性的。 - juanchopanza
使用gcc编译器,带有-02时间对我来说是相同的;但是clang编译器会出现错误,并且差异仍然存在。 - Stephan Dollberg
显示剩余5条评论
3个回答

10
我把你的代码改成了这样:
std::array<double, 1000000> array;

double total = 0;
std::fill(array.begin(), array.end(), 0.);

for (unsigned j = 0; j < 1000; ++j)
{
    auto start = std::chrono::high_resolution_clock::now();

    for (unsigned i = 0; i < array.size(); i++)
    {
        array[i] += 1.;
    }

    auto end = std::chrono::high_resolution_clock::now();
    total = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
}

std::cout << total << " for Array." << std::endl;

std::vector<double> vector(1000000, 0.);
total = 0;

for (unsigned j = 0; j < 1000; ++j)
{
    auto start = std::chrono::high_resolution_clock::now();

    for (unsigned i = 0; i < vector.size(); i++)
    {
        vector[i] += 1.;
    }

    auto end = std::chrono::high_resolution_clock::now();
    total = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
}

std::cout << total << " for Vector." << std::endl;

我使用-O3的结果:

8123 for Array.
8117 for Vector.

在我看来,两者的速度都相同。


我确认使用O3选项的您的结果:数组为3005,向量为3018。对于10000个周期:数组为30103,向量为30082。 - user1434698

2
数字没有启用优化是没有意义的。很可能在您的情况下,对size()的重复调用会产生差异。

1

std::array 在编译时已知大小,因此内存很可能会在堆栈上分配。

std::vector 使用 std::allocator(它可能使用 `new` 在运行时从自由存储区(也称为堆)中分配内存)。

我认为堆与栈的分配比例为30%是正常的。


编辑:在liveworkspace.org上运行几次(我知道这不是最科学的测量方法)(std::vectorstd::array),我得到了8毫秒对10毫秒的结果。由于所有分配确实都在测量之外,因此我会天真地得出结论,访问堆比访问栈内存慢。如果这通常是正确的,我也不会感到惊讶,因为在堆的情况下有一个额外的间接性。


所有的分配都发生在时间窗口之外。 - Marcelo Cantos
3
很明显它并没有在栈上分配1M个双精度浮点数 - 再猜猜看。 - Lubo Antonov
1
@lucas1024 你认为 std::array 知道除了栈以外的任何东西吗? - rubenvb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接