C/C++ コードを徹底的に測定および調整して、x86_64 システムのキャッシュでパフォーマンスを向上させたいと考えています。カウンター (Windows マシンの QueryPerformanceCounter) で時間を測定する方法は知っていますが、ワーキング セットに関してサイクルごとの命令またはサイクルごとの読み取り/書き込みをどのように測定するのか疑問に思っています。
これらの値を測定するにはどうすればよいですか?
C/C++ コードを徹底的に測定および調整して、x86_64 システムのキャッシュでパフォーマンスを向上させたいと考えています。カウンター (Windows マシンの QueryPerformanceCounter) で時間を測定する方法は知っていますが、ワーキング セットに関してサイクルごとの命令またはサイクルごとの読み取り/書き込みをどのように測定するのか疑問に思っています。
これらの値を測定するにはどうすればよいですか?
最新のプロセッサ(つまり、20年未満の制約があまりないプロセッサ)はスーパースカラーです。つまり、一度に複数の命令を実行します(命令の順序が正しい場合)。最新のx86プロセッサは、CISC命令を内部RISC命令に変換し、それらを並べ替えて結果を実行します。複数のレジスタバンクを備えているため、「同じレジスタ」を使用する命令を並行して実行できます。今日、「命令の実行にかかる時間」を定義する合理的な方法はありません。
現在のCPUはメモリよりもはるかに高速であり(数百の命令がメモリにアクセスするための一般的なコストです)、パフォーマンスはすべてキャッシュに大きく依存しています。そして、キャッシュの一部を共有する(または共有しない)コアのあらゆる種類の面白い効果があります...
パフォーマンスを最大化するためのコードの調整は、ソフトウェアアーキテクチャから始まり、プログラムの編成、アルゴリズム、およびデータ構造の選択(ここでは、キャッシュ/仮想メモリの認識のわずかな部分も役立ちます)、注意深いプログラミング、および(最も極端な手段として、パフォーマンスの最後の2%)あなたが言及したような考慮事項(そして他のお気に入りの「アセンブリでの書き換え」)。そして、最初のレベルが同じコストでより多くのパフォーマンスを提供するため、順序はそれです。掘り下げる前に測定してください、プログラマーは悪名高いですボトルネックを見つけるのに信頼できない。そして、この複雑なコードが正しいことを自分自身に納得させるために、作業自体とメンテナンスの両方で、パフォーマンスのためにコードを再編成するコストを考慮してください。コンピューターと人の相対的なコストを考えると、極端なパフォーマンスの調整はほとんど意味がありません(おそらく、一般的なオペレーティングシステムで頻繁に移動するコードパス、コンパイラーによって生成される一般的なコードパスでは、ほとんど意味がありません)。
コードがキャッシュにヒットする場所とメモリにヒットする場所に本当に関心があり、プロセッサの設計が約 10 ~ 15 年未満である場合は、プロセッサにパフォーマンス カウンターがあります。これらのレジスタにアクセスするにはドライバ レベルのソフトウェアが必要なので、このための独自のツールを作成したくないでしょう。幸いなことに、その必要はありません。
Intel の VTune、AMD の CodeAnalyst、Linux の oprofile などのツールがあります (AMD と Intel の両方のプロセッサで動作します)。
実際に完了した命令の数、プロセッサが待機しているサイクル数をカウントするさまざまなレジスタの全範囲があります。また、「メモリ読み取り数」、「キャッシュ ミス数」、「TLB ミス数」、「FPU 命令数」などのカウントも取得できます。
次の、よりトリッキーな部分は、もちろん、これらの種類の問題を修正しようとすることです。別の回答で述べたように、プログラマーはこれらの種類の微調整が常に得意であるとは限りません。言うまでもなく、確かに時間がかかります。プロセッサ モデル X でうまく動作するものが必ずしもモデル Y で高速に動作するとは限りません (初期の Pentium 4 には、AMD プロセッサでは非常にうまく動作しないいくつかのチューニング トリックがありました。一方、そのコードをその時代の AMD プロセッサ用にチューニングする場合)。 、同世代の Intel プロセッサでも問題なく動作するコードが得られます!)
相対サイクル数を読み取る rdtsc x86 命令に興味があるかもしれません。
多くのコンパイラでカウンターを読み取るための実装については、http://www.fftw.org/cycle.hを参照してください。
ただし、QueryPerformanceCounter を使用して単純に測定することをお勧めします。実際のサイクル数が重要になることはめったにありません。コードを調整するには、通常、相対時間の測定値を比較するだけでよく、rdtsc には多くの落とし穴があります (ただし、説明した状況にはおそらく当てはまりません)。