9

x86 CPU にあるタイムスタンプ レジスタ (TSR) を使用してベンチマーク パフォーマンスを測定することを検討しています。クロック速度の変化の影響を受けない単調な時間単位で測定するため、これは便利なレジスタです。とてもかっこいい。

これは、パイプライン同期に cpuid を使用するなど、TSR を使用して確実にベンチマークを行うための asm スニペットを示す Intel ドキュメントです。16ページ参照:

http://www.intel.com/content/www/us/en/embedded/training/ia-32-ia-64-benchmark-code-execution-paper.html

開始時刻を読み取るには、次のように表示されます (少し注釈を付けました)。

__asm volatile (
    "cpuid\n\t"             // writes e[abcd]x
    "rdtsc\n\t"             // writes edx, eax
    "mov %%edx, %0\n\t" 
    "mov %%eax, %1\n\t"
    //
    :"=r" (cycles_high), "=r" (cycles_low)  // outputs
    :                                       // inputs
    :"%rax", "%rbx", "%rcx", "%rdx");       // clobber

と の値を取得するためにスクラッチ レジスタが使用される理由が気にedx なりeaxます。movs を削除して、 と から TSR 値を読み取ってみませんedxeax? このような:

__asm volatile(                                                             
    "cpuid\n\t"
    "rdtsc\n\t"
    //
    : "=d" (cycles_high), "=a" (cycles_low) // outputs
    :                                       // inputs
    : "%rbx", "%rcx");                      // clobber     

これにより、2 つのレジスタが節約され、C コンパイラがスピルする必要が生じる可能性が低くなります。

私は正しいですか?それとも、それらの MOV は戦略的なものですか?

(そのシナリオでは命令の順序が逆になるため、停止時間を読み取るためにスクラッチ レジスタが必要であることに同意します。rdtscp、...、cpuid があります。cpuid 命令は rdtscp の結果を破棄します)。

ありがとう

4

2 に答える 2

6

おっしゃるとおり、例が不格好です。 通常、 ifmovが inline-asm ステートメントの最初または最後の命令である場合、それは間違っています。制約を使用して、入力が必要な場所または出力がどこにあるかをコンパイラに伝える必要があります。

私の GNU C inline asm guides / links collection、およびタグ wikiの他のリンクを参照してください。( タグの wiki にも、一般的に asm に関する優れた情報が満載です。)


またはrdtsc具体的には、「CPU サイクル カウントを取得しますか?」を参照してください。__rdtsc()@Mysticialの回答にある組み込みの優れたインラインasmについて。


クロック速度の変化に影響されない単調な時間単位で測定します。

はい、過去 10 年以内に製造された CPU では可能です。

プロファイリングでは、実時間ではなく、コア クロック サイクルで時間を持つ方が便利な場合が多いため、マイクロベンチマークの結果は省電力/ターボに依存しません。 パフォーマンス カウンターは、これ以外にも多くのことを行うことができます。

それでも、リアルタイムが必要な場合rdtscは、それを実現するためのオーバーヘッドが最も少ない方法です。


そして、コメントでの議論:はいcpuid、シリアル化する必要がrdtscあります.CPUIDの後まで、および次の命令が実行を開始できないことを確認してください. RDTSC の後に別の CPUID を配置することもできますが、それによって測定のオーバーヘッドが増加し、精度/精度がほぼゼロになると思います。

LFENCE は、RDTSC で役立つ安価な代替手段です。命令リファレンスのマニュアル エントリには、それ以降の命令の実行が開始されず、前の命令が(コアの順序が正しくない部分の ROB/RS から)リタイアするまで実行されないという事実が記載されています。並べ替えられる命令はロードとストアだけですか? を参照してください。、およびそれを使用する具体的な例については、「clflush to invalidate cache line via C function 」を参照してください。のような真のシリアル化命令とは異なりcpuid、ストア バッファをフラッシュしません。

(最近の AMD CPU では、Spectre 軽減策が有効になっておらず、部分的にシリアライズすらされておらず、Agner Fog のテストlfenceによると、1 クロックあたり 4 で実行されます 。AMD プロセッサで LFENCE はシリアライズされていますか? )

Margaret Bloom は、この便利なリンクを掘り起こしました。これは、LFENCE が Intel の SDM に従って RDTSC をシリアル化することも確認しており、RDTSC の周りでシリアル化を行う方法について他の情報を持っています。

于 2016-08-17T17:28:08.437 に答える