[解決済み] レジスターが猛烈に速いなら、なぜもっとたくさんないのか?
疑問点
32ビットでは、8本の汎用レジスタがありました。64 ビットでは、その量は 2 倍になりますが、64 ビットの変更自体には関係ないようです。
さて、レジスタがそんなに高速(メモリアクセスなし)なら、なぜ自然に数が増えないのでしょうか?CPUメーカーは、CPUにできるだけ多くのレジスタを組み込むべきではありませんか?なぜこのような量しかないのか、論理的な制約は何なのでしょうか?
どのように解決するのですか?
膨大な数のレジスタを持たない理由はたくさんあります。
- レジスタは、ほとんどのパイプライン ステージに高度にリンクされています。まず、レジスタの寿命を追跡し、結果を前のステージに転送する必要があります。この複雑さはすぐに解決不可能になり、関係する配線の数も同じ速度で増えていきます。これは、面積の点で高価であり、最終的には、ある時点以降、電力、価格、および性能の点で高価であることを意味します。
- 命令エンコード スペースを占有します。16 個のレジスタはソースとデスティネーションに 4 ビット、3 オペランド命令 (例: ARM) の場合はさらに 4 ビットを使用します。レジスタを指定するためだけに、非常に多くの命令セット・エンコード・スペースが取られることになります。これは最終的にデコード、コード サイズ、および再び複雑さに影響します。
- 同じ結果を達成するためのより良い方法があります...
最近、私たちは本当にたくさんのレジスタを持っています - それらはただ明示的にプログラムされていないだけです。私たちには、quot;register renaming" があります。ユーザーは小さなセット (8-32 レジスタ) にしかアクセスしませんが、実際にはもっと大きなセット (たとえば 64-256) によってバックアップされています。そして、CPUは各レジスタの可視性を追跡し、名前を変更したセットに割り当てる。例えば、あるレジスタに対して、ロード、モディファイ、ストアを連続して何度も行うことができ、キャッシュミスなどに応じて、これらの操作をそれぞれ独立して実際に実行させることができます。ARMでは。
ldr r0, [r4]
add r0, r0, #1
str r0, [r4]
ldr r0, [r5]
add r0, r0, #1
str r0, [r5]
Cortex A9 コアはレジスタの名前を変更するため、"r0" への最初のロードは実際には名前を変更した仮想レジスタに行きます - これを "v0" と呼びましょう。ロード、インクリメント、ストアは "v0"で行われます。一方、再びr0に対してロード/変更/ストアを実行しますが、これはr0を使用する完全に独立したシーケンスであるため、"v1"にリネームされます。例えば、"r4"のポインタからのロードがキャッシュ・ミスにより停止したとしましょう。しかし、それは大丈夫です。それは名前が変更されているので、(同じく r0 にマップされた) "v1" で次のシーケンスを実行することができ、おそらくそれはキャッシュ ヒットであり、私たちは大きなパフォーマンスの勝利を収めました。
ldr v0, [v2]
add v0, v0, #1
str v0, [v2]
ldr v1, [v3]
add v1, v1, #1
str v1, [v3]
x86は最近、リネームされたレジスタの数が膨大になってると思う(目安は256本)。そうすると、命令ごとに、ソースとデスティネーションが何であるかを言うためだけに、8ビット×2が必要になります。そうすると、コアに必要な配線の数が大幅に増え、サイズも大きくなってしまいます。そのため、ほとんどの設計者は 16 ~ 32 本のレジスタを使用することにしており、アウトオブオーダーの CPU 設計では、レジスタ名の変更がそれを軽減する方法となっています。
編集
: アウトオブオーダー実行とレジスタのリネームの重要性について。レジスタは一時的なタグに過ぎず、より大きな仮想レジスタセットにリネームされるため、OOOがあれば、レジスタの数はそれほど重要ではありません。レジスタの数が少なすぎると、小さなコード列を書くのが難しくなるので、レジスタの数はあまり多くしない方がよいでしょう。x86-32では、レジスタが8個と限られているため、多くのテンポラリがスタックを経由することになり、コアはメモリへの読み書きを転送するために余分なロジックを必要とするため、これは問題です。OOO がない場合は、通常、小さなコアについて話していることになり、その場合、大きなレジスタ セットはコスト/パフォーマンス上の利点が乏しくなります。
x86-32 は 8 つのレジスタを持ちますが、これは間違いなく小さすぎです。ARMは16レジスタにしましたが、これは良い妥協点です。32本のレジスタは、どちらかというとやや多すぎで、最後の10本くらいは必要ないでしょう。
SSE およびその他のベクトル浮動小数点コプロセッサのための追加レジスタについては、どれも触れていません。これらのレジスタは、整数コアから独立して実行され、CPU の複雑さを指数関数的に増大させないので、追加セットとして理にかなっています。
関連
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] forループの中で<と<=のどちらを使うべきか [閉じた状態].
-
[解決済み] Rでdata.frameをマージ/ジョインする最速の方法は何ですか?
-
[解決済み] RustのOption型のオーバーヘッドとは?
-
[解決済み] EBPフレームポインタレジスタの目的は何ですか?
-
[解決済み] 開発者は読みやすさとパフォーマンスのどちらを優先させるべきか?[クローズド]
-
[解決済み] 原子演算コスト
-
[解決済み] なぜ、条件付の手は分岐予測失敗の影響を受けないのですか?
-
[解決済み] Laravelは本当にこんなに遅いのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Scalaのパターンマッチはバイトコードレベルでどのように実装されているのですか?
-
[解決済み] ファイルキャッシュをクリアしてパフォーマンステストを繰り返す
-
[解決済み] OFFSET / FETCH NEXTからの総行数取得
-
[解決済み] なぜSSEスカラーsqrt(x)はrsqrt(x) * xより遅いのですか?
-
[解決済み] Entity Frameworkのクエリは遅いが、SqlQueryの同じSQLは速い。
-
[解決済み] translateZ(0)に対するCSSのパフォーマンス
-
[解決済み] ループのアンロールが役に立つとしたら、どんなときか?
-
[解決済み] EBPフレームポインタレジスタの目的は何ですか?
-
[解決済み] なぜ、条件付の手は分岐予測失敗の影響を受けないのですか?
-
[解決済み] Rでループが遅いのはなぜですか?