Intel x86 プロセッサの命令セットを調べているときに、「mov」、「add」、「mul」などの「直感的な」命令があることに気付きましたが、「sete」のように少し不自然に見えるものもあります。問題は、実際的な懸念というよりはむしろ好奇心からです。なぜ設計者は特定の実行シナリオを単一の命令で実装することを選択したのでしょうか? そのような設計上の決定を説明する読み物を知っていますか?
3 に答える
「特定の実行シナリオ」が命令の妥当な候補であるかどうかを決定するために設計者が使用するいくつかの基準:
ステートレスな動作- 操作は、オペランドまたは実行時の目に見えるマシンの状態 (算術フラグなど) のみに依存する必要があります。非表示状態は許可されていません。この制限により、命令が完了したように見えた後もビジーのままであるノンブロッキング命令が除外されます。
限られたメモリのタッチ- メモリ アクセスは、多くの場合レート リミッタです。コード密度を向上させる以外に、メモリのボトルネックのために両方が同じように実行される場合、個別の操作を 1 つの大きな命令に結合しても意味がありません。
計算的に興味深い- 新しい命令は、他の方法よりも効率的に何かを行う必要があります。x86 AES 命令は極端な例です。ビットスウィズルのような比較的単純な操作も、頻繁に発生する場合は重要です。
ビジネス価値- 命令を実装するためのシリコン領域と検証作業は、それ自体で採算が取れますか?
互換性値- 最後になりましたが、多くの命令は、レガシー ソフトウェアをサポートする以外の理由で存在しません。
コードを実現するために、少なくとも2つの可能なシーケンスがあります。これが私の分析です
; "classic" code
cmp edx,15
jne past
mov al,20
past:
と
; "evolved" code
cmp edx,15
sete al,20
条件付きの単純な割り当てには、単一の命令のみをジャンプする場合でも、反対の条件での条件付きジャンプが「含まれるべき」という考え方が少しあります。しかし、それは-あなた自身の言葉で-頻繁に発生する特定の実行シナリオなので、より良い代替案が利用可能であるなら、なぜですか?
コードが実行されるとき、実行速度に影響を与える多くの要因があります。そのうちの2つは、比較/算術/ブール演算の結果がフラグレジスタに到達するのにかかる時間であり、もう1つは、ジャンプが行われたときの実行ペナルティです(これを少し単純化しすぎています)。
したがって、従来のコードは移動を実行するか、ジャンプします。前者はおそらく他のコードと並行して実行され、後者はプリフェッチャーが新しい位置からデータをロードして待機状態になる可能性があります。プロセッサの分岐予測が関与している可能性があり、多くの要因に応じて、誤って予測し、追加のペナルティが発生する可能性があります。
進化したケースでは、preftecherはまったく影響を受けず、実行速度に優れています。また、seteシーケンスは、おそらくmov + jneコンボよりも少ないバイト数に収まります。つまり、実行に含まれるコードキャッシュラインの容量/作業は比較的少なくなります。つまり、データキャッシュの容量/作業は比較的多くなります。良い。割り当ての内容がすぐに必要ない場合は、seteを、周囲のコードと(実行に関して)よりよく調和する位置に再スケジュールすることができます。この再スケジュールは、明示的に(コンパイラーによって)または暗黙的に(CPU自体によって)実行できます。
通常の(通常は調整されていない)肥大化したアプリケーションコードの場合、このような命令を使用しても、全体的なパフォーマンスにはほとんど影響しません。非常にタイトなループを備えた高度に専門化された手動調整コードでは、特にコードの複数のコピーが異なるコアで実行されている場合、4つまたは5つのキャッシュラインではなく3つのキャッシュライン内での実行の違いが大きな違いを生む可能性があります。
の場合sete
、それはおそらく命令セットで書かれたコードの実際の経験の問題でした。少なくともメモリが機能する場合sete
は、386の時点で追加されたため、それまでに命令セットは数年間アクティブに使用されていました。推測では、彼らはおそらく、コードを調べて、多くのことを行ったが、命令セットで直接サポートされていないことを見つけるのに時間を費やしました。彼らはおそらくそれらをスクリーニングして、CPUで直接サポートすることではるかに効率的にするのが簡単なものを見つけるでしょう。
多くの場合はそれにかなり似ています。作業は基本的にソフトウェアでプロトタイプ化され、適度に柔軟で効率的で実装が簡単な設計を見つけます。次に、設計が比較的洗練されている場合、CPU設計者はそれを調べて、ハードウェアに(少なくとも一部)実装することによって少なくとももう少し効率的にすることができないかどうかを確認します。
いわゆるRISCプロセッサのほとんどは、既存のプロセッサ上の既存のコンパイラを使用してソースコードから生成されたコードの統計を収集することによって設計されました。次に、命令の使用頻度を調べ、(使用しようとした)頻繁に使用されたものを最適化し、あまり使用されなかったものを単純に削除しました。