1

SHLD命令 ( __shiftleft128 ) を使用してビット ストリームを読み取る単純なビット リーダーがあります。

これはうまくいきます。しかし、私はいくつかのプロファイリングを行っており、命令の後に来るSHLD命令には時間がかかることに気付きました。

    Assembly                    CPU Time    Instructions Retired
add r10b, r9b                   19.000ms    92,000,000
cmp r10b, 0x40                  58.000ms    180,000,000
jb 0x140016fa6 <Block 24>       
        Block 23:       
and r10b, 0x3f                  43.000ms    204,000,000
mov r15, r11                    30.000ms    52,000,000
mov qword ptr [rbp+0x20], r11       
add rbx, 0x8                    16.000ms    78,000,000
mov qword ptr [rbp+0x10], rbx       
mov r11, qword ptr [rbx]        6.000ms     44,000,000
bswap r11                       2.000ms 
mov qword ptr [rbp+0x28], r11   8.000ms     20,000,000
        Block 24:       
mov rdx, r15                    61.000ms    208,000,000
movzx ecx, r10b                 1.000ms     6,000,000
**shld** rdx, r11, cl           24.000ms    58,000,000
inc edi                       **127.000ms** 470,000,000

上の表でわかるように、inc命令の後のshld命令には多くの時間がかかります (8% の CPU 時間)。

なぜそうなるのか、どうしたら回避できるのか、もう少し詳しく知りたいです。CPUレベルでsldと並行して実行できる命令はありますか?

shldAMDの最適化マニュアルを読んだことを覚えていますが、再び見つけることができません。

4

1 に答える 1

1

わかりにくいですが、遅延は何らかの例外処理ルーチンの結果であるようです。

行動

ただし、インテルのマニュアルではshld、未定義の応答が呼び出されるいくつかのケースを指定しています。

デスティネーション オペランドは、レジスタまたはメモリ位置にすることができます。ソースオペランドはレジスタです。カウント オペランドは、即値バイトまたは CL レジスタに格納できる符号なし整数です。カウント オペランドが CL の場合、シフト カウントは CL とカウント マスクの論理積です。非 64 ビット モードおよびデフォルトの 64 ビット モード。カウントのビット 0 ~ 4 のみが使用されます。これにより、カウントが 0 ~ 31 の値にマスクされます。カウントがオペランドのサイズより大きい場合、結果は undefined になります。

カウントが 1 以上の場合、CF フラグはデスティネーション オペランドからシフトアウトされた最後のビットで埋められ、結果の値に従って SF、ZF、および PF フラグが設定されます。1 ビット シフトの場合、符号変化が発生すると OF フラグが設定されます。それ以外の場合はクリアされます。1 ビットを超えるシフトの場合、OF フラグは未定義です。シフトが発生した場合、AF フラグは未定義です。カウント オペランドが 0 の場合、フラグは影響を受けません。カウントがオペランドのサイズより大きい場合、フラグは undefinedです。

sld の例外:-

In Protected Mode --> #GP(0),#SS(0),#PF(fault-code),#AC(0),#UD

更新:: 落とし穴:-->
まず定義:-

Instructions Retired — イベント セレクト C0H、Umask 00H
このイベントは、リタイア時の命令数をカウントします。複数のマイクロオペレーションで構成される命令の場合、このイベントは、命令の最後のマイクロオペレーションのリタイアをカウントします。REP プレフィックスを持つ命令は、1 つの命令としてカウントされます (反復ごとではありません)。multiops 命令の最後の micro-op がリタイアする前のフォルトはカウントされません。
このイベントは、VM 終了条件では増加しません。 カウンターは、ハードウェア割り込み、トラップ、および割り込みハンドラー内でカウントを続けます

inc edi **127.000ms** 470,000,000 (リタイアした命令)
上記の定義から、この命令があまりにも多くのマイクロオペレーションに割り込んでいるか、何らかの割り込みハンドラが同時に実行されていることは明らかです。

于 2012-08-17T19:08:31.410 に答える