Fortran プログラミングガイド |
第 7 章
移植
この章では、他の Fortran から Sun コンパイラへのプログラムの移植について説明します。VAX VMS Fortran プログラムであれば、大部分はそのまま Sun
f77
でコンパイルできます。詳細は、『FORTRAN 77 言語リファレンス』の 付録 D『VMS 言語拡張』を参照してください。
注 - 移植上の問題のほとんどは Fortran 77 プログラムに関連します。Sun Fortran 95 コンパイラf95
は、標準以外の拡張をほとんど組み込んでいません。これについては、『Fortran ユーザーズガイド』を参照してください。
時間と日付関数
時刻や CPU の経過時間を戻すライブラリ関数は、システムによって異なります。
次に示す時間関数は Sun Fortran ライブラリでは直接にはサポートされていません。ただし、これらの関数と同じ機能のサブルーチンをユーザーが作成できます。
次の表に、Sun Fortran ライブラリでサポートされる時間関数を示します。
詳細は、『Fortran ライブラリ・リファレンス』、またはそれぞれの関数のマニュアルページを参照してください。
次の表に示すルーチンは、VMS Fortran のシステムルーチン
idate
とtime
との互換機能を提供します。これらのルーチンを使用するときは、f77
のコマンド行で-lV77
オプションを指定しなければなりません。この場合、標準のf77
バージョンの代わりに VMS バージョンの方が使用されることになります。
表 7-2 非標準 VMS Fortran システムルーチンの要約 idate
日、月、年 (d,m,y) 形式の日付 call idate(d, m, y)
integer
time
時分秒 (hhmmss) 形式の現在時刻 call time(t)
character*8
注 -date
(3F) ルーチンおよびidate
(3F) ルーチンの VMS バージョンは年を示す場合に 2 桁の値しか返さないので、「2000 年には無効」 になります。これらのルーチンから返される日付を差し引いて継続時間を計算するプログラムは、1999 年 12 月 31 日以降は正しく機能しなくなります。Fortran 95 のルーチンdate_and_time
(3F) が FORTRAN 77 と Fortran 95 の両プログラムで使用できるので、これらのルーチンの代わりにdate_and_time
(3F) を使用してください。詳細は、『Fortran ライブラリ・リファレンス』を参照してください。
エラー条件のサブルーチンである
errsns
は完全に VMS オペレーティングシステムに特有のものであるため、この Fortran にはありません。次に、これら時間関数を使用した簡単な例を示します (
TestTim.f
)。
demo%TimeTest
Hello, Time Now Is: Mon Feb 12 11:53:54 1996See how long 'sleep 4' takes, in secondsElapsed time for sleep 4 was: 5 secondsatan(q) 1000 times took: 2.26550E-03 secondsdemo%書式
f77
およびf95
の書式編集記述子は、他のシステム上では動作が異なる場合があります。ここでは、f77
と他の実装では取り扱いの異なる編集記述子を示します。
A
- 英数値変換。文字型のデータ要素とともに使用します。Fortran では、この記述子はどの変数型でも使用できました。f77
では、従来の使用方法 (1 ワードに対して最大 4 文字まで) をサポートしています。$
- 改行文字の出力を抑制します。R
- 記述子中で、これに続く I 書式に対して任意の基数を設定します。SU
- これに続く I 書式に対して符号なし出力を選択します。たとえば、編集記述子のZ
またはO
を使用する代わりに、次に示す書式で出力を 16 進数または8
進数に変換できます。
10 FORMAT( SU, 16R, I4 )20 FORMAT( SU, 8R, I4 )キャリッジ制御
Fortran のキャリッジ制御は、Fortran が最初に開発されていたときに使用されていた装置の機能から発達したものです。同じ歴史上の理由のため、UNIX オペレーティングシステムから派生したオペレーティングシステムには、Fortran のキャリッジ制御がありません。しかし、次の 2 つの方法でシミュレートできます。
asa
フィルタを使用して、Fortran のキャリッジ制御規則を UNIX のキャリッジ制御書式に変換してから (asa
(1) のマニュアルページを参照してください)lpr
を使用してファイルを出力してください。f77
: 単純なジョブでは、OPEN(N, FORM='PRINT')
を使用します。これにより、1 行送りや 2 行送り、用紙送り、1 カラム目の除去の機能が実現されます。たとえば、装置 6 を開き直してFORM
パラメータを
OPEN( 6, FORM='PRINT')
- このようにして開いたファイルを、
lp
(1) コマンドを使用して出力できます。ファイルを扱う
Fortran の初期のシステムは名前付きファイルを使用せず、実際のファイル名と内部装置番号を対応させるコマンド行機構を提供していました。この機能は、標準の UNIX のリダイレクトなど、いくつかの方法でエミュレートできます。
例 :
stdin
をredir.data
からリダイレクトします。csh
(1) を使用した例です。
科学技術計算用メインフレームから移植する
アプリケーションコードが本来、CRAY や CDC などの 64 ビット (または 60 ビット) メインフレーム用に開発されていた場合、UltraSPARC-II プラットフォームへポーティングしているときに、これらのコードを次のオプションを付けてコンパイルしたい場合があります。
-fast -xarch=v9a -xchip=ultra2 \ -xtypemap=real:64,double:64,integer:64
このオプションは、自動的にすべてのデフォルトの
REAL
変数および定数をREAL*8
に、デフォルトのCOMPLEX
をCOMPLEX*16
に昇格させます。宣言されていない変数または単にREAL
やCOMPLEX
であると宣言されている変数だけを昇格させ、明示的に宣言された変数 (REAL*4
など) は昇格させません。単精度のREAL
定数もすべてREAL*8
に昇格されます (ターゲットプラットフォームに対して-xarch
や-xchip
を設定します)。デフォルトのDOUBLE PRECISION
データもREAL*16
に昇格させるには、-xtypemap
例でdouble:64
をdouble:128
に変更します。
-xtypemap
オプションは、-dbl、-r8、-i2
に優先します。詳細については、『Fortran ユーザーズガイド』、f77
(1) およびf95(1)
のマニュアルページを参照してください。より忠実にオリジナルのメインフレーム環境を再現したい場合は、オーバーフロー、ゼロ除算、無効演算時には停止するほうがよいかもしれません。主プログラムを
-ftrap=common
を付けてコンパイルすると、そのようになります。データ表現
Fortran におけるデータオブジェクトのハードウェア表現に関する詳細は、『FORTRAN 77 言語リファレンス』、『Fortran ユーザーズガイド』、『数値計算ガイド』を参照してください。通常、システムやハードウェアプラットフォーム間でデータ表現が異なると、移植性に関して重大な問題が生じます。
- サンの浮動小数点は IEEE 754 規格に準拠しているため、
REAL*8
の最初の 4 バイトはREAL*4
と同じではありません。- 実数型、整数型、論理型のデフォルトサイズは、
-xtypemap=
オプション (または-i2
、-dbl
、-r8
) を使用して変更する場合を除き、FORTRAN 77 規格に記述されています。- 文字変数は、自由に他の変数と
EQUIVALENCE
文で結合できます。しかし、境界合わせの問題が生じる可能性があるので注意が必要です。f77
IEEE 浮動小数点演算では、オーバーフローまたはゼロ除算に関する例外が発生しますが、デフォルトではSIGFPE
を発行したり、トラップしたりしません。例外のシグナルが発行される場合は、結果は IEEE の不定形式になります。詳細は、このマニュアルの第 6 章「浮動小数点演算」を参照してください。- 正規化された無限値が決定されることがあります。
libm_single
(3F) とlibm_double
(3F) のマニュアルページを参照してください。書式付き、および並びによる入出力文を使用すると、不定書式の書き込みや読み取りを行うことができます。ホレリスデータ
古い Fortran アプリケーションの多くは、ホレリス ASCII データを数値データオブジェクトに格納します。1977 Fortran 規格 (および Fortran 95) において、
CHARACTER
データ型はこの目的のために提供され、その使用が推奨されています。現在でも古い Fortran のホレリス (nH
) 機能を使用して変数を初期化できますが、標準的な使い方ではありません。次の表に、データ型に適合する文字の最大数を示します。この表では、太字のデータ型は、f77 コマンド行フラグ、-dbl、-r8、-xtypemap=
のいずれかによって昇格させられるデフォルトの型を示します。
通常の Fortran における標準 ASCII 文字の格納に関しては、次のことが言えます。
つまり、いずれのオプションの場合でも領域は用意されますが、通常の Fortran で
-r8
の場合は領域は利用できません。オプション
-i2、-r8、-dbl
は現在では使用しないので、代わりに-xtypemap
オプションを使用してください。
ホレリス定数を引数として渡したり、式や比較の中で使用しようとすると、ホレリス定数は文字型の式として解釈されます。
そのデータの型で使用しなければならない場合は、ホレリス定数によってデータ項目を初期化し、それを他のルーチンへ引き渡してください。
非標準コーディングの手順
一般的に、アプリケーションプログラムをあるシステムのコンパイラから別のシステムのコンパイラに移植するとき、非標準のコーティングを削除すれば、移植は簡単になります。あるシステムで成功した最適化や回避策が、他のシステムでは曖昧であり、コンパイラを混乱させることもあります。特に、特定のアーキテクチャ用に最適化された手作業によるチューニングは、他の場所ではパフォーマンスを低下させる原因となる可能性もあります。パフォーマンスとチューニングに関しては、第 8 章と第 9 章で述べます。しかし、次の話題は、移植に際して、一般的に考慮すべきことです。
初期化されない変数
局所変数や
COMMON
変数を自動的にゼロに初期化するシステムもあれば、「非数値」(NaN) に初期化するシステムもあります。しかし、標準的な取り決めはありません。したがって、プログラムは変数の初期値に関して仮定を行うべきではありません。移植性を最大限保証するために、プログラムはすべての変数を初期化すべきです。呼び出し間での別名での参照
別名での参照は、同じ記憶領域アドレスが複数の名前で参照されるときに発生します。これは、副プログラムへの実引数が、それら実引数間で、あるいは副プログラム内の
COMMON
変数間でオーバーラップしている場合に起こります。たとえば、引数X
とZ
は同じ記憶領域の位置を参照します。B
とH
も同様です。
COMMON /INS/B(100)REAL S(100), T(100)...CALL SUB(S,T,S,B,100)...SUBROUTINE SUB(X,Y,Z,H,N)REAL X(N),Y(N),Z(N),H(N)COMMON /INS/B(100)...このような別名での参照は、すべての移植可能なコードの中で避けるべきです。いくつかのシステム上で、高い最適化レベルを使用すると、予測できない結果になることがあります。
あいまいな最適化
古いコードには、古いベクトル化コンパイラに特定のアーキテクチャに最適なコードを生成させるための、通常の計算の
DO
ループを再構成しているソースコードが含まれていることがあります。ほとんどの場合、この再構成は必要がないもので、しかもプログラムの移植性を下げます。よく使用される再構成は、"strip-mining" (ストリップマイニング) とループの展開の 2 つです。ループセクショニング (strip-mining)
いくつかのアーキテクチャ上では、固定長のベクトルレジスタのために、プログラマは手作業でループ内の配列計算について、セグメントの中にループセクショニングをしなければなりませんでした。
REAL TX(0:63)...DO IOUTER = 1,NX,64DO IINNER = 0,63TX(IINNER) = AX(IOUTER+IINNER) * BX(IOUTER+IINNER)/2.QX(IOUTER+IINNER) = TX(IINNER)**2END DOEND DOループセクショニングは最近のコンパイラには適切でありません。このループは、次のようにより明瞭に書くことができます。
DO IX = 1,NTX = AX(I)*BX(I)/2.QX(I) = TX**2END DOループの展開
以前、手作業によるループの展開はソースコード最適化のための典型的なテクニックでした。しかし、現在はコンパイラがこの再構成を自動的に行います。
上記ループは、本来意図していたとおり、次のように書き換えるべきです。
DO K = 1,NDO J = 1,NDO I = 1,NA(I,J) = A(I,J) + B(I,K) * C(K,J)END DOEND DOEND DO問題の解決方法
ここでは、Sun Fortran に移植したプログラムが予想どおりに動かないときに何をすればいいのかを提案します。
結果が近いけれども正確ではない場合
- サイズと工学上の単位に注意してください。ゼロに非常に近い数が異なる場合がありますが、この差異はあまり問題ではありません。特にこの数が別のコンピュータで大陸の距離をフィートで演算して表したような 2 つの巨大数の差である場合などは問題ではありません。たとえば、1.9999999e-30 と -9.9992112e-33 は異なりますが、差異はほとんどありません。
VAX の数学演算は IEEE の数学演算と同じではなく、異なった IEEE プロセッサでさえも結果が違ってきます。特に、これは三角関数を多く含んでいる場合に顕著です。複雑な要因がからんでおり、また、標準仕様が厳密に定義するのは基本的な算術関数だけであるため、IEEE マシンの間にさえ微妙に差異があります。第 6 章「浮動小数点演算」を参照してください。
call nonstandard_arithmetic
を使用して実行してみてください。これもパフォーマンスをかなり向上させ、サンのワークステーションをより VAX システムに似せて動作させます。VAX または他のシステムが手近にある場合、その上でも実行してみてください。多くの数値アプリケーションが、浮動小数点の実装により多少異なる結果を生成するのは、ごく一般的なことです。NaN
、+Inf
やその他の考えられるエラーがないか検査してください。さまざまな例外をトラップする命令については、第 6 章「浮動小数点演算」や、ieee_handler
(3m) のマニュアルページを参照してください。ほとんどのマシンでは、これらの例外は単に実行を中止させるだけです。- 2 つの数が 6 x 1029 だけ異なっていても、浮動小数点の表現は同じになることもあります。次に、違う数であるのに同じ表現の例を示します。
real*4 x,yx=99999990e+29y=99999996e+29write (*,10), x, x10 format('99,999,990 x 10^29 = ', e14.8, ' = ', z8)write(*,20) y, y20 format('99,999,996 x 10^29 = ', e14.8, ' = ', z8)end
- 出力結果は次のようになります。
99,999,990 x 10^29 = 0.99999993E+37 = 7cf0bdc199,999,996 x 10^29 = 0.99999993E+37 = 7cf0bdc1- この例では、差は 6 x 1029 です。このような大きな差異が生じる理由は、IEEE の単精度で保証されているのは 10 進 - 2 進変換に対して 10 進の 6 桁だけだからです。7 桁や 8 桁を正しく変換できる場合もありますが、これは値によって異なります。
警告なしにプログラムが異常終了する
警告なしにプログラムが異常終了する場合で、実行のたびに異常が発生するまでの時間が異なる場合は、次のように対処してください。
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |