1

いくつかのテスト目的で、リアルタイムビデオ処理コードでいくつかの高速操作の実行時間を測定するためのコードを作成しました。そして、物事はうまく機能しています。非常にリアルな結果が得られていますが、興味深い特徴が1つあります。

属性付きのPOSIX関数を使用しています。したがって、ナノ秒の精度(1 / 1000000000秒)でtimespecを取得しており、その方法でtimespec値を取得するには、数プロセッサティックしかかからないと言われています。clock_gettimeCLOCK_MONOTONIC

これが私がtimespecsを保存するために使用している2つの関数です。また、使用されているデータ構造の定義を追加しました。

QVector<long> timeMemory;
QVector<std::string> procMemory;
timespec moment;

void VisionTime::markBegin(const std::string& action) {
    if(measure){
    clock_gettime(CLOCK_MONOTONIC, &moment);
    procMemory.append(action + ";b");
    timeMemory.append(moment.tv_nsec);
    }
}

void VisionTime::markEnd(const std::string& action) {
    if(measure){
    clock_gettime(CLOCK_MONOTONIC, &moment);
    procMemory.append(action + ";e");
    timeMemory.append(moment.tv_nsec);
    }
}

結果を、後で使用するいくつかのQVectorに収集しています。

これらの2つの関数が初めて実行されたとき(互いに直後、間に何もない)、2つの保存された時間仕様の差は約34000nsであることに気付きました。次回は差が約2分の1になります。等々。それらを何百回も実行すると、平均差は約2000nsになります。したがって、これらの関数の平均的な繰り返し実行にかかる時間は、最初の関数の約17000分の1です。私は何百もの測定を続けて行っているので、最初の実行が少し長く続くことは私にとって実際には重要ではありません。しかし、とにかくそれは私に興味があるだけです、なぜそれはそのようですか?

私はJavaでさまざまな経験がありますが、C++はまったく初めてです。ここで物事がどのように機能するかはよくわかりません。最適化レベルにO3フラグを使用しています。私のQMakeconf: QMAKE_CXXFLAGS += -O3 -march=native

それで、誰もがこの小さなコードのどの部分が実行時に速くなるか、どのようにそしてなぜかを知ることができますか?QVectorに追加するのは疑わしいです。最適化はこれに何らかの影響を及ぼしますか?

これがstackoverflowに関する私の最初の質問です。長すぎないことを願っています:)すべての回答に感謝します!

4

2 に答える 2

3

おそらく分岐予測によるものです。http://en.wikipedia.org/wiki/Branch_predictor

于 2012-09-25T21:06:53.037 に答える
3

測定コードにはかなりの数の潜在的な初回コストがあります。ここにいくつか、それらをテストする方法を示します。

メモリ割り当て:これらのQVectorには、初めて使用するまでヒープにメモリが割り当てられません。

また、ベクトルはほとんどの場合、少量のメモリを割り当てることから始まり、データを追加するにつれて指数関数的に割り当てられます(このようなコンテナの標準的な妥協案)。したがって、ランタイムの開始に向けて多くのメモリが割り当てられ、その後、頻度は時間の経過とともに減少します。

の戻り値を確認することでこれが発生していることを確認し、次QVector::capacity()のように動作を調整QVector::reserve(int)できます。たとえば、を実行するtimeMemory.reserve(10000);procMemory.reserve(10000);、測定を開始する前に最初の1万回の測定に十分なスペースを確保できます。

レイジーシンボルバインディング:動的リンカーは、デフォルトでは、必要になるまでQt(または他の共有ライブラリ)からのシンボルを解決しません。したがって、これらの測定関数がコード内でいくつQVectorstd::stringの関数が呼び出される最初の場所である場合、ダイナミックリンカはこれらの関数を解決するために1回限りの作業を行う必要があり、これには時間がかかります。

これが実際に当てはまる場合は、LD_BIND_NOW=1LinuxまたはDYLD_BIND_AT_LAUNCH=1Macで環境変数を設定することにより、遅延読み込みを無効にすることができます。

于 2012-09-26T03:30:46.397 に答える