2016-05-26 2 views
5

私は小さな構造を持っており、個々のメンバーをコピーすることは、構造を一度にコピーするよりも大幅に高速であることが分かりました。これには正当な理由はありますか?個々のメンバーを構造全体より速くコピーしますか?

私のプログラム:

// Some random structure 
private struct PackStats 
{ 
    public int nGoodPacks, nBadPacks, nTotalPacks; 
} 

// ... 
PackStats stats1 = new PackStats(); 
PackStats stats2 = new PackStats(); 

// Set some random statistics 
stats1.nGoodPacks = 55; 
stats1.nBadPacks = 3; 
stats1.nTotalPacks = (stats1.nGoodPacks + stats1.nBadPacks); 

// Now assign stats2 from stats1 

// This single line consumes ~190ns... 
stats2 = stats1; 

// ...but these three lines consume ~100ns (in total) 
stats2.nGoodPacks = stats1.nGoodPacks; 
stats2.nBadPacks = stats1.nBadPacks; 
stats2.nTotalPacks = stats1.nTotalPacks; 

ナノ秒の範囲で時間を測定するために、私は倍の割り当ての何百万を作る:

uint uStart = GetTickCount(); 
for (int nLoop=0; nLoop<10000000; nLoop++) 
{ 
    // Do something... 
} 
uint uElapsed = (GetTickCount() - uStart); 

結果は、最適化が有効と無効の両方で、ほぼ一致しました。..この小さな構造の個々のメンバーをコピーすることは約2倍速かった。同じ結果がC/C++にも当てはまりますか?

+0

ILコードの検査についてのコメントがありました。それをどうやって行うかわからず、方法を研究します。説明が簡単な場合は、コメントで返信してください。 – AlainD

+0

http://stackoverflow.com/q/9025186/11683 – GSerg

+0

anycpu用にコンパイルされた64ビットCPU、 –

答えて

3

あなたのタイミングはデバッグビルドのようです。私のタイミングは以下の通りです

private void DoIt() 
    { 
     const int numReps = 1000000000; 
     PackStats stats1 = new PackStats(); 
     PackStats stats2 = new PackStats(); 

     stats1.a = 55; 
     stats1.b = 3; 
     stats1.c = stats1.a + stats1.b; 

     for (var i = 0; i < 2; ++i) 
     { 
      var sw1 = Stopwatch.StartNew(); 
      for (var j = 0; j < numReps; ++j) 
      { 
       stats2 = stats1; 
      } 
      sw1.Stop(); 
      Console.WriteLine("Copy struct = {0:N0} ms", sw1.ElapsedMilliseconds); 

      sw1.Restart(); 
      for (var j = 0; j < numReps; ++j) 
      { 
       stats2.a = stats1.a; 
       stats2.b = stats1.b; 
       stats2.c = stats1.c; 
      } 
      sw1.Stop(); 
      Console.WriteLine("Copy fields = {0:N0} ms", sw1.ElapsedMilliseconds); 
     } 
    } 

   struct  fields 
Debug/Debug  2,245  1,908 
Debug/No  2,238  1,919 
Release/Debug 287   294 
Release/No  281   275 

これは、Visual Studioの2015年にプログラムがどれCPUとしてコンパイルされ、そして64上で実行されて、私はこのコードで同じテストをしましたビットマシン。

デバッグ/デバッグとは、デバッガが接続された状態で実行されるデバッグビルドを意味します(つまり、プログラムを実行するにはF5キーを押します)。デバッグ/いいえは、デバッグなしで実行されるデバッグビルド(つまり、Ctrl + F5)を意味します。もちろん、リリースはリリースビルドを意味します。

リリースモードでは、一度に構造体をコピーするか、個々のフィールドをコピーするかの違いはほとんどありません。ここに示されている最悪のケースでは、10億回の反復回数が6ミリ秒です。

あなたの質問に対する回答:「メンバー全体を構造全体よりも速くコピーするか?」 "デバッグモードでは、はい"と表示されます。

+1

リリース2015は、リリースモードの最適化で優れた仕事をしているようですので、その結果は嬉しく思います(私はVS 2008を使用していました)。以前の回答は、 'stats2 = stats1;'を使用したときに新しい構造体が作成されたと指摘しましたが、答えは削除されました。あなたの結果と結びついていると思います。効率的なオプティマイザは、おそらく新しい構造を不必要に作成することを避けることができます。 – AlainD

関連する問題