7

このスライド (スライド15の後)では、使用することをお勧めします

void updateAims(float* aimDir, const AimingData* aim, vec3 target, uint count)
{
     for(uint i = 0; i < count; i++)
     {
          aimDir[i] = dot3(aim->positions[i], target) * aim->mod[i];
     }
}

キャッシュ効率が高いからです。

クラスがある場合はどうですか

class Bot
{
    vec3 position;
    float mod;
    float aimDir;

    void UpdateAim(vec3 target)
    {
         aimDir = dot3(position, target) * mod;
    }
 };

 void updateBots(Bots* pBots, uint count, vec3 target)
 {
      for(uint i = 0; i < count; i++)
            pBots[i]->UpdateAim(target);
  }

そして、そのクラスのすべてのオブジェクトを単一の線形配列に格納します。

それらはすべて同じアレイにあるので、キャッシュミスはありますか?なぜ最初のアプローチが優れているのでしょうか?

4

2 に答える 2

11

最新のキャッシュアーキテクチャは通常、データのとして構造化されており、それぞれが複数の単語を保持するのに十分な大きさです。64バイトが一般的なラインサイズです。キャッシュにないデータを読み取ろうとすると、必要な単語だけでなく、行全体がフェッチされます。書き込み時に、キャッシュ内のデータは、存在する場合は更新されますが、存在しない場合は通常、フェッチする必要はありません。

最初のケースでは、フェッチされる入力データのすべてのキャッシュラインに対して、そのすべての単語を使用します。2番目では、一部の構造フィールドのみを使用します。他のものをフェッチすると、帯域幅が無駄になります。

具体的にはaimDir、計算に必要のない、毎回の古い値を取得しています。一般に、「オブジェクト」には、この特定の計算では不要なフィールドが多く含まれている可能性があり、キャッシュにフェッチされて無視されるため、さらに多くの帯域幅が無駄になります。

于 2012-08-27T12:23:15.283 に答える
0

メモリレイアウトはかなり異なり、ボットの配列を使用すると、最初のアプローチの利点が失われます。

最初のアプローチでは、すべてのaimDirデータがフラグメント化されていないメモリブロックに格納されます。したがって、最初に処理した場合は、次のメモリユニットに保存されるため、すぐに次のアイテムに進むことができます。

の配列がある場合は、フラグメント化されていないメモリブロックにオブジェクトが格納されてBotいます。Botしかし、aimDir2つのボットの異なるデータは、ボット(positionおよびmod)によって他のデータによって分離されるようになりました。

グラフィカルに、最初のアプローチ(positionとmodの配列も想定している場合)は次のようになります。

[R]は、ボットに関係のないランダムな未知のデータを意味します

[R][position_0][position_1]...[position_n][R][mod_0][mod_1]...[mod_n][R][aimDir_0][aimDir_1]...[aimDir_n][R]

2番目のアプローチは次のようになります。

[R][[position_0],[mod_0],[aimDir_0]][[position_1][mod_1][aimDir_1]]...[[position_n][mod_n][aimDir_n]][R]
于 2012-08-27T12:25:49.543 に答える