7

CPUキャッシュが速度パフォーマンスに与える影響をテストするプログラムを作成しました。

void* foo(void* ptr)
{
    int* r = (int*) ptr;

    for (int i = (r - s); i < N; i += NUM_THREADS)
        *r += num[i];        
    return NULL;
}

void* bar(void* ptr)
{
    int* r = (int*) ptr;
    int idx = r - s;
    int block = N/NUM_THREADS;
    int start = idx * block, end = start + block;

    for (int i = start; i < end; ++i)
        *r += num[i];        
    return NULL;
}

基本的にfoo()、インターレーススキャンを実行しましたがbar()、アレイをブロックごとにスキャンしました。

テスト結果は、それbar()がはるかに高速であることを示しています。

gcc ping-pong.c -std=gnu99 -lpthread -O2  ; ./a.out
1.077037s
0.395525s

では、この結果をどのように解釈するのでしょうか?

完全なソースコードは次の場所にあります:https ://gist.github.com/4617935

更新:すべてのifステートメントが削除されました

4

2 に答える 2

3

まったく不思議ではないことがわかりました。

キャッシュミスをプロファイリングするためにvalgrindを試しました。結果は次のとおりです。

$ valgrind --tool=cachegrind --cachegrind-out-file=profile ./a.out
....
$ cg_annotate profile --auto=yes --show=D1mr --context=1
....
-- line 63 ----------------------------------------
    .  void* foo(void* ptr)
     0  {
     0      int* r = (int*) ptr;
     .  
     0      for (int i = (r - s); i < N; i += NUM_THREADS)
16,388          *r += num[i];
     0      return NULL;
     0  }
     .  
-- line 71 ----------------------------------------

-- line 72 ----------------------------------------
     .  void* bar(void* ptr)
     0  {
     0      int* r = (int*) ptr;
     0      int idx = r - s;
     0      int block = N/NUM_THREADS;
     0      int start = idx * block, end = start + block;
     .  
     0      for (int i = start; i < end; ++i)
 4,098          *r += num[i];
     0      return NULL;
     0  }

ご覧のとおり、L1キャッシュの読み取りミスはの4倍でfoo()ありbar、4は単なるNUM_THREADS。です。

@Mysticialが答えたように

シーケンシャルメモリアクセスは、ほとんどの場合、非シーケンシャルアクセスよりも優れています。

シーケンシャルではないメモリアクセスが多いほど、キャッシュミスが多くなります。

于 2013-01-24T05:57:39.140 に答える
1

シーケンシャルアクセスがはるかに高速である理由は、キャッシュ構造によるものではなく、HWプリフェッチ(関連しているが同じではない)によるものです。ストリームまたはストライドベースのアクセスパターンを認識し、データのプリフェッチを先に実行できる「ストリーミング」プリフェッチャーがいくつかあります。

いくつかの例(Intel CPUですが、他のCPUでも同様のプリンシパルが一般的に使用されています): http ://software.intel.com/en-us/articles/optimizing-application-performance-on-intel-coret-microarchitecture-using -ハードウェア-実装済み-プリフェッチャー

ここで提案されているvalgrindプロファイリングはそれを示しています。L2/L3も確認することをお勧めします。大きなデータセットでは、有用なプリフェッチがそこに存在する可能性が高くなります(経験則-コアから離れるほど、より多くの時間とアグレッシブなプリフェッチに使用できるストレージ)。

于 2013-01-28T21:41:13.987 に答える