HN 日本語サマリー

← 一覧へ戻る
プログラミング

Assembly Hall of Shame

Assembly Hall of Shame (github.com)

402 pointsby piotrgrabowski99 コメント

要約

「Assembly Hall of Shame」は、単一命令のパフォーマンスの絶対的な最低ラインを追求するプロジェクトです。x86アーキテクチャでは、fxrstor64命令がPCIeファブリックの遅延を利用して、198,002,498,236サイクルという驚異的な実行時間を記録し、現在のチャンピオンとなっています。このプロジェクトでは、意図的に命令の実行時間を長くする方法を探求しています。

全文翻訳

Assembly Hall of Shame 概要 レイテンシ分析は通常、コードを可能な限り高速に実行するためのパフォーマンス最適化に焦点を当てます。「Assembly Hall of Shame」は、その逆のアプローチを取ります。単一命令のパフォーマンスの絶対的な最低ラインを追求します。 🏆 現在のチャンピオン 🏆 x86: fxrstor64 戦略: fxrstor64を使用して、PCIeファブリック内の高レイテンシMMIO領域から512バイトのFPU/MMX/XMM状態をロードします。その後、ロードが進行中にファブリックを枯渇させます。多数のコアが、投稿されないトランザクションでPCIeルートコンプレックスとエンドポイントを飽和させる別の高レイテンシMMIOレジスタをタイトな4バイト読み取りで攻撃します。これにより、CPU 0の512バイトのfxrstor64は、その競合トラフィックのすべてをキューイングしなければならなくなります。 対戦相手: AMD Ryzen 7 5800H; CPU 0 — タイミングされた命令 movl $0xfcc68830, %rsi fxrstor64 %rsi ; CPUs 1..N — 別の高レイテンシの場所にハンマーループ movl 0xfcc68858, %eax 🏆 スコア: 198,002,498,236 サイクル 🏆 時間: 62 秒 栄誉賞 GPUレジスタの停止によって引き起こされた、非投稿型dwordトランザクションを強制した仕様違反の非アラインメントymm0ロードが、smiiiiiiiiiiiiiiiiにおけるシステム管理モードの基本的な設計を破壊するために使用されました。 vmovdqu 0xfcc003b1, %ymm0 ルール 命令は必要なセットアップをすべて使用できますが、スコアリングの対象となるのは単一の命令のみです。 トラップされた/エミュレートされた/仮想化された命令は、ハンドラーではなくトラップのみをタイミングできます。 命令は割り込み可能であってはなりません。 rep movs, pauseなどは失格となります。 時間はCPUのベースクロック周波数に基づいて正規化されます。 すべてのプラットフォームは工場出荷時の構成である必要があります - ハードウェアの変更はありません。 x86 リーダーボード 27. nop 戦略: nopは何もしません。リーダーボードをそれに応じて開きます。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz nop スコア: 1 サイクル 時間: 0 ナノ秒 26. nop16 戦略: 通常のnopは短すぎましたが、何もしないことをより長くするにはどうすればよいでしょうか?長いnopを試してみてください。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz data16 data16 data16 data16 data16 data16 data16 nopl 0x00000000(%%eax,%%eax,1) スコア: 20 サイクル 時間: 7 ナノ秒 25. rdtsc 戦略: 方向感覚を得るための単なる参照命令です。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz rdtsc スコア: 49 サイクル 時間: 18 ナノ秒 24. idiv 戦略: 128ビットの被除数(rdx:rax=2:0)と小さな除数を使用して、商を符号拡張によって課される上限を超えさせ、除算器マイクロコードの最も長いパスを駆動します。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz xorq %rax, %rax ; rax = 0 (被除数の下位64ビット) movq $2, %rdx ; rdx = 2 (上位64ビット: 完全な被除数 = 2^65) movq $5, %rbx ; 除数 → 商 = 2^65/5 ≈ 7.4×10^18 idivq %rbx スコア: 77 サイクル 時間: 28 ナノ秒 23. enter 戦略: 最大ネスト深度(31)を使用して、マイクロコードのディスプレイウォークパスを通じて30個のディスプレイポインタのロードとプッシュを強制します。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz enter $0, $31 ; 0 バイト割り当て、ネスト深度 31 (最大) スコア: 112 サイクル 時間: 41 ナノ秒 22. fldl 戦略: FPマイクロコードアシストをトリガーするために小さな非正規数を試します。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz movabsq $0x0000000000000001, %rax movq %rax, -8(%rsp) fldl -8(%rsp) スコア: 133 サイクル 時間: 49 ナノ秒 21. clflush 戦略: キャッシュラインがダーティであることを確認します。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz clflush (%rax) ; rax -> L3に常駐するダーティキャッシュライン スコア: 165 サイクル 時間: 60 ナノ秒 20. fsin 戦略: 指数0x7ffを使用して「特殊値」処理にマイクロコードで到達します。正/負、NaN/infは関係ないようです。QNaNを使用します。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz movabsq $0x7fffffffffffffff, %rax movq %rax, -8(%rsp) fldl -8(%rsp) fsin スコア: 257 サイクル 時間: 94 ナノ秒 19. mfence 戦略: movntiストアを使用して書き込み結合ラインフィルバッファをすべて異なるキャッシュラインに飽和させ、mfenceがフルLFB書き込みパスをアンコアにドレインしてからリタイアするように強制します。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz movnti %r9, 0*64(%rdi) ; ×16 個の異なるキャッシュライン — 書き込み結合LFBを飽和させる ; … movnti %r9, 15*64(%rdi) mfence ; リタイア前にすべての保留中のLFB書き込みをドレインする必要がある スコア: 326 サイクル 時間: 120 ナノ秒 18. mov cr3 戦略: 現時点では何もありません。TLBを無効にするのにどれくらいの時間がかかるかを確認するだけです。 対戦相手: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5) mov %rax, %cr3 スコア: 352 サイクル 時間: 110 ナノ秒 17. fadd 戦略: 非正規ソースオペランドを使用してx87 FPマイクロコードアシストパスにヒットします。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz fldl subnorm ; 1e-310: 値 < DBL_MIN, バイアス付き指数 = 0 faddl subnorm ; ソースは非正規 → FPマイクロコードアシスト スコア: 677 サイクル 時間: 249 ナノ秒 16. split lock 戦略: lockプレフィックス付きオペランドをキャッシュライン境界をまたぐようにアラインメントし、CPUが高速MESIキャッシュコヒーレンスパスを使用する代わりに外部バスロックをアサートするように強制します。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz ; split_ptr % 64 == 63 — dwordはバイト63 (ラインN) と64–66 (ラインN+1) にまたがる lock xaddl %r9d, (%rdi) スコア: 865 サイクル 時間: 319 ナノ秒 15. fdiv 戦略: 非正規除数を使用します。ハードウェアはマイクロコードアシストに制御を渡します。アシストはオペランドを正規化し、除算を実行し、その後アーキテクチャ状態を復元します。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz movabsq $0x3ff0000000000000, %rax ; 1.0 (正規の被除数) movq %rax, -8(%rsp) fldl -8(%rsp) ; ST(0) = 1.0 movabsq $0x0000002000000000, %rax ; 6.79e-313 (非正規除数) movq %rax, -8(%rsp) fdivl -8(%rsp) ; ST(0) = 1.0 / 非正規 → FPアシスト スコア: 883 サイクル 時間: 325 ナノ秒 14. cpuid 戦略: rakefieldを使用して、最もレイテンシの高いCPUIDリーフを見つけます。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz movl $6, %eax cpuid スコア: 1248 サイクル 時間: 460 ナノ秒 13. rdrand 戦略: タイトなループで実行し、ハードウェアエントロピープールが補充されるよりも速く枯渇させ、エントロピーソースが回復するのを待つように後続の呼び出しをブロックさせます。 対戦相手: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz rdrand %rax スコア: 5,579 サイクル 時間: 2.057 マイクロ秒 12. wrmsr 戦略: project:nightshyftを使用して、高レイテンシMSRを特定します。ZenのMCG_CTLは勝者のようです。マイクロコードのクワイエットと、ハードウェアユニット間のMCAエラーバンクの同期を行う可能性があります。一部はオフダイである可能性があり、単純なローカルレジスタ書き込みではなく、ファブリックレベルの通信が必要です。 対戦相手: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5) movl $0x17b, %ecx ; MCG_CTL wrmsr スコア: 34,304 サイクル 時間: 10.742 マイクロ秒 11. out 戦略: NICデバイスレジスタ境界をまたぐI/Oポートをターゲットにし、各書き込み時にデバイスがTX DMAエンジンをクワイエットするようにトリガーします。 対戦相手: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5) mov $0xf019, %dx পরিমাণl %eax, %dx スコア: 49,857 サイクル 時間: 15.580 マイクロ秒 10. rdmsr 戦略: project:nightshyftを使用して、高レイテンシのモデル固有レジスタを特定します。VIAは0x133にある文書化されていないレジスタを使用しており、非常に高い応答時間を示します。それが何をするのかは不明です。 対戦相手: VIA Eden Processor 800MHz movl $0x133, %ecx ; 文書化されていないMSR rdmsr スコア: 161,602 サイクル 時間: 202.004 マイクロ秒 9. wbinvd 戦略: L1/L2/L3キャッシュをダーティラインで完全にロードし、階層全体のDRAM書き戻しを強制します。 対戦相手: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5) wbinvd スコア: 1,616,480 サイクル 時間: 506.165 マイクロ秒 8. in 戦略: ACPI PMブロックにマップされたI/Oポートをターゲットにします。ここで非アラインメント4バイト読み取りが、このポートがどこへ行くのか分からない複数の非投稿型ロードにデコードされます。 対戦相手: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5) mov $0x0413, %dx inl %dx, %eax スコア: 12,524,415 サイクル 時間: 3.921769 ミリ秒 7. mov 戦略: mmioticを使用して、PCIeファブリック内の高レイテンシのデッドスペースを特定し、未知のGPUレジスタにヒットします。 対戦相手: AMD Ryzen 7 5800H with Radeon Graphics (Trigkey S5) movl 0xfcc003b0, %esi スコア: 443,937,696 サイクル 時間: 139.010268 ミリ秒 6. mov rax 戦略: MMIO空間で最も遅いレジスタを検索します