プロセッサに32個のレジスタがあるのはなぜですか?


52

プロセッサが32個のレジスタで停止した理由を常に疑問に思っていました。それはマシンの群を抜いて最速のピースです。より多くのレジスタを備えたより大きなプロセッサを作ってみませんか?それは、RAMへのアクセスが減ることを意味しませんか?


2
特定のポイントを超えると、すべてのローカル変数がレジスタに収まると思います。あなたが作業している実際のデータは、おそらく大きすぎるとにかくです
ニクラスB.

14
収益の減少。明らかに、レジスタは(さまざまな意味で)RAMよりも「高価」であるか、8GBのレジスタしかありません。
デビッドリチャービー14年

5
そのように速い理由の1つは、それらの多くが存在しないためです。
stackErr 14年

5
CPUの合計レジスタ数と、一度に使用できるレジスタ数には違いがあります。
トールビョーンラヴンアンデルセン

CPUとGPUは、主にそれぞれキャッシュとマルチスレッドによって遅延を隠します。したがって、CPUにはレジスタがほとんどありませんが、GPUにはレジスタが何万もあります。これらすべてのトレードオフと要因について説明しているGPUレジスタファイルに関する調査論文を参照してください。
user984260

回答:


82

まず、すべてのプロセッサアーキテクチャが32レジスタで停止したわけではありません。命令セットで32個のレジスタが公開されているほとんどすべてのRISCアーキテクチャには、実際には32個の整数レジスタと32個の浮動小数点レジスタがあります(つまり64個)。(浮動小数点「add」は整数「add」とは異なるレジスタを使用します。)SPARCアーキテクチャにはレジスタウィンドウがあります。SPARCでは、一度に32個の整数レジスタにしかアクセスできませんが、レジスタはスタックのように動作し、一度に16個の新しいレジスタをプッシュおよびポップできます。HP / IntelのItaniumアーキテクチャには、128個の整数レジスタと128個の浮動小数点レジスタが命令セットで公開されていました。NVidia、AMD、Intel、ARM、およびImagination Technologiesの最新のGPUはすべて、レジスタファイル内の膨大な数のレジスタを公開しています。(私はこれがNVidiaおよびIntelアーキテクチャに当てはまることを知っています。AMD、ARM、およびImaginationの命令セットにはあまり精通していませんが、レジスタファイルも大きいと思います。)

第二に、ほとんどの最新のマイクロプロセッサは、レジスタの名前変更を実装して、リソースを再利用する必要があることによる不必要なシリアル化を排除します。そのため、基礎となる物理レジスタファイルは大きくなりますコンパイラが非常に多くの一意のレジスタ名を生成すると同時に、スケジューラに大きなレジスタファイルを提供する必要がある。

命令セットで公開されるレジスタの数をさらに増やすのが難しい場合がある理由は2つあります。まず、各命令でレジスタ識別子を指定できる必要があります。32レジスタには5ビットのレジスタ指定子が必要なため、3アドレス命令(RISCアーキテクチャでは一般的)は、レジスタを指定するためだけに32命令ビットのうち15ビットを使用します。これを6ビットまたは7ビットに増やした場合、オペコードと定数を指定するスペースが少なくなります。GPUとItaniumには、はるかに大きな命令があります。大きな命令にはコストがかかります。より多くの命令メモリを使用する必要があるため、命令キャッシュの動作は理想的ではありません。

2番目の理由はアクセス時間です。メモリを大きくすると、メモリからのデータへのアクセスが遅くなります。(基本的な物理学の観点から言えば、データは2次元空間に格納されるため、ビットを格納する場合、特定のビットまでの平均距離はです。)レジスタファイルは単なる小さなマルチポートメモリ、およびそれを大きくするための制約の1つは、最終的には、より大きなレジスタファイルに対応するために、マシンのクロックを遅くする必要があることです。通常、全体的なパフォーマンスの観点では、これは損失です。 O nO(n)


1
SPARC64 VIIIfxの256 FPRと32の追加の非ウィンドウGPRは、次の1つまたは2つの命令にそれぞれ13ビットを提供するSet XAR命令を追加することで実現できます。これはHPCを対象としたため、レジスタカウントがわかりやすくなっています。また、より多くのレジスタに関連するいくつかのトレードオフとテクニックについて詳しく説明したいと思いました。しかし、あなたは知恵を示して、より疲れ果てた(そしてそれでも完全ではない)答えを避けました。
ポールA.クレイトン

2
意味のある測定値を見つけるのは簡単ではありませんが、「汎用」コード用のレジスタを増やすことの利点を少し減らすことは価値があるかもしれません。Mitch Alsupはcomp.archで、x86を16ではなく32レジスタに拡張すると、選択した8〜16レジスタ拡張の(ISTR)10〜15%に比べてパフォーマンスが約3%向上すると述べたと思います。ロードストアISAの場合でも、64に変更してもほとんど利点がありません(少なくとも現在のGPコードでは)。(ちなみに、GPUは多くの場合、スレッド間でレジスタを共有します。たとえば、1つのスレッドが250で、他のスレッド用に合計16が残ります。)
Paul A. Clayton

環境管理(したがって、アルファ変換)は、多くの場合高水準言語に関連付けられており、実際には登録レベルで使用されていることがわかります。
babou

PaulA.Clayton @私はいつもIA-64は、ISAレジスタの数が最も多いのアーキテクチャであると考え
phuclv

@LưuVĩnhPhúcSPARC64 VIIIfxはHPC固有のものでした。参考までに、Am29k1987-8年頃に導入)には、64個のグローバルGPRと128個のウィンドウ付きGPRがあり、Itanium(他のISAのGPRに機能する8つの分岐レジスタとループカウントレジスタがあります)よりもGPRが多くなっています。
ポールA.クレイトン

16

レジスタの数を制限するもう2つの理由:

  • ほとんど期待されないゲイン:現在のIntel / AMD x64モデルなどのCPUには32kByte以上のL1-Dキャッシュがあり、L1キャッシュへのアクセスには通常1クロックサイクルしかかかりません(完全なシングルRAMの場合は約100クロックサイクルに比べます)アクセス)。そのため、L1キャッシュにデータを保持するのに比べて、レジスタに多くのデータを保持することから得られるものはほとんどありません。
  • 追加の計算コスト:レジスタを増やすとオーバーヘッドが発生し、実際にコンピューターが遅くなる可能性があります。
    • マルチタスク環境では、タスクスイッチは通常、メモリに残されたプロセスのすべてのレジスタの内容を保存し、入力するプロセスのレジスタをロードする必要があります。レジスタが多いほど、時間がかかります。
    • 同様に、レジスタウィンドウのないアーキテクチャでは、カスケードされた関数呼び出しは同じレジスタセットを使用します。したがって、関数Bを呼び出す関数Aは、B自体と同じレジスタセットを使用します。したがって、Bは使用するすべてのレジスタの内容(Aの値を保持している)を保存し、戻る前に書き戻す必要があります(一部の呼び出し規約では、Bを呼び出す前にレジスタの内容を保存するのはAの仕事ですが、オーバーヘッドは似ています)。レジスタが多いほど、この保存にかかる時間が長くなり、関数呼び出しのコストが高くなります。

レジスタと同じ問題が発生しないように、L1キャッシュではどのように機能しますか?
babou

4
高性能プロセッサでは、L1 Dcacheレイテンシはより一般的に3または4サイクル(アドレス生成を含む)です。たとえば、IntelのHaswellには4サイクルのレイテンシがあります(データ依存性レジスタレイテンシがないこともパイプラインで隠すのが簡単です)。また、Dcacheは、レジスタファイル(たとえば、ファイルを複製したAlpha 21264の4読み取り、6書き込み、4読み取りの2ファイルは、 8)。
ポールA.クレイトン

@ PaulA.Clayton:L1キャッシュに3〜4サイクルのレイテンシがある場合、64ワードの独自の64ワードのアドレス空間を持つ64ワードのシングルサイクルメモリのセットを使用することで何らかの利点があることを示唆します。専用の「ロード/ストアダイレクト」命令。特に、すべての非ゼロ値をプッシュする方法があり、その後にどの単語が非ゼロであったかを示す方法があり、その後、それらを戻す方法(ポップされなかったレジスタをゼロにする) 。多くのメソッドには16〜60ワードのローカル変数があるため、3〜4サイクルから1サイクルまでのアクセス時間を短縮すると便利です。
スーパーキャット

@supercatさまざまなスタック(およびグローバル/ TLS [ナップザック]など)のキャッシュのアイデアは、学術論文や署名バッファーPDF)などのメカニズムで提示されています。これはおしゃべりになっています(おそらく終了するか、他の場所に移動する必要があります)。
ポールA.クレイトン14年

4

多くのコードには多くのメモリアクセスがあります(30%は典型的な数値です)。このうち、通常は約3分の2が読み取りアクセスで、1/3が書き込みアクセスです。これは、配列へのアクセス、オブジェクトメンバー変数へのアクセスなど、レジスタが不足しているためではありません。

これは、C / C ++の作成方法が原因で、メモリ(またはデータキャッシュ)で実行する必要があります(ポインタを取得できるものはすべて、潜在的にメモリに格納する必要があるアドレスを持つ必要があります)。コンパイラが、狂った間接ポインタトリックを使用して意外に変数に書き込みを行わないと推測できる場合、それらをレジスタに配置します。これは、関数変数に対してはうまく機能しますが、グローバルにアクセス可能な変数(一般的には、malloc ())グローバル状態がどのように変化するかを推測することは本質的に不可能だからです。

このため、コンパイラがとにかく16個以上の汎用レジスタを使用して何でもできるようになることは一般的ではありません。すべての人気のある建築家がその数について持っている理由です(ARMには16があります)。

MIPSや他のRISCには32があります。これは、それほど多くのレジスタを用意するのがそれほど難しくないためです-コストが十分に低いので、「なぜ?」32以上はほとんど役に立たず、レジスタファイルのアクセスが長くなるという欠点があります(レジスタの数を2倍にするごとに、マルチプレクサの層が追加され、遅延が少し増える可能性があります...)。また、平均して命令がわずかに長くなります。つまり、命令メモリの帯域幅に依存する種類のプログラムを実行すると、余分なレジスタが実際に速度を低下させます。

CPUの順序が正しくなく、レジスタ名の変更を行わず、サイクルごとに多くの操作(3つ以上)を実行しようとしている場合、理論的には、サイクルごとの操作数が増えるにつれて、より多くのレジスタが必要になります。これが、Itaniumに非常に多くのレジスタがある理由です!しかし、実際には、数値浮動小数点またはSIMD指向のコード(Itaniumが得意)を除き、ほとんどのコードには多くのメモリ読み取り/書き込みとジャンプがあり、サイクルあたり3を超える操作というこの夢を実現できません。 (特に、データベース、コンパイラ、javascriptなどの高レベル言語実行、エミュレーションなどのようなサーバー指向ソフトウェアで)。これがItaniumを沈めたものです。

すべては、計算と実行の違いに帰着します!


2

プロセッサに常に 32個のレジスタがあることを誰が教えてくれますか?x86には8個、ARM 32ビット、x86_64には16個、IA-64には128個、その他多くの数字があります。あなたは見ることができ、ここで。MIPS、PPC、または命令セットに32個の汎用レジスターがあるアーキテクチャーでも、フラグレジスター(存在する場合)、制御レジスター、名前変更されたレジスターおよびハードウェアレジスターは含まれないため、その数は32よりもはるかに大きくなります。

すべてに価格があります。レジスタの数が多いほど、タスクの切り替え時に多くの作業が必要になり、命令のエンコードに必要なスペースが増えます。レジスタが少ない場合、関数を呼び出したり、関数から戻ったり、タスクを切り替えたりするときに、一部の計算量の多いコードにレジスタがないというトレードオフを考慮して、保存や復元を行う必要はありません。

さらに、レジスタファイルが大きいほど、高価で複雑になります。SRAMは最速で最も高価なRAMなので、CPUキャッシュでのみ使用されます。ただし、同じ容量のレジスタファイルよりもはるかに安価であり、面積も小さくなります。


2

たとえば、典型的なIntelプロセッサには、「公式に」16個の整数レジスタと16個のベクトルレジスタがあります。しかし、実際にはさらに多くのことがあります。プロセッサは「レジスタ名の変更」を使用します。命令reg3 = reg1 + reg2がある場合、reg3を使用する別の命令がまだ終了していないと問題が発生します。前の命令によって読み取られる前にreg3を上書きする場合、新しい命令を実行できませんでした。

したがって、約160ほどの実際のレジスタがあります。したがって、上記の単純な命令は「regX = reg1 + reg2に変更され、regXにはreg3が含まれていることを覚えておいてください」。レジスタの名前を変更しないと、順不同の実行は完全に死んでしまいます。


1

私は電気技師ではありませんが、レジスタの数を制限する理由の別の可能性はルーティングです。演算ユニットの数には限りがあり、すべてのレジスタから入力を取得し、すべてのレジスタに出力できる必要があります。これは、サイクルごとに多くの命令を実行できるパイプラインプログラムがある場合に特に当てはまります。

これの単純なバージョンは、複雑さを持ち、レジスタの数をスケーラブルにできないようにします。O(n2)

この答えは、Ivan GodardのMill CPUに関する講演を見ることで得られました。Mill CPUの革新の一部は、任意のレジスタに出力できないことです。出力はすべてレジスタスタックまたは「ベルト」にプッシュされるため、出力の行き先が常にわかるため、ルーティングの問題が軽減されます。入力レジスタを演算ユニットに送るためのルーティングの問題がまだ残っていることに注意してください。

参照してくださいベルト(9の2) -ミルCPUアーキテクチャを、問題文の、そしてミルのソリューション。


「すべてのレジスタから入力を取得し、すべてのレジスタに出力できる必要があります。」-通常、これはバスで実装され、レジスタごとにALUに個別に接続する必要はありません。
user253751

1
@immibis:300ピコ秒でデータを移動したい場合、バスはそれを行いません。また、多くのデータを移動したい場合(たとえば、2つのオペランドと1つの結果をそれぞれ同じサイクルで3つの命令を実行する場合)、バスは完全に機能しません。
gnasher729

0

MIPS ISAについては、ヘネシーとパターソン、コンピューター組織とデザイン第4版p。176、この特定の質問に直接答えます:

小さいほど速くなります。速度への欲求が、MIPSが多くのレジスタではなく32個のレジスタを持っている理由です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.