L2 が満たされていない場合、CPU は大幅に高速に動作するようです。プログラマーは、コードの一部が常に実行されなくても、最終的にはバイナリでより小さくなるものをコーディングするほうがよいでしょうか? たとえば、構成ファイルでのみオンになっているコードの一部です。
1 に答える
真実はもう少し複雑です、私はあなたのためにそれを概説しようとします。
マルチコアプロセッサを搭載した最新のPCのメモリ階層を見ると、次の6つのレベルがあることがわかります。
- プリフェッチャー、コアごとに1つ(レイテンシーなし)
- L1キャッシュ、コアごとに1つまたは2つ(コードとデータの組み合わせ、AMDK10では2* 64K)(レイテンシーは3つのclksと言います)
- L2キャッシュ、コアごとに1つ(AMD K10では512K)(レイテンシーは10と言う)
- L3キャッシュ、すべてのコアで使用されるプロセッサごとに1つ(AMDK10ではncores* 1 MB)(レイテンシーは30と言う)
- システムRAM、すべてのプロセッサで使用されるシステムごとに1つ(レイテンシは100と言います)
- 同期(またはバスロック)、すべてのバスマスタリングデバイスで使用されるシステムごとに1つの方法(古いPCIカードが33 MHzのクロッキングでバスマスタリング時に使用可能な32クロックすべてを使用している場合、レイテンシは少なくとも1usまで300サイクル- 3000クロックサイクルを意味する3GHzプロセッサ)
サイクルカウントが正確であるとは思わないでください。これらは、コードの実行時に発生する可能性のあるペナルティの感触を与えることを目的としています。
時々メモリも同期する必要があり、それには時間がかかるので、私はメモリレベルとして同期を使用します。
使用する言語は、パフォーマンスに大きな影響を与えます。C、C ++、またはForTranで記述されたプログラムは、Basic、C#、Javaなどのインタプリタプログラムよりも小さく、実行速度が速くなります。CとFortranは、データ領域とそれらへのプログラムアクセスを整理するときにもより良い制御を提供します。カプセル化や標準クラスの使用など、オブジェクト指向言語(C ++、C#、およびJava)の特定の関数では、より大きなコードが生成されます。
コードの記述方法もパフォーマンスに大きな影響を与えます。ただし、知識のない人の中には、コンパイラが非常に優れているため、優れたソースコードを記述する必要がないと言う人もいます。優れたコードは優れたパフォーマンスを意味し、GarbageInは常にGarbageOutになります。
あなたの質問の文脈では、通常、気にしないよりも小さく書く方がパフォーマンスに優れています。効率的にコーディングすることに慣れている場合(小さい/速いコード)、めったに使用されないシーケンスを記述しているのか、頻繁に使用するシーケンスを記述しているのかに関係なく、コーディングを行います。
キャッシュには、プログラム全体がロードされていない可能性がありますが(可能性はありますが)、コード内の32バイトまたは64バイトのアドレスからフェッチされたデータの32バイトまたは64バイトのチャンク(「キャッシュライン」)が多数あります。これらのチャンクの1つにある情報にアクセスすればするほど、キャッシュラインが長く保持されます。コアがL1にないチャンクを1つ必要とする場合は、必要に応じてRAMまで検索し、ペナルティクロックを発生させます。それをしながらサイクルします。
したがって、一般に、小さくてタイトなインラインコードシーケンスは、キャッシュへの影響が少ないため、実行速度が速くなります。他のコード領域を頻繁に呼び出すコードは、最適化されていないジャンプを使用したコードと同様に、キャッシュに大きな影響を与えます。分割は非常に有害ですが、問題のコアの実行にのみ影響します。どうやらAMDはIntelよりもはるかに優れているようです(http://gmplib.org/~tege/x86-timing.pdf)。
データ編成の問題もあります。ここでは、1つのキャッシュラインフェッチがフェッチごとに1つだけではなく、複数の頻繁に使用される変数を取り込むように、物理的に小さな領域に頻繁に使用されるデータを配置することもお勧めします(これは標準です)。
データまたはデータ構造の配列にアクセスするときは、メモリアドレスの低い方から高い方へアクセスするようにしてください。繰り返しになりますが、あちこちにアクセスすると、キャッシュに悪影響を及ぼします。
最後に、データが実際に使用される前に可能な限りデータのフェッチを開始するようにキャッシュに指示できるように、データのプリフェッチヒントをプロセッサに与える手法があります。
これらのことを理解して実用的なレベルで使用できるようにするには、さまざまな構成をテストし、できればrdtscカウンターを使用して時間を計る必要があります(stackoverflowで多くの情報があります) )またはプロファイラーを使用します。