6

ゲーム エンジンのマイクロ最適化の状況: C++ 11 の範囲 for ループを使用vector<int>して、autoキーワードで , を反復処理しています。

より速いもの:

for(auto value : ints) ...

また

for(auto& value : ints) ...

?

4

4 に答える 4

14

どちらが速いかを気にする前に、どちらが意味的に正しいかを気にする必要があります。反復される要素を変更する必要がない場合は、最初のバージョンを選択する必要があります。それ以外の場合は、2 番目のバージョンを選択する必要があります。

確かに、ベクトルの内容を変更する必要がない場合でも、への参照を使用するオプションがまだあることに異議を唱えることができますconst

 for(auto const& value : ints)

そして、問題は次のようになります。どちらが速いですか? 参照constまたは値による?

for繰り返しますが、上記が意味的に正しいかどうかを最初に検討する必要があります。これは、ループ内で何をしているかによって異なります。

int i = 0;
for (auto const& x : v) // Is this correct? Depends! (see the loop body)
{
    v[i] = 42 + (++i);
    std::cout << x;
}

for (auto i : x)これは、これが意味的に正しい場合はいつでも使用する基本的な型について述べています。

パフォーマンスが悪くなるとは思いません (むしろ良くなると思います) が、パフォーマンスに関してはいつものように、仮定を裏付ける唯一の有意義な方法は、測定、測定、および測定することです。

于 2013-05-13T14:11:28.573 に答える
5

変更valueして、ベクター内の実際の要素を変更することが期待される場合は、必要 auto&です。変更しない場合は、 orvalueを使用してまったく同じコードにコンパイルされる可能性があります(自分で調べるためにプロファイルします)。autoauto&

QueryPerformanceCounter に基づくタイマーで VS2012 を使用してタイミングを計りました...

    m::HighResTimer timer;

    std::vector<int> ints(100000000, 17);

    int count = 0;

    timer.Start();
    for(auto& i : ints)
        count += i;
    timer.Stop();

    std::cout   << "Count: " << count << '\n'
                << "auto& time: " << duration_cast<duration<double, std::milli>>(timer.Elapsed()).count() << '\n';

    count = 0;
    timer.Reset();
    timer.Start();
    for(const auto& i : ints)
        count += i;
    timer.Stop();

    std::cout   << "Count: " << count << '\n'
                << "const auto& time: " << duration_cast<duration<double, std::milli>>(timer.Elapsed()).count() << '\n';

    count = 0;
    timer.Reset();
    timer.Start();
    for(auto i : ints)
        count += i;
    timer.Stop();

    std::cout   << "Count: " << count << '\n'
                << "auto time: " << duration_cast<duration<double, std::milli>>(timer.Elapsed()).count() << '\n';

結果....

Count: 1700000000
auto& time: 77.0204

Count: 1700000000
const auto& time: 77.0648

Count: 1700000000
auto time: 77.5819
Press any key to continue . . .

ここでは時差を読みません。すべての実用的な目的のために、それらは同一であり、実行ごとにわずかに変動します。

于 2013-05-13T14:09:02.030 に答える
2

GCC では、両方のバージョンが を-O1介して最適化フラグを使用して同じアセンブリにコンパイルされ-O3ます。

コンパイラが最適化をfor (auto value : ints)処理するので、値を変更する必要がないときはいつでも を使用します。Andy が指摘しているように、const-ref を使用することもできますが、パフォーマンスがまったく向上しない場合は、気にしません。

于 2013-05-13T14:28:21.630 に答える
2

まず第一に、値を変更する場合は使用しauto&、変更しない場合は使用しないでください。勝手に変えてしまう可能性があるからです。

const auto&ただし、と シンプルの間で選択できる場合がありますauto。の場合、ここではパフォーマンスは問題ではないと思いますstd::vector<int>

使用する理由auto

  1. 読みやすくなっています
  2. 変更可能です(変更せずにvector

使用する理由const auto&

  1. 他の型で使用する必要があるため、このように記述する方が一般的です。さらに、型を複雑な型に変更しても、誤ってパフォーマンスの問題が発生することはありません。
  2. この変数の値を変更することはできないため、コンパイル時にエラーが発生する可能性があります。

どちらの場合も、何をするかを理解する必要があります。サイクルが何らかの形で範囲を変更するかどうかによって異なります。

于 2013-05-13T14:11:40.670 に答える