2016-02-22 8 views
5

私は画像処理を行うポータブルCライブラリを開発してきました。Cでテストパフォーマンスの最適化をどのようにユニット化できますか?

私はGCCの自動ベクトル化(ターゲットプロセッサに応じてSSEまたはAVX)モードを利用するために、いくつかの低レベル関数にかなりの時間を費やしていますが、やはり移植性の高いCコード使用:restrictおよび__builtin_assume_aligned)。

Windows上でコードをテストする時間です(MSVCコンパイラ)。しかし、その前に、GCCの自動ベクトル化コードをそのまま保存するために、自分の足を踏み外したり、慎重に選択したすべての指示を緩和したりしないように、何らかのユニットテストをセットアップしたいと思います。

私は単純に#ifdef/#endifの全身機能を使うことができましたが、どの回帰のコンパイラアップデートでも検出するより長期的な解決策を考えています。

私は単体テストにかなり自信があります(そこにはたくさんの良いフレームワークがあります)が、私はそのような低レベルの機能の単体テストには自信がありません。ジェンキンなどのCIサービスでパフォーマンスユニットテストをどのように統合するのですか?

PS:私は、例えば、特定のプロセッサに基づいてハードコーディングされたタイミング結果を保存しないようにしたい:私はあなただったら、あなたはMSVCを使用するには、いくつかの良い理由を持っていると仮定すると

// start timer: 
gettimeofday(&t1, NULL); 
// call optimized function: 
... 
// stop timer: 
gettimeofday(&t2, NULL); 
// hard code some magic number: 
if(t2.tv_sec - t1.tv_sec > 42) return EXIT_FAILURE; 
+1

最適化されていない(汎用)関数がありますか?実行時間を比較すると良いでしょう... 't_opt'は' t_non_opt'よりも小さいと予想されますが、それでも100%の保証はありません。他のプロセスがランダムにディスクにアクセスすると、あなたのテストはいつでもプリエンプションになる可能性があります。あなたのテストでは他のことが起こるかもしれません... – zaufi

+0

あなたは何を目指していますか?コードを修正した後、コードが正しく(ユニットテストを行う)、結果コードのパフォーマンスを確認したいのですか(何か違っていて、さまざまな方法でアプローチされる可能性がありますか?)後者の場合は、生成されたアセンブリコードを出力して期待と比較することもできます。 –

+0

@DirkHerrmannそれは全体のポイントです! 「ポータブル」アセンブリコードを印刷するにはどうすればよいですか?これは正確なgccのバージョンに依存するかもしれません。 – malat

答えて

-1


私は周りの干渉を減らすために、可能な限り低レベルの方法に固執します。
したがって、テストに適切なフレームワークを使用したい場合でも、所定のパラメータでタイマーを適切な場所にアタッチしてキー機能を呼び出している単純なループは、選択肢よりも信頼性の高い結果を提供します。タイミングの結果の基本的な平均値と標準偏差を計算することができれば、何がパフォーマンスよりも遅くなったり遅くなったりするのか、非常に明確な画像が得られます。

1

あなたの問題は、基本的に2つの部分に分かれています。

  1. 慎重に最適化されたコードをパフォーマンスベンチマークする最良の方法は何ですか?

  2. あなたが検知できるように、コードの変更および/またはコンパイラのアップデートが google benchmarkフレームワークは問題#に合理的なアプローチを提供するかもしれない

コードのパフォーマンスに影響を与えた場合の比較の結果を比較する方法

  • 1。これはC++ですが、C関数を呼び出すのは止めません。

    このライブラリは、JSONや古いCSVなどのさまざまな形式の要約レポートを作成できます。これらを実行ごとにどこかに格納するように手配することができます。

    単純なperl/python/etcスクリプトを書いて、ベンチマークの結果を比較し、それらが何らかのしきい値を超えた場合にアラームを発生させることができます。

    注意しなければならないことは、テストを実行しているシステムの負荷などの変数に起因する結果のノイズの可能性があることです。テストを実行している環境についてはあまり言いませんでしたが、他のVMを含むホスト上の(たとえば)VMの場合は、他のVMで何が起きていてもテスト結果が歪んでしまう可能性があります。

    JenkinsのようなCIフレームワークでは、テストを実行するときに実行するアクションをスクリプト化できるため、このアプローチをそのようなフレームワークに統合するのは比較的簡単です。

  • 1

    単純かつ繰り返し可能な方法でパフォーマンスを測定する方法は、valgrind/callgrindを通じてベンチマーク単位テストを実行することです。これにより、のCPUサイクル、命令とデータのリードとライトのトランザクション(異なるキャッシュ深度での)、バス遮断トランザクションなどが得られます。これらの値は、既知の良好な開始値。

    Valgrindはコードの実行をエミュレートするので繰り返し可能です。それはコードを直接実行するよりもはるかに遅いですが、システムの負荷などから独立しています。

    ここで、Valgrind + wine + Windowsプログラムの記述はありますがLinuxの場合)、dynamoRIOはオプションです。 Valgrindに似たツール、命令カウンタ、メモリ、キャッシュ使用量アナライザなどを提供します。 (Linuxでも利用可能で、この記事の執筆時点でOS Xに半分移植されているようです)

    +1

    はウィンドウ上で移植可能ではありませんが、テストのタイミング以上の詳細は少なくともあります。 – malat

    +0

    valgrind +ワインの設定の言及がありますが、ええ、それは複雑になるかもしれません。 – hmijail

    +0

    @malat、まだ作業している場合は、Windows用のvalgrindのさまざまなツールに相当するものを見つけました:http://dynamorio.org/(「命令カウントツールのカウントダウン」および「マルチプロセスオンラインキャッシュシミュレータdrcachesim ") – hmijail

    関連する問題