24

C++ プログラムを設計するときに起こりうるキャッシュ ミスの数を減らすにはどうすればよいですか?

インライン関数は毎回役に立ちますか? それとも、プログラムが CPU バウンドの場合 (つまり、プログラムが I/O 指向ではなく計算指向である場合) だけでよいのでしょうか?

4

6 に答える 6

35

この種のコードで作業するときに私が考慮したいことがいくつかあります。

  • 「配列の構造」と「構造の配列」のどちらが必要かを検討してください。どちらを使用するかは、データの各部分によって異なります。
  • 構造体を32バイトの倍数に維持して、キャッシュラインを均等にパックするようにしてください。
  • データをホット要素とコールド要素に分割します。クラスoのオブジェクトの配列があり、ox、oy、ozを頻繁に一緒に使用するが、たまにoi、oj、okにアクセスする必要がある場合は、ox、oy、およびozを組み合わせて、i、j、および並列の腋窩データ構造へのk個のパーツ。
  • データの多次元配列がある場合、通常の行順レイアウトでは、優先次元に沿ってスキャンする場合はアクセスが非常に高速になり、他の次元に沿ってスキャンする場合はアクセスが非常に遅くなります。代わりに、空間充填 曲線に沿ってマッピングすると、任意の次元を移動するときにアクセス速度のバランスをとるのに役立ちます。(ブロッキング手法は似ています。基数が大きいZオーダーです。)
  • キャッシュミスが発生する必要がある場合は、コストを償却するために、そのデータを可能な限り使用するようにしてください。
  • マルチスレッドで何かをしていますか?キャッシュ整合性プロトコルによる速度低下に注意してください。フラグと小さなカウンターを埋めて、別々のキャッシュラインに配置します。
  • IntelのSSEは、事前に十分にアクセスするものがわかっている場合に、いくつかのプリフェッチ組み込み関数を提供します。
于 2009-01-20T10:49:24.987 に答える
10

データ バインド操作の場合

  1. リスト、マップ、セットで配列とベクトルを使用する

  2. 行単位で列単位で処理

于 2009-01-20T10:16:05.553 に答える
2

関数の実行をインライン化すると、命令キャッシュに損害を与えるリスクがあります。そして、メモリがフェッチバウンドでない場合、(もしあれば)大きな違いを生む可能性は低いです。

いつものように、最適化は、ハンチではなくプロファイリングによって通知する必要があります。言うまでもなく、プロファイラーが何を言っているかを理解する必要があります。これは、アセンブリ言語に精通していることと、最適化するプラットフォームの特定の特性を意味します。

今は少し古いですが、MikeAbrashの「Graphic'sProgrammingBlack Book」には、まだ多くの良い一般的なアドバイスがあります。

于 2009-01-20T10:47:13.227 に答える
2

また、C++ とマルチスレッドを実行している場合は、各プロセッサのキャッシュ上のデータの偽共有、局所性、ホットネスを考慮する必要があります。それは大きな違いを生む可能性があります。また、特にマルチスレッドでは、LIFO 方式で計算する方が FIFO 方式で計算するよりも効率的ですが、シングル プロセッサ アーキテクチャでも有効です。

于 2009-01-20T11:01:13.263 に答える
2

CPU がデータを効率的にプリフェッチできるようにします。たとえば、多次元配列を列ではなく行で処理したり、ループをアンロールしたりすることで、キャッシュ ミスの数を減らすことができます。

この種の最適化はハードウェア アーキテクチャに依存するため、Intel VTune などのプラットフォーム固有のプロファイラーを使用して、キャッシュで発生する可能性のある問題を検出することをお勧めします。

于 2009-01-20T10:09:46.457 に答える
1

必要のない場合は、動的メモリの使用を避けてください。new、delete、スマートポインタなどを使用すると、プログラムデータがメモリ全体に分散する傾向があります。それは良いことではありません。(たとえば、スタック上のオブジェクトを宣言することによって)ほとんどのデータをまとめることができれば、キャッシュは確実にはるかにうまく機能します。

于 2009-01-20T10:43:13.393 に答える