4

以下は、2 つの Pentium アセンブリ シーケンスのリストからのクリップです。シーケンスのタイミングを計ろうとする外部ループがあり、これらのルーチンに到達するためにコールスルー テーブルを実行しています。したがって、外線通話は毎回同じ場所から行われています。2 つのシーケンスの違いは、最初のシーケンスは 2 番目のシーケンスよりも命令が 1 つ少ないことです。

2 つの Intel マシンで得られる結果は大きく異なります。

CPUID 命令は、ファミリ、モデル、およびステッピングを示します。

マシン 1: ファミリー 6、モデル 15 ステッピング 11. CPUZ が「Intel Core 2 Duo E6750」を報告
命令は統計的に同じ速度で実行されます。

マシン 2: ファミリ 15、モデル 3、ステッピング 3。CPUZ は「Intel Pentium 4」を報告します。
最初のシーケンスは、2 番目のシーケンスよりも約 8% 長くかかります。

時間の増加を説明することはできません。異なるフラグ ホールドオフ、分岐の予測、レジスタの使用に関する問題などがあってはなりません。少なくとも、それはわかりません。

1 台のマシンで最初のシーケンスの実行に時間がかかる理由を知っている人はいますか?

編集: 最初のシーケンスに「XOR PTR ereg, 0」を追加すると、Pentium 4 の 2 番目のシーケンスとタイミングが一致します。

最初のシーケンス:

00000040               ALUSHIFT_AND_C_V_E LABEL NEAR
00000040  0F B7 04 55       MOVZX   EAX, gwr[(SIZEOF WORD) * EDX]       ; EAX = 0000000000000000 LLLLLLLLLLLLLLLL
   00000000 E
00000048  0F B7 14 4D       MOVZX   EDX, gwr[(SIZEOF WORD) * ECX]       ; EDX = 0000000000000000 RRRRRRRRRRRRRRRR
   00000000 E
00000050  23 C2             AND     EAX, EDX                            ; AX = L&R      (result)
00000052  A3 00000000 E     MOV     dvalue, EAX                         ; Save the temporary ALU/Shifter result
00000057  C3                RET                                         ; Return

2 番目のシーケンス:

00000060               ALUSHIFT_AND_C_V_NE LABEL NEAR
00000060  0F B7 04 55       MOVZX   EAX, gwr[(SIZEOF WORD) * EDX]       ; EAX = 0000000000000000 LLLLLLLLLLLLLLLL
   00000000 E
00000068  0F B7 14 4D       MOVZX   EDX, gwr[(SIZEOF WORD) * ECX]       ; EDX = 0000000000000000 RRRRRRRRRRRRRRRR
   00000000 E
00000070  23 C2             AND     EAX, EDX                            ; AX = L&R      (result)
00000072  80 35 00000000 E  XOR     BYTE PTR ereg, 1                    ; E = ~E
   01
00000079  A3 00000000 E     MOV     dvalue, EAX                         ; Save the temporary ALU/Shifter result
0000007E  C3                RET                                         ; Return
4

4 に答える 4

3

Pentium I または II の後では、コンパイラによって実行されるほとんどの最適化は必要ありませんでし。チップはこれらの命令をマイクロオペレーションに分解し、最適化します。t は、チップ間の分岐予測の違い、または XOR + RET が単純な RET と同じくらい高価であるという事実である可能性があります。あなたが上で見ているペンティアムのモデルについては、私はよく知りません。もう 1 つの可能性は、キャッシュ ラインの問題またはハードウェアの違いである可能性もあります。

インテルのドキュメントに何かがあるかもしれませんし、ないかもしれません。

関係なく。経験豊富なアセンブリ コーダーは、テストによって唯一の真実が得られることを知っています。

于 2009-07-08T16:57:08.063 に答える
1

増加の原因となるコードが配置されている場所との興味深い相互作用があることが判明しました。すべてがキャッシュ アライメントされているにもかかわらず、コードのブロックを切り替えると、Pentium-4 での時間が増加しました。

これを調査したり、見たりするために時間を割いてくれたすべての人に感謝します。

于 2009-07-10T14:35:47.547 に答える
0

このコードの前に1つ、2つなどのnopを追加して(そして他に何も変更せずに)、これがキャッシュ内のどこにあるかを移動して、キャッシュ効果があるかどうかを確認できます(または単にキャッシュをオフにします)。警告ですが、追加のnopだけで、PCアドレス指定に関連して使用しているものに到達できなくなった命令を他の場所に変更でき、命令バイトが増える可能性があり、テスト対象のコードが必要以上に移動する可能性があります。変更する他の比較的対処された指示。

キャッシュゲームをプレイする場合でも、ここでの獣の性質は、1つの命令ストリームを受け取り、それを実行ユニット間で分割するチップ内の魔法です。

微調整とテストは、理由がわからなくても、最終的にパフォーマンスを実際に得るものです。ただし、そのコードを古いチップ、新しいチップ、別のマザーボード、または同じチップファミリに移動するとすぐに、パフォーマンスを微調整することで、すべてのパフォーマンスが向上する可能性があります。

于 2009-07-13T19:41:28.003 に答える
0

数ヶ月前、私も似たようなことがありました。__thread私のプロジェクトには、スレッドローカル変数の使用を有効にするための構成スイッチがあります。それがなければ、それは使用pthread_getspecificなどです。__thread後者は、バージョンに加えて、関数呼び出しに加えて、引数の設定、レジスタの保存などのためのいくつかの追加命令と同じくらいすべてのビットを実行します。興味深いことに、面倒なバージョンは一貫して高速でした。ただし、Pentium 4 のみ。他のすべてのチップは正常に動作しました。

于 2009-08-06T06:19:54.700 に答える