
コンピュータ エンジニアリングにおいて、レジスタ ウィンドウとは、内部レジスタのサブセットを固定のプログラマが認識できるレジスタに動的にエイリアスすることで、レジスタをサブルーチン専用にする機能です。レジスタ ウィンドウは、関数の呼び出しと戻りに必要なスタック操作の数を減らすことで、プロセッサのパフォーマンスを向上させるために実装されています。Berkeley RISC設計の最も影響力のある機能の 1 つであり、後にAMD Am29000、Intel i960、Sun Microsystems SPARC、Intel Itaniumなどの命令セット アーキテクチャに実装されました。
一般的な操作
プログラムのさまざまな部分に複数のレジスタ セットが用意されています。レジスタは、複数のサブルーチンでプロセッサ リソースを共有するように、プログラマーから意図的に隠されています。
レジスタを非表示にすることは効率的に実装できます。CPU は、プロシージャ呼び出し中にプログラムのある部分から別の部分への移動を認識します。これは、少数の命令 (プロローグ)の 1 つによって実行され、同様に少数のセット (エピローグ)の 1 つで終了します。Berkeley 設計では、これらの呼び出しにより、その時点で新しいレジスタ セットが「スワップイン」されるか、呼び出しの終了時に「デッド」(または「再利用可能」) としてマークされます。
CPUへの応用
Berkeley RISC 設計では、合計 64 個のレジスタのうち 8 個だけがプログラムから見えるようになっています。レジスタの完全なセットはレジスタ ファイルと呼ばれ、8 個の特定のセットはウィンドウと呼ばれます。ファイルでは、最大 8 個のプロシージャ呼び出しが独自のレジスタ セットを持つことができます。プログラムが 8 個以上の呼び出しチェーンを呼び出しない限り、レジスタをスピルする必要はなく、つまり、レジスタ アクセスに比べて処理が遅いメイン メモリまたはキャッシュに保存する必要もありません。
これに対して、Sun Microsystems SPARCアーキテクチャでは、8 つのレジスタが 4 セット同時に表示されます。8 つのレジスタが 3 セットそれぞれ「ウィンドウ」化されています。8 つのレジスタ (i0 から i7) は、現在のプロシージャ レベルへの入力レジスタです。8 つのレジスタ (L0 から L7) は、現在のプロシージャ レベルにローカルで、8 つのレジスタ (o0 から o7) は、現在のプロシージャ レベルから次に呼び出されるレベルへの出力です。プロシージャが呼び出されると、レジスタ ウィンドウは 16 個のレジスタだけシフトし、古い入力レジスタと古いローカル レジスタを非表示にして、古い出力レジスタを新しい入力レジスタにします。共通レジスタ (古い出力レジスタと新しい入力レジスタ) は、パラメータの受け渡しに使用されます。最後に、8 つのレジスタ (g0 から g7) は、すべてのプロシージャ レベルにグローバルに表示されます。
AMD 29000 では、ウィンドウを可変サイズにできるように設計が改良され、呼び出しに必要なレジスタが 8 個未満の一般的なケースでの利用が可能になりました。また、レジスタを 64 個のグローバル セットとウィンドウ用の追加 128 個に分割しました。同様に、IA-64 (Itanium) アーキテクチャでは、32 個のグローバル レジスタと 96 個のウィンドウという可変サイズのウィンドウが使用されました。
Infineon C166アーキテクチャでは、ほとんどのレジスタは内部 RAM 内の単なる位置であり、レジスタとしてアクセス可能であるという追加の特性があります。これらのうち、16 個の汎用レジスタ (R0 ~ R15) のアドレスは固定されていません。代わりに、R0 レジスタは「コンテキスト ポインタ」(CP) レジスタによって指されるアドレスに配置され、残りの 15 個のレジスタがその後に順番に続きます。[1]
レジスタ ウィンドウは、アップグレード パスも簡単に提供します。追加のレジスタはプログラムからは見えないため、いつでも追加のウィンドウを追加できます。たとえば、オブジェクト指向プログラミングを使用すると、多くの場合、より小さな呼び出しの数が多くなりますが、たとえばウィンドウを 8 から 16 に増やすことで対応できます。これは SPARC で使用されたアプローチであり、新しい世代のアーキテクチャではより多くのレジスタ ウィンドウが含まれています。最終的には、レジスタ ウィンドウのオーバーフローが少なくなるため、低速のレジスタ ウィンドウのスピルおよびフィル操作が少なくなります。
批判
レジスタウィンドウの欠点は、コンテキストスイッチに大量のレジスタをメモリに保存する必要があることです。SPARC 実装では、レジスタウィンドウが常に 16 レジスタ分進められるため、これが発生すると、保存されたレジスタの多くには有用なデータさえ含まれなくなります。レジスタウィンドウの実装につながった当初の研究は、独立したプログラムのみを考慮し、マルチタスクのワークロードを無視していると批判する人もいます。[2]
レジスタウィンドウはレジスタパフォーマンスを向上させる唯一の方法ではありません。MIPSを設計していたスタンフォード大学のグループはバークレーの研究を見て、問題はレジスタの不足ではなく、既存のレジスタの不十分な使用にあると判断しました。代わりに、彼らはコンパイラのレジスタ割り当てに多くの時間を費やし、MIPS で利用可能なより大きなセットを賢く使用するようにしました。その結果、チップの複雑さが軽減され、レジスタの総数は半分になり、単一のプロシージャがより大きな可視レジスタスペースを使用できる場合には、潜在的に高いパフォーマンスが実現しました。最終的に、現代のコンパイラでは、MIPS はプロシージャ呼び出し中でもレジスタスペースをより有効に活用しています。[要出典]
参考文献
- ^ 「Infineon C166 ファミリー命令セットマニュアル」(PDF) . Keil . 2020 年 3 月 12 日閲覧。
- ^ Magnusson, Peter (1997 年 4 月). 「Sparc アーキテクチャのスタックとレジスタを理解する」. CSE 131 - コンパイラ構築.サンディエゴ大学. 2024 年10 月 24 日閲覧.
欠点は、システムとのやり取り時にレジスタをスタックにフラッシュする必要があり、大部分がゴミであることが多いデータのメモリへの書き込みの長いシーケンスが必要になることです。レジスタ ウィンドウは、マルチタスク ワークロードではなくプログラムのみを個別に考慮したシミュレーション研究と、最適化が不十分なコンパイラを考慮したために生じた悪いアイデアでした。
- Frantzen, Mike; Shuey, Mike (2001)。「StackGhost: ハードウェアによるスタック保護」。第 10 回 Usenix セキュリティ シンポジウムの議事録。USENIX。pp . 55–66。2010年8月 27 日に取得。
- Magnusson, Peter (1997 年 4 月)。「Sparc アーキテクチャのスタックとレジスタを理解する」。2012 年 12 月 24 日時点のオリジナルよりアーカイブ。2010年8 月 27 日閲覧。
- Mueller、Frank。「setjmp/longjmp」。ウィンドウ処理による複雑な Sparc 実装について説明します。
