| 数値計算ガイド |
付録 B
SPARC の動作と実装
この付録では、SPARC ワークステーションで使用される浮動小数点ユニット (FPU) に関連する問題を説明します。特に、各ワークステーションに最適なコード生成フラグを確定する方法を示します。
浮動小数点ハードウェア
この節では、多数の SPARC 浮動小数点ユニットを一覧で示し、それらがサポートする命令セットと例外処理機能について説明します。浮動小数点のトラップ時に発生する状況、トラップされるアンダーフローとトラップされないアンダーフローの違い、IEEE 以外の (非標準) 算術モードの SPARC の実装での適切な処理などに関する簡単な説明については、『SPARC Architecture Manual, Version 8』の付録 N「SPARC IEEE 754 Implementation Recommendations」および『SPARC Architecture Manual, Version 9』の付録 B 「IEEE std 754-1985 Requirements for SPARC-V9」を参照してください。
表 B-1 に、SPARC ワークステーションで使用される浮動小数点ハードウェアを示します。初期の大部分の SPARC システムでは、TI または Weitek で開発されたモデルにもとづく浮動小数点ユニットが使用されています。
これら 2 種類の FPU は他のワークステーションベンダーにライセンス提供されているため、SPARC ワークステーションによっては他の半導体メーカーのチップが使用される場合もあります。他メーカーチップの一部は、次の表にも示されています。
この表の最後の列は、それぞれの FPU でもっとも高速なコードを取得するために使用するコンパイラフラグを示しています。これらのフラグは、2 つの独立したコード生成属性を制御します。
-xarchフラグは、コンパイラが使用できる命令セットを決定します。-xchipフラグは、コードのスケジューリングにおけるプロセッサのパフォーマンス特性についてコンパイラが立てる仮定を決定します。SPARC 浮動小数点ユニットはすべて、少なくとも『SPARC Architecture Manual, Version 7』で定義されている浮動小数点命令セットを実装しています。そのため、-xarch=v7を指定してコンパイルしたプログラムは、それ以降のプロセッサの機能を十分利用しない可能性がありますが、どの SPARC システムでも動作します。同様に、-xchipの特定の値でコンパイルされたプログラムは、-xarchで指定された命令セットをサポートするすべての SPARC システムで動作しますが、指定されたプロセッサ以外のプロセッサを搭載したシステムでは実行速度が落ちる場合があります。この表に挙げられた microSPARC-I よりも前の浮動小数点ユニットは、『SPARC Architecture Manual, Version 7』に定義された浮動小数点命令セットを実装しています。これらの FPU を使用したシステムで実行しなければならないプログラムは、
-xarch=v7を指定してコンパイルする必要があります。コンパイラはこれらのプロセッサのパフォーマンス特性については特に仮定しないため、これらのプロセッサはどれも単一の-xchipオプション、-xchip=oldを共有します。表 B-1 に示されたシステムの中には、現在 Sun WorkShop Compiler でサポートされていないものもあります。それらは、履歴を示すために挙げられているにすぎません。これらのシステムをサポートするコンパイラで使用するコード生成フラグについては、『数値計算ガイド』の該当する版を参照してください。microSPARC-I および microSPARC-II 浮動小数点ユニットは、『SPARC Architecture Manual, Version 8』で定義されている浮動小数点命令セット (FsMULd および 4 倍精度命令を除く) を実装しています。
-xarch=v8を指定してコンパイルしたプログラムはこれらのプロセッサが搭載されたシステム上で動作しますが、実装されていない浮動小数点命令はシステムカーネルがエミュレートしなければなりません。そのため、FsMULd を広範囲にわたって使用するプログラム (多数の単精度の複素数演算を行う FORTRAN プログラムなど) では、パフォーマンスが著しく低下する場合があります。このような事態を避けるには、これらのプロセッサを搭載したシステム用のプログラムを、-xarch=v8aを指定してコンパイルしてください。SuperSPARC-I、SuperSPARC-II、hyperSPARC、および TurboSPARC 浮動小数点ユニットは、『SPARC Architecture Manual, Version 8』で定義されている浮動小数点命令セット (4 倍精度命令を除く) を実装しています。これらのプロセッサを搭載したシステムで最高のパフォーマンスを得るには、
-xarch=v8を指定してコンパイルしてください。UltraSPARC-I、UltraSPARC-II、および UltraSPARC-IIi 浮動小数点ユニットは、『SPARC Architecture Manual、Version 9』で定義されている浮動小数点命令セット (4 倍精度命令を除く) を実装しています。具体的には、これらの FPU は、32 倍精度の浮動小数点レジスタを提供します。コンパイラがこれらのレジスタを使用できるようにするには、
-xarch=v8plus(32 ビット OS で動作するプログラム用) または-xarch=v9(64 ビット OS で動作するプログラム用) を指定してコンパイルしてください。これらのプロセッサは、標準の命令セットの拡張機能も提供しています。Visual Instruction Set (VIS) として知られる追加命令をコンパイラが自動的に生成することはまれですが、その場合はアセンブリコードで使用できます。そのため、これらのプロセッサがサポートする命令セットをフルに利用するためには、-xarch=v8plusa(32 ビット) または-xarch=v9a(64 ビット) を使用してください。
-xarchおよび-xchipオプションは、-xtargetマクロを使用して同時に指定できます (-xtargetフラグは、-xarch、-xchip、および-xcacheフラグの適切な組み合わせとして展開されます)。デフォルトのコード生成オプションは、-xtarget=genericです。-xarch、-xchip、-xtargetの値の全一覧など、詳細については、cc(1)、CC(1)、f77(1)、およびf95(1) のマニュアルページとコンパイラマニュアルを参照してください。-xarchに関する詳細は『Fortran ユーザーズガイ
ド』、『C ユーザーズガイド』、および『C++ ユーザーズガイド』にあります。浮動小数点状態レジスタと待ち行列
どのバージョンの SPARC アーキテクチャを実装しているかにかかわらず、SPARC 浮動小数点ユニットはすべて、FPU に対応した状態ビットと制御ビットが入った浮動小数点状態レジスタ (FSR) を提供しています。遅延浮動小数点トラップを実装している SPARC FPU はすべて、現在実行中の浮動小数点命令についての情報を保持する浮動小数点待ち行列 (FQ) を提供しています。発生した浮動小数点例外を検出し、丸め方向、トラップ、および標準外演算モードを制御するように、FSR はユーザーソフトウェアからアクセスできます。FQ は、浮動小数点トラップの処理のために、オペレーティングシステムのカーネルによって使用されます。FQ は、通常ユーザーソフトウェアからは見えません。
ソフトウェアは、FSR をメモリーに格納する
STFSR命令とFSRをメモリーから読み込むLDFSR命令を介して、浮動小数点状態レジスタにアクセスします。SPARC アセンブリ言語では、これらの命令は次のように記述されます。
st %fsr, [addr] ! FSR を指定されたアドレスに格納するld [addr], %fsr ! FSR を指定されたアドレスから読み込むSun WorkShop Compiler に付属のライブラリが置かれたディレクトリに入っているインラインテンプレートファイル
libm.ilには、STFSRおよびLDFSR命令の使用を示す例が入っています。次の図 B-1 は、浮動小数点状態レジスタのビットフィールドのレイアウトを示しています。
図 B-1 SPARC 浮動小数点状態レジスタ![]()
(SPARC アーキテクチャのバージョン 7 と 8 では、この図に示されているように FSR は 32 ビットを占めます。バージョン 9 では FSR は 64 ビットに拡張されますが、そのうちの下位 32 ビットはこの図と一致し、上位 32 ビットには 3 つの浮動小数点条件コードフィールドがさらに入っているだけで、大部分は未使用です。)
この図中の
resは予約済みのビットを示し、verは FPU のバージョンを示す読み取り専用フィールドです。fttとqneは、システムが浮動小数点トラップを処理する場合に使用します。残りのフィールドについては、次の表に示します。
表 B-2 浮動小数点状態レジスタフィールド RM 丸め方向モード TEM トラップ有効化モード NS 標準外モード fcc 浮動小数点条件コード aexc 累積例外フラグ cexc 現在の例外フラグ
RMフィールドには、浮動小数点演算の丸め方向を指定する 2 ビットが入っています。NSビットは、標準外演算モードを実装している SPARC FPU でこのモードを有効にします。実装していない FPU では、このビットは無視されます。fccフィールドには、浮動小数点比較命令によって生成された浮動小数点条件コードが入っており、分岐演算と条件付き移動演算によって使用されます。TEM、aexc、およびcexcフィールドには、トラップの制御と、5 つの IEEE 754 浮動小数点例外のそれぞれについての累積例外フラグと現在の例外フラグの記録を行う 5 ビットが入っています。これらのフィールドは、表 B-3 に示すようにさらに分割されます。
表 B-3 例外処理フィールド TEM、トラップ有効化モードNVM 27 OFM 26 UFM 25 DZM 24 NXM 23 aexc、累積例外フラグnva 9 ofa 8 ufa 7 dza 6 nxa 5 cexc、現在の例外フラグnvc 4 ofc 3 ufc 2 dzc 1 nxc 0
上記の記号 NV、OF、UF、DZ、および NX は、無効演算、オーバーフロー、アンダーフロー、ゼロ除算、および不正確な例外をそれぞれ意味します。
ソフトウェアサポートが必要な特別な場合
SPARC 浮動小数点ユニットは、通常はソフトウェアサポートを必要とすることなく完全にハードウェア内で命令を実行します。しかし、以下の 4 つの状況において、ハードウェアは浮動小数点命令を正常に完了しません。
- 浮動小数点ユニットが無効になっている場合。
- 命令がハードウェアによって実装されていない場合 (たとえば、Weitek 1164/1165 ベース FPU での
fsqrt[sd]、microSPARC-I および microSPARC-II FPU でのfsmuld、全 SPARC FPU での 4 倍精度命令など)。- ハードウェアが命令のオペランドについて正しい結果を配布できない場合。
- 命令が IEEE 754 浮動小数点例外を引き起こし、その例外のトラップが有効である場合。
これらの状況での最初の応答はすべて、プロセスからシステムカーネルに対するトラップの発行です。システムカーネルは、トラップの原因を確かめ、適切な処置を行います (「トラップ」は、通常の制御フローの割り込みを意味します)。最初の 3 つの状況では、カーネルはソフトウェア内でトラップ命令をエミュレートします。エミュレートされる命令もまた、トラップが有効になった例外を引き起こす可能性があることに注意してください。
上記の最初の 3 つの状況で、エミュレートされる命令がトラップが有効になった IEEE 浮動小数点例外を発生させない場合、カーネルは命令を完了します。命令が浮動小数点比較の場合は、その結果を反映させるために条件コードを更新します。命令が算術演算の場合は、宛先レジスタに対して適切な結果を配布します。カーネルは、命令によって発生した (トラップされない) 例外を反映させるために現在の例外フラグの更新も行い、それらの例外の論理和を累積例外フラグに入れます。その後カーネルは、トラップが起きた位置でプロセスの実行を継続するように手はずを整えます。
ハードウェアが実行する命令やカーネルソフトウェアがエミュレートする命令がトラップが有効になった IEEE 浮動小数点例外を発生させる場合、命令は完了されません。宛先レジスタ、浮動小数点条件コード、および累積例外フラグは変更されず、現在の例外フラグはトラップの原因となった例外を反映するようにセットされ、カーネルは
SIGFPEシグナルをプロセスに送ります。次の疑似コードは、浮動小数点トラップの処理の概要を示しています。
aexcフィールドは、通常ソフトウェアでしかクリアーできません。
多くの浮動小数点命令がカーネルによってエミュレートされなければならないとき、プログラムのパフォーマンスは大幅に低下します。この状況が発生する相対頻度は、トラップの種類など、いくつかの要因によって異なります。
普通の状況では、
fp_disabledトラップはプロセスあたり 1 度だけ発生します。システムカーネルは、プロセスがはじめて開始されるときに浮動小数点ユニットを無効にします。そのため、プロセスによって実行される最初の浮動小数点演算がトラップを発生させます。トラップを処理したあと、カーネルは浮動小数点ユニットを有効にします。有効にされたユニットは、プロセスの間中、有効な状態が継続します。システム全体について浮動小数点ユニットを無効にすることも可能ですが、これはお勧めできません。カーネルまたはハードウェアのデバッグ目的にとどめてください。
unimplemented_FPopトラップは、実装していない命令に浮動小数点ユニットが出会う場合に必ず発生します。現在の SPARC 浮動小数点ユニットのほとんどは、4 倍精度命令を除いて『SPARC Architecture Manual, Version 8』に定義されている命令は少なくとも実装しており、また Sun WorkShop Compiler は 4 倍精度命令を生成しないため、ほとんどのシステムではこの種のトラップが発生することはありません。前述したように、FsMULd 命令を実装していない microSPARC-I および microSPARC-II プロセッサは例外ですので注意してください。この 2 つのプロセッサでのunimplemented_FPopトラップを避けるには、-xarch=v8aオプションを指定してプログラムをコンパイルしてください。残る 2 種類のトラップ、
unfinished_FPopおよびトラップされた IEEE 例外は、通常、NaN、無限大、および非正規数がかかわる特殊な演算状況に関連しています。IEEE 浮動小数点例外、NaN、および無限大
浮動小数点命令がトラップが有効になった IEEE 浮動小数点例外に出会うと、命令は完了されず、システムはプロセスに対して
SIGFPEシグナルを配布します。プロセスがすでにSIGFPEシグナルハンドラを確立している場合にはそのハンドラが呼び出されますが、それ以外の場合プロセスは停止します。トラップを有効にするのは通常、例外発生時にプログラムを停止するためであることから、メッセージを出力してプログラムを停止するシグナルハンドラを呼び出すか、あるいはシグナルハンドラがインストールされていないときにシステムのデフォルト動作にまとめ直すと、ほとんどのプログラムにおいてトラップされた IEEE 浮動小数点例外の発生が少なくなります。しかし、第 4 章で説明しているように、シグナルハンドラはトラップ命令に結果を供給して実行を継続することもできます。多くの浮動小数点例外がトラップされてこの方法で処理される場合は、パフォーマンスが大幅に低下することに注意してください。ほとんどの SPARC 浮動小数点ユニットは、少なくとも、無限オペランド、NaN オペランド、または IEEE 浮動小数点例外がかかわるケースでもトラップを起こします。これは、トラップが無効になっている場合や、トラップが有効になった例外を命令が引き起こさない場合でも同様です。これは、ハードウェアがこのような特殊なケースをサポートせず、
unfinished_FPopトラップを生成し、カーネルエミュレーションソフトウェアが命令を完了するに任せる場合に発生します。unfinished_FPopトラップとなる条件は、SPARC FPU の種類によって異なります。たとえば、初期のほとんどの SPARC FPU や hyperSPARC FPU は、トラップが有効かどうかにかかわらずすべての IEEE 浮動小数点例外でトラップします。UltraSPARC FPU は、浮動小数点例外のトラップが有効で、しかも命令が例外を発生させるかどうかをハードウェアが決定できないという場合に「悲観的に」トラップします。一方、SuperSPARC-I、SuperSPARC-II、TurboSPARC、microSPARC-I、および microSPARC-II FPU ではすべての例外的なケースがハードウェアで処理され、unfinished_FPopトラップが生成されることはありません。ほとんどの
unfinished_FPopは浮動小数点例外との組み合わせで発生するため、例外処理 (例外フラグのテスト、結果のトラップと置換、または例外発生時の停止) を行うことにより、過度のトラップの発生を避けることができます。もちろん、例外を処理する場合の労力と、例外がunfinished_FPopトラップとなるに任せる場合の労力のバランスをとるように注意してください。非正規数と標準外演算
一部の SPARC 浮動小数点ユニットが
unfinished_FPopトラップとなるもっとも一般的な状況として、非正規数が挙げられます。多くの SPARC FPU は、浮動小数点演算に非正規オペランドが含まれるか、浮動小数点演算がゼロ以外の非正規の結果 (段階的アンダーフローを起こす結果) を必ず生成する場合に常にトラップします。アンダーフローはさほど発生しませんが、プログラミングが困難です。また、アンダーフローされた中間結果の正確度は、演算の最終結果における全体的な正確度に通常はほとんど影響がありません。そのため、SPARC アーキテクチャには、非正規数がかかわるunfinished_FPopトラップに関連したパフォーマンス低下を避ける方法をユーザーに提供する標準外演算モードが含まれています。SPARC アーキテクチャは、標準外演算モードを明確には定義していません。SPARC アーキテクチャは、標準外演算モードが有効になるとき、このモードをサポートするプロセッサは IEEE 754 規格に準拠しない結果を生成できると述べているにすぎません。しかし、このモードをサポートする既存の SPARC 実装はすべて、このモードを使用して段階的アンダーフローを無効にし、すべての非正規オペランドと非正規結果をゼロに置換します。1 つだけ例外があります。Weitek 1164/1165 FPU は、標準外モードで非正規結果をゼロにフラッシュするだけで、非正規オペランドをゼロとして扱うことはありません。
SPARC 実装の中には、標準外モードを提供しないものもあります。SuperSPARC-I、SuperSPARC-II、TurboSPARC、microSPARC-I、および microSPARC-II 浮動小数点ユニットは、完全にハードウェア内で非正規オペランドの処理と非正規結果の生成を行うため、標準外演算をサポートする必要がありません (これらのプロセッサで標準外モードを有効にしても無視されます)。そのため、これらのプロセッサでは、段階的アンダーフローのためにパフォーマンスが低下することはありません。
段階的アンダーフローがプログラムのパフォーマンスに影響を与えているかどうかを調べるには、まずアンダーフローが実際に発生しているかどうかを調べ、続いてプログラムがどれだけシステム時間を使用しているかをチェックする必要があります。アンダーフローの発生の有無を調べるには、数学ライブラリ関数
ieee_retrospective()を使用して、プログラムの終了時にアンダーフロー例外フラグが発生するかを見ることができます。FORTRAN プログラムは、デフォルトでieee_retrospective()をコールします。C および C++ プログラムは、終了前に明示的にieee_retrospective()を呼び出す必要があります。アンダーフローが発生すると、ieee_retrospective()は次のようなメッセージを出力します。
Note: IEEE floating-point exception flags raised:
Inexact; Underflow;
See the Numerical Computation Guide, ieee_flags(3M)プログラムがアンダーフローに出会う場合、
timeコマンドを使用してプログラム実行の時間を測ることにより、プログラムがどれだけシステム時間を使用しているか確認できます。
demo% /bin/time myprog > myprog.output305.3 real 32.4 user 271.9 sysシステム時間 (上記例の 3 番目の数字) の値が異常に大きい場合、複数のアンダーフローが原因となっている場合があります。その場合、プログラムが段階的アンダーフローの正確度に依存していないときは、標準外モードを有効にしてパフォーマンスを高めることができます。この方法は 2 つあります。その 1 つは、プログラムの起動時に標準外モードを有効にするために、
-fnsフラグ (マクロ-fastと-fnonstdの一部として暗黙に示されます) を使用してコンパイルするものです。もう 1 つは、付加価値数学ライブラリlibsunmathが提供している、標準外モードを有効または無効にする 2 つの関数を使用するものです。nonstandard_arithmetic()を呼び出すと標準外モードが有効になり (このモードがサポートされている場合)、standard_arithmetic()を呼び出すと IEEE 動作が復元されます。次に、これらの関数を呼び出す C と FORTRAN の構文を示します。
C, C++ nonstandard_arithmetic(); standard_arithmetic(); FORTRAN call nonstandard_arithmetic() call standard_arithmetic()
警告 - 標準外演算モードでは段階的アンダーフローの利点である正確さが失われるため、このモードは注意して使用する必要があります。段階的アンダーフローの詳細は、第 2 章を参照してください。
標準外演算とカーネルのエミュレーション
標準外モードを実装している SPARC 浮動小数点ユニットでは、このモードを有効にすると、ハードウェアは非正規オペランドをゼロとして扱い、非正規結果をゼロにフラッシュします。しかし、トラップされた浮動小数点命令をエミュレートするために使用されるカーネルソフトウェアは、標準外モードを実装していません。この理由の 1 つは、このモードの効果が定義されておらず実装に依存しているためです。もう 1 つの理由は、段階的アンダーフロー処理に費やす労力がソフトウェアでの浮動小数点演算のエミュレーションの労力に比べてわずかなものであるためです。
標準外モードにより影響を受ける浮動小数点演算に割り込みが発生する場合 (たとえば、発行されたが、コンテキストの切り替えが起きたり別の浮動小数点命令がトラップを起こしたりして完了しなかった場合など)、カーネルソフトウェアが標準の IEEE 演算を使用してそれをエミュレートします。そのため特別な状況では、標準外モードで動作しているプログラムが、システム負荷に応じて少々異なる結果を出す可能性があります。実際には、まだこのような動作は発見されていません。このような動作は、何百万回もの演算の中の 1 つの演算が段階的アンダーフローで実行されるか、それとも非段階的なアンダーフローで実行されるかということに非常に敏感なプログラムだけに影響すると思われます。
fpversion(1) 関数 − FPU に関する情報の検索コンパイラと共に提供されている
fpversionユーティリティは、インストールされている CPU を識別し、プロセッサとシステムバスのクロック速度を予測します。fpversionは、CPU と FPU によって格納された識別情報を解釈することによって、CPU と FPU の型を確定します。また、予測可能な時間内に動作するシンプルな命令を実行するループの時間を測ることにより、それらのクロック速度を推定します。このループは、時間計測の正確度を上げるように何度も実行されるため、fpversionの結果は即座には出ません。実行には数秒かかります。
fpversionは、ホストシステムに使用する上で最適な-xtargetコード生成オプションも報告します。Ultra 4 ワークステーションでは、
fpversionは情報を次のように表示します。この表示は、タイミングやマシン構成の違いによって多少異なります。
|
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |