2011-12-25 9 views
3

自分のStringBuilderをコンパイル言語(C++など)で記述しています。ベンチマークCPUバインドアルゴリズム/実装

さまざまな実装のパフォーマンスを測定する最も良い方法は何ですか? 1回のバッチから他のバッチへのタイミングが15%も異なることがあり、パフォーマンスの向上を正確に評価できないため、パフォーマンスの向上がそれよりも小さくなる可能性があります。

私は次のことをやった:リアルタイム優先度

  • を持つプロセスは、単一のCPUコア
  • への親和性を設定して実行するタイミング
  • ため

    1. 無効にSpeedStepの
    2. 使用RDTSC

      これは結果をやや安定させました。他のアイデア?

  • +2

    数十万回以上の実行を試してください。各ベンチマークを少なくとも10秒間実行します。 – Mysticial

    +0

    確かに、それは私の転倒計画です。それは少し流れを壊します:) –

    +0

    私の経験から、1秒未満のタイミングは、ハードウェアとパフォーマンスカウンターでも非常に一貫性のない結果をもたらします。 – Mysticial

    答えて

    1

    コードを正確に測定することは本当に難しいです。このような要件については、Agner Fog's test suiteをご覧になることをお勧めします。これを使用すると、クロックサイクルを測定し、いくつかの重要な要因(キャッシュミス、分岐予測ミスなど)を収集することができます。

    また、私はAgnerのサイトからPDF documentをご覧になることをお勧めします。このようなマイクロ最適化を可能にすることは、非常に貴重なドキュメントです。

    実際のパフォーマンスは「クロックサイクル」の機能ではありません。キャッシュミスは、実際のアプリケーション内の各実行ごとにすべてを変更することができます。だから、私はまずキャッシュミスを最適化するだろう。同じメモリ部分に対して複数回コードを実行するだけで、キャッシュミスが劇的に減少します。したがって、正確に測定することは困難です。アプリケーション全体のチューニングは、通常、IMOの方が良いアイデアです。 Intel VTuneと他のツールは、そのような用途には本当に適しています。

    +0

    ありがとう、私はそれをチェックします! –

    +1

    私はすべてのエミュレータが非常に確定的なインオーダーCPUをシミュレートすると信じています。したがって、RDTSCを使用して実際のパフォーマンスを反映することさえできません。私は著者が各命令のためにいくつかの固定クロックサイクルを割り当て、それらをカウントすると信じています。したがって、これは実際のパフォーマンスとは無関係の特別な固定数を数える可能性が非常に高いです。今日、CPUにはいくつかのパイプラインがあることに注意してください。そして、パフォーマンス機能はやや複雑です。 –

    +0

    クロックカウントは、実際のCPUかエミュレートされたCPUのどちらであっても、実際のパフォーマンスを示すものではありませんが、実行間で非常に一貫性がある可能性があるため、 –

    1

    私はこれまで多くのことを心配していましたが、多くの作業を必要とする理想的な解決策である perfect です実際にはこのようにしたことはありません。

    解決策は、386エミュレータを使用してコードを実行することです。このエミュレータは、実行された操作の数を正確に示します。あなたはそこにオープンソースの386エミュレータを見つけることができるはずです。それは指示に正確であり、それはあなたのテストの一回の実行を必要とします。あなたがそれをしたら、あなたがそれをした方法を投稿してください!

    +1

    私はあなたがこれを投稿したときにBOCHSを設定していました:)実際、BOCHSの 'rdtsc'命令は仮想カウンタを返します。したがって、より正確になると思います。 –

    +0

    私はそれをやった!下の私の答えを見てください。 –

    7

    私は、このように100%一致した結果を達成した:

    1. は、MS-DOSとBochsのを設定します。
    2. MS-DOS
      —または—
      1. はBochsの中HX-DOS extenderをインストール
      2. 32ビット版のWindowsをターゲットに、あなたのツールチェーンを設定対象とするあなたのツールチェーンを設定します。
      3. 必要に応じて、ツールキットの標準ライブラリ/ランタイムをハックし、HX-DOSに実装されていないWindows APIが必要な機能をスタブアウト/削除します。エクステンダーは、プログラムを実行しようとすると、実装されていないAPIのリストを出力します。
    3. ベンチマークのサイクル数を数桁減らしてください。
    4. ベンチマークコードをアセンブラcli/sti(この変更後に最新のOSでは実行されないことに注意してください)で囲みます。
    5. まだベンチマークを使用していない場合は、タイミングのためにデルタをrdtscで使用してください。サンプルはcli&hellip内にある必要があります。 sti命令
    6. Bochsで実行してください!

    Bochs screenshot

    結果は完全に決定論的であると思われるが、全体的なパフォーマンス(詳細については、オスマン・トゥランの答えの下で議論を参照)の正確な評価ではありません。ボーナスチップとして


    は、ここに(あなたが毎回リビルド/フロッピーイメージを再マウント/アンマウントする必要はありません)Bochsのとファイルを共有する簡単な方法です:Windowsでは

    を、Bochsのは、意志フロッピーイメージファイルをロックしますが、ファイルはまだ共有書き込みモードで開かれています。つまり、ファイルを上書きすることはできませんが、書き込むことはできます。 (私は* nixのOSは、ファイルディスクリプタに関する限り、新しいファイルを作成するために上書きを引き起こすかもしれないと思う)。トリックはddを使うことです。私は、次のバッチスクリプトを設定していた:

    ... benchmark build commands here ... 
    copy /Y C:\Path\To\Benchmark\Project\test2dos.exe floppy\test2.exe 
    bfi -t=288 -f=floppysrc.img floppy 
    dd if=floppysrc.img of=floppy.img 
    

    bfiはバートのBuild Floppy Imageです。

    次に、Bochsにfloppy.imgをマウントするだけです。


    ボーナス先端#2:手動で、ベンチマークにBochsの中のすべての時間を開始floppyディレクトリに空のgo.txtファイルを置いて、Bochsの中で、このバッチを実行することを避けるために:

    @echo off 
    A: 
    :loop 
    choice /T:y,1 > nul 
    if not exist go.txt goto loop 
    del go.txt 
    echo --------------------------------------------------- 
    test2 
    goto loop 
    

    それ新しいフロッピーイメージを検出するたびにテストプログラムを起動します。このようにして、単一のスクリプトでベンチマーク実行を自動化することができます。


    更新:このメソッドはあまり信頼性がありません。場合によっては、いくつかのテストの順序を変更するだけで、タイミングが200%も変化することがあります(元の質問に記載されている方法を使用して実際のハードウェアで実行した場合、

    +0

    クール! C - :=このジョブには仮想マシン全体を使用しなければならないというのは残念です。ベンチマークのために1組の自己完結型コードのインタプリタで十分であるからです。そのようなものを見つけることが可能ならば! –

    +0

    なぜMS-DOSを使用することをお勧めしますか? [bochs.rc](http://bochs.sourceforge.net/doc/docbook/user/bochsrc.html)でclock:sync = slowdownを設定することができます。 –

    +0

    MS-DOSにはほとんどオーバーヘッドがなく、プリエンプティブなマルチタスキングがないためです。 –

    関連する問題