web-dev-qa-db-ja.com

同じ条件(RAM、CPUキャッシングなど)でソフトウェアのパフォーマンスをベンチマークする方法は?

大きなファイルを小さなファイルに分割するソフトウェアを書いていて、いくつかのソリューションをコーディングしています。

私は各ソリューションの実行時間を測定しています。 (スレッドあり、goルーチンあり、MPI etc))、それらを客観的に比較したい。

同じソリューションを1回以上実行すると、実行時間が短くなり、データの一部がメモリ階層(RAMまたはCPUレジスタなど)にキャッシュされるために発生することを理解しています。

これらの影響を取り除くことにより、テストをより客観的で再現可能なものにしたいと考えています。各テストを白紙の状態で実行したい。

PCを再起動してパフォーマンスを再度測定すると、以前のデータからRAMが空になり、結果は大丈夫です。 PCを復元せずにそれを行う方法はあるのでしょうか?

この種のテストを行う最良の方法は何ですか?私は次のようなことをしたい:a.exeを実行して時間を測定し、すべてのRAMをクリーンアップし、このデータについてキャッシュされたものをCPUに登録するN回繰り返す

次に、aの平均速度、bの平均速度を計算し、最後にデータを比較できます。

私はたくさん研究していて、役に立つリソースを見つけることができなかったので、いくつかの情報を提供してください。オプションで、これを実現するためのプログラム可能な方法が必要です。ベンチマークパイプラインに追加ツールを統合するいくつかの方法。

これまでに試したこと:

  1. キャッシングが問題であると指摘するためだけにPCを再起動します
  2. 毎回、Dockerコンテナー内でソフトウェアを実行します。良かったがとても遅い

前もって感謝します !

2
Kristi Jorgji

同じソリューションを1回以上実行すると、実行時間が短くなり、データの一部がメモリ階層(RAMまたはCPUレジスタなど)にキャッシュされるために発生することを理解しています。

したがって、同じ "ソリューション"を数回(たとえば、まったく同じものを5回実行)実行し、それらすべてをベンチマークする必要があります。次の質問は、どのタイミングが最も適切であるかです。最悪のものを選択することもできます(おそらく初めて)、またはそれらの平均を検討することも、最悪および最良の実行を無視して残りの部分のみを気にすることなどもできます。

一般に、コンピュータ(およびそのオペレーティングシステム)は完全に確定的ではないため、まったく同じ条件でソフトウェアをベンチマークすることはできません。 正確にいくつかの走行条件を再現することができます。したがって、いくつかのベンチマークを作成する必要があります。また、「開始」または「コールドスタート」操作は一般的な実行条件ではありません(ただし、特別な場合)ので、通常は無視してください。

ハードウェアはnon-deterministic:CPU cache 動作であることに注意してください。 CPUパイプライン処理スーパースカラーアウトオブオーダー実行 、外部 割り込み -タイマー、ネットワーク、USBディスク、...-そしておそらく CPU周波数 -チップが高すぎる場合に制限-はソフトウェアの制御なしで変化します。したがって、カーネル scheduler は実行ごとに異なる動作をします(プリエンプティブスケジューリングのため...)。 OSについての詳細は オペレーティングシステム:3つの簡単な部分 もご覧ください。一部のソフトウェアレイヤー(例: [〜#〜] aslr [〜#〜] )は、非決定性をさらに追加する可能性があります。

あなたの場合、平均時間を考慮したいと思います。実際には、実際にプログラムを使用するときに、一部のデータがすでに「ここ」にある(たとえば ページキャッシュ にある)可能性が高くなります。

あなたの場合、「冷たい」状態を測定することは現実的ではないと思います。巨大なファイルを分割するとき、それは数秒または数分前に生成(またはダウンロード、または取得)されている可能性が高いため(分割する前に数時間待つ必要があるため)、本当に「ウォーム」状態に関心がある、そして実際には、ページキャッシュに(部分的に)含まれている可能性があります。

詳細は明らかにコンピュータ、オペレーティングシステム、およびファイルシステムに固有です。システムが確定的であり、複数の実行に対して同じタイミングを与えることを期待しないでください。したがって、ベンチマークは正確に再現できません。

最後に、あなたの問題(それぞれ数百ギガバイトの巨大なファイルを分割すること)はおそらくCPUにバインドされているのではなく、ディスクIOにバインドされているので、少なくともバッファーに適切なサイズ(少なくとも128キロバイト、そしておそらく数メガバイト; setvbuf(3) ...を参照)。ファイルが大きくなく、ページキャッシュに完全に収まる場合(たとえば、ほとんどのファイルに数ギガバイトがある場合)は、状況が異なる場合があります。

ところで、Linuxでは、 posix_fadvise(2)readahead(2) のようなシステムコールに興味があるかもしれません。適切に使用すると、全体的なパフォーマンスが向上する可能性があります。そして、あなたは csplit(1) または split(1) を再発明しているようです。なぜあなたのニーズに十分ではないのですか?また、なぜそれだけ最適化する必要があるのですか(開発者の時間は、プログラムを実行しているコンピューターよりも多くかかることに注意してください)。

1日あたり数ギガバイトの数千のファイルを分割するか、または少なくとも数百ギガバイトの1日あたり数十のファイルを分割することに興味がありますか?これらは2つの異なる問題です! (私はあなたがいくつかの普通のデスクトップを持っていると思います)。そして、これらのファイルはどこから来たのですか?彼らはどのようにあなたのディスクに着陸していますか?どのディスクテクノロジーとファイルシステム(SSD、回転ハードディスク、リモートファイルシステム)?

PS。私はあなたの質問に驚いています。テキストファイルの分割(数千行など)は問題にならず、満足のいく方法で簡単にコーディングできます(バッファーが十分に大きい場合)。このような分割パフォーマンスが非常に重要になる状況(数日の作業時間を正当化するほど)は想像できません。あなたはあなたの文脈を説明し、それをはるかに動機づける必要があります。もちろんバイトサイズは重要です!