1. ホーム
  2. c++

[解決済み】std::vectorは普通の配列よりそんなに遅いの?

2022-04-05 01:44:24

質問

というのが一般的な常識だと思っていました。 std::vector は、配列として実装されています。今日、私はそれをテストし、そしてそれはそうではないようです。

以下はテスト結果です。

UseArray completed in 2.619 seconds
UseVector completed in 9.284 seconds
UseVectorPushBack completed in 14.669 seconds
The whole thing completed in 26.591 seconds

約3~4倍も遅いんですね~。これでは「quot」の意味がありません。 vector may be slower for a few nanosecs" というコメントがあります。

そして、使ったコード。

#include <cstdlib>
#include <vector>

#include <iostream>
#include <string>

#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time/microsec_time_clock.hpp>

class TestTimer
{
    public:
        TestTimer(const std::string & name) : name(name),
            start(boost::date_time::microsec_clock<boost::posix_time::ptime>::local_time())
        {
        }

        ~TestTimer()
        {
            using namespace std;
            using namespace boost;

            posix_time::ptime now(date_time::microsec_clock<posix_time::ptime>::local_time());
            posix_time::time_duration d = now - start;

            cout << name << " completed in " << d.total_milliseconds() / 1000.0 <<
                " seconds" << endl;
        }

    private:
        std::string name;
        boost::posix_time::ptime start;
};

struct Pixel
{
    Pixel()
    {
    }

    Pixel(unsigned char r, unsigned char g, unsigned char b) : r(r), g(g), b(b)
    {
    }

    unsigned char r, g, b;
};

void UseVector()
{
    TestTimer t("UseVector");

    for(int i = 0; i < 1000; ++i)
    {
        int dimension = 999;

        std::vector<Pixel> pixels;
        pixels.resize(dimension * dimension);

        for(int i = 0; i < dimension * dimension; ++i)
        {
            pixels[i].r = 255;
            pixels[i].g = 0;
            pixels[i].b = 0;
        }
    }
}

void UseVectorPushBack()
{
    TestTimer t("UseVectorPushBack");

    for(int i = 0; i < 1000; ++i)
    {
        int dimension = 999;

        std::vector<Pixel> pixels;
            pixels.reserve(dimension * dimension);

        for(int i = 0; i < dimension * dimension; ++i)
            pixels.push_back(Pixel(255, 0, 0));
    }
}

void UseArray()
{
    TestTimer t("UseArray");

    for(int i = 0; i < 1000; ++i)
    {
        int dimension = 999;

        Pixel * pixels = (Pixel *)malloc(sizeof(Pixel) * dimension * dimension);

        for(int i = 0 ; i < dimension * dimension; ++i)
        {
            pixels[i].r = 255;
            pixels[i].g = 0;
            pixels[i].b = 0;
        }

        free(pixels);
    }
}

int main()
{
    TestTimer t1("The whole thing");

    UseArray();
    UseVector();
    UseVectorPushBack();

    return 0;
}

私のやり方が悪いのか、それとも何か?それとも、このパフォーマンス神話を打ち破ったのでしょうか?

でリリースモードを使っています。 ビジュアルスタジオ2005 .


ビジュアル C++ , #define _SECURE_SCL 0 削減 UseVector を半分にする(4秒にする)。これは本当に大きいです、IMO。

解決方法は?

以下を使用します。

<ブロッククオート

g++ -O3 Time.cpp -I <MyBoost>

./a.out

UseArrayの実行時間:2.196秒

UseVector 4.412秒で完了

UseVectorPushBackの実行時間:8.017秒

全体が完了したのは14.626秒

つまり、arrayはvectorの2倍速いということですね。

しかし ベクトルは2回、配列は1回だけなので、これは予想通りです。注 resize() ベクトルでは、メモリを確保するだけでなく、ベクトル内を移動して各メンバーのコンストラクタを呼び出しています。

コードを少しアレンジして、ベクターが各オブジェクトを一度だけ初期化するようにします。

 std::vector<Pixel>  pixels(dimensions * dimensions, Pixel(255,0,0));

今、もう一度同じタイミングを行う。

g++ -O3 Time.cpp -I <MyBoost>

./a.out

UseVectorの実行時間:2.216秒

vectorはarrayよりほんの少しパフォーマンスが悪くなりました。IMO この差は重要ではなく、このテストに関連しない多くの事柄が原因である可能性があります。

のPixelオブジェクトを正しく初期化/破棄していないことも考慮に入れます。 UseArrray() メソッドが呼び出されないためです。(この単純なクラスでは問題ないかもしれませんが、もう少し複雑なもの(たとえばポインタやポインタを持つメンバー)では問題が発生するでしょう。