Sun Studio 12 Update 1: Fortran ユーザーズガイド

2.3.1 一般的な指令

一般的な Fortran 指令は次のような書式で使用します。

C$PRAGMA keyword ( a [ , a ] ) [ , keyword ( a [ , a ] ) ] ,

C$PRAGMA SUN keyword ( a [ , a ] … ) [ , keyword ( a [ , a ] … ) ] ,…

C$PRAGMA SPARC keyword ( a [ , a ] … ) [ , keyword ( a [ , a ] … ) ] ,…

変数 keyword は特定の指令を表します。追加の引数やサブオプションも指定できます。指令によっては、前述に示す SUNSPARC といった追加のキーワードを指定する必要があります。

一般的な指令の構文は、次のとおりです。

制限事項は、次のとおりです。

Fortran のコンパイラは、次の一般的な指令を認識します。

表 2–2 一般的な Fortran 指令の要約

C 指令

C$PRAGMA C(list)

外部関数の名前リストを C 言語のルーチンとして宣言します。 

IGNORE_TKR Directive

C$PRAGMA IGNORE_TKR {name {, name} ...}

コンパイラは、特定の呼び出しを解釈するとき、一般的な手続きのインタフェースで表示される仮引数名の型、種類、ランクを無視します。 

UNROLL Directive

C$PRAGMA SUN UNROLL=n

コンパイラに、次のループは長さ n に展開できることを伝えます。

WEAK Directive

C$PRAGMA WEAK(name[=name2])

name を弱いシンボル (weak symbol) または name2 の別名として宣言します。

OPT Directive

C$PRAGMA SUN OPT=n

副プログラムの最適化レベルを n に設定します。

PIPELOOP Directive

C$PRAGMA SUN PIPELOOP=n

次のループでは n 離れた反復間に依存関係があることを宣言します。

PREFETCH Directives

C$PRAGMA SUN_PREFETCH_READ_ONCE(name )C$PRAGMA SUN_PREFETCH_READ_MANY(name )C$PRAGMA SUN_PREFETCH_WRITE_ONCE(name )C$PRAGMA SUN_PREFETCH_WRITE_MANY(name )

名前の参照のために、先読み命令を生成するようにコンパイラに要求します。(-xprefetch オプションを指定する必要があります。このオプションはデフォルトで有効になっています。PREFETCH 指令は、—xprefetch=no でコンパイルし無効にします。ターゲットアーキテクチャーも PREFETCH 指令をサポートしている必要があり、コンパイラ最適化レベルは -xO2 より上である必要があります)。

ASSUME Directives

C$PRAGMA [BEGIN} ASSUME (expression [,probability])

C$PRAGMA END ASSUME

プログラム内の特定の個所において、コンパイラが真であると想定できる条件について表明を行います。 

2.3.1.1 C 指令

C() 指令は、その引数が外部関数であることを指定します。EXTERNAL 宣言と同義です。ただし、通常の外部名とは違って、Fortran コンパイラでは、これらの引数名に下線が付けられません。詳細は、『Fortranプログラミングガイド』の「C と Fortran のインタフェース」の章を参照してください。

特殊な関数の C() 指令は、各副プログラム中にある、その関数への最初の引用よりも前に現れなければなりません。

例: CABCXYZ をコンパイルします。


       EXTERNAL ABC, XYZ
C$PRAGMA C(ABC, XYZ)

2.3.1.2 IGNORE_TKR 指令

この指令では、コンパイラは、特定の呼び出しを解釈するとき、総称手続きのインタフェースで表示される仮引数名の型、種別、次元数を無視します。

たとえば、次の手続きのインタフェースでは、SRC はどのようなデータ型でもよく、LENKIND=4 または KIND=8 のいずれかであることが可能です。インタフェースブロックは、汎用的な手順名に対し 2 つの特定の手順を定義します。この例は、Fortran 95 自由形式で示されます。


INTERFACE BLCKX

SUBROUTINE BLCK_32(LEN,SRC)
  REAL SRC(1)
!$PRAGMA IGNORE_TKR SRC
  INTEGER (KIND=4) LEN
END SUBROUTINE

SUBROUTINE BLCK_64(LEN,SRC)
  REAL SRC(1)
!$PRAGMA IGNORE_TKR SRC
  INTEGER (KIND=8) LEN
END SUBROUTINE

END INTERFACE

The subroutine call:

INTEGER L
REAL S(100)
CALL BLCKX(L,S)

BLCKX の呼び出しによって、一般的なコンパイルでは BLCK_32 が呼び出され、-xtypemap=integer:64 を使用してコンパイルした場合は BLCK_64 が呼び出されます。S の実際の型は、どのルーチンを呼び出すかを定義しません。これによって、引数の型、種別、次元数に基づいてライブラリルーチンを呼び出すラッパーの一般的なインタフェースの記述を単純化できます。

形状引き継ぎの配列、Fortran ポインタ、割り当て可能な配列の仮引数は、指令では指定できません。名前が指定されていない場合は、形状引き継ぎの配列、Fortran ポインタ、割り当て可能な配列の仮引数を除いて、手続きのすべての仮引数に指令が適用されます。

2.3.1.3 UNROLL 指令

UNROLL 指令では、C$PRAGMA のあとに SUN と指定する必要があります。

C$PRAGMA SUN UNROLL=n 指令は、最適化パス中に、次のループを n 回展開するようにコンパイラに指示します。コンパイラは、解析の結果、ループの展開が適切であると判断した場合のみ展開します。

n は正の整数です。次の選択が可能です。

実際に展開されたループがあると、実行可能ファイルのサイズが大きくなります。詳細については、『Fortran プログラミングガイド 』のパフォーマンスと最適化に関する章を参照してください。

例: ループを 2 回展開するときは、次のように指定します。


C$PRAGMA SUN UNROLL=2

2.3.1.4 WEAK 指令

WEAK 指令は、以前に定義されているよりも低い優先順位で同じシンボルを定義します。この指令は主に、ライブラリを作成する場合にソースファイル中で使用されます。リンカーは弱いシンボルを解決できなくてもエラーメッセージを表示しません。


C$PRAGMA WEAK (name1 [=name2])

WEAK (name1) によって、name1 が優先順位の低いシンボルとして定義されます。この場合リンカーは、name1 の定義が見つけられなくてもエラーメッセージを出力しません。

WEAK (name1=name2) によって、name1 が優先順位の低いシンボルとして、また、name2 の別名として定義されます。

プログラムから呼び出された name1 が定義されていない場合、リンカーはライブラリの定義を使用します。ただし、プログラムで name1 の定義が行われている場合は、そのプログラムの定義が使用され、ライブラリ中にある name1 の優先順位が低い大域的な定義は使用されません。プログラムから name2 が直接呼び出されると、ライブラリの定義が使用されます。name2 の定義が重複すると、エラーが発生します。詳細は、Solaris の『リンカーとライブラリ』を参照してください。

2.3.1.5 OPT 指令

OPT 指令では、C$PRAGMA のあとに SUN と指定する必要があります。

OPT 指令は副プログラムの最適化レベルを設定し、コンパイルコマンド行に指定されているレベルは上書きされます。指令は副プログラムの直前に指定する必要があり、その副プログラムだけに適用されます。たとえば、次のようにします。


C$PRAGMA SUN OPT=2
        SUBROUTINE smart(a,b,c,d,e)
        ...etc

上記の例を、-O4 を指定する f95 コマンドでコンパイルする場合、指令はこのレベルを上書きして -O2 でサブルーチンをコンパイルします。このルーチンのあとに別の指令がないかぎり、次の副プログラムは -O4 でコンパイルされます。

ルーチンを -xmaxopt[ =n] オプションでコンパイルして、指令が認識されるようにする必要があります。このコンパイラオプションは PRAGMA OPT 指令の最適化の最大値を指定します。PRAGMA OPT に指定した最適化レベルが -xmaxopt レベルよりも大きいと、-xmaxopt レベルが使用されます。

2.3.1.6 PIPELOOP[= n] 指令

PIPELOOP=n 指令では、C$PRAGMA のあとに SUN と指定する必要があります。

この指令は DO ループの直前に指定する必要があります。n には正の整定数かゼロを指定し、ループの反復間の依存関係をオプティマイザに指示します。ゼロの値は反復間の依存関係 (ループの伝達性) がないことを示し、オプティマイザで自由にパイプラインできます。正の値の n はループの I 番目の反復が (I-n) 番目の反復に依存していることを意味し、一度に n 反復だけパイプラインできます。(n が指定されない場合のデフォルトは 0 です)


C    We know that the value of K is such that there can be no
C    cross-iteration dependencies (E.g. K>N)
C$PRAGMA SUN PIPELOOP=0
      DO I=1,N
       A(I)=A(I+K) + D(I)
       B(I)=B(I) + A(I)
      END DO

最適化についての詳細は、『Fortran プログラミングガイド』を参照してください。

2.3.1.7 PREFETCH 指令

-xprefetchオプションフラグを使用すると (「3.4.157 –xprefetch[= a[,a]]」を参照)、コンパイラに指示した一連の PREFETCH 指令は、先読みをサポートするプロセッサで指定のデータ要素について先読み命令を生成できます。


C$PRAGMA SUN_PREFETCH_READ_ONCE(name)
C$PRAGMA SUN_PREFETCH_READ_MANY(name)
C$PRAGMA SUN_PREFETCH_WRITE_ONCE(name)
C$PRAGMA SUN_PREFETCH_WRITE_MANY(name)

先読み命令についての詳細は、『C ユーザーズガイド』または『SPARC Architecture Manual, Version 9』も参照してください。

2.3.1.8 ASSUME 指令

ASSUME 指令は、プログラムの特定地点の条件についてコンパイラにヒントを与えます。これらの表明は、コンパイラへの最適化指示のガイドラインとして役立ちます。また、プログラマは、それらの指令を使用して、実行時にプログラムの妥当性をチェックできます。ASSUME のフォーマットは 2 種類あります。

「単一表明」ASSUME の構文は、次のようになります。


C$PRAGMA ASSUME (expression [,probability])

また、「範囲表明」ASSUME は、次のようになります。


C$PRAGMA BEGIN ASSUME [expression [, probability)
     block of statements
C$PRAGMA END ASSUME

単一表明形式を使用すると、プログラムのその地点でコンパイラが想定できる条件を示すことができます。範囲表明形式を使用すると、ステートメントの範囲内を通して成立する条件を示すことができます。範囲表明の BEGINEND のペアは正しくネストされる必要があります。

必要なは、上にリストされている以外でユーザー定義の演算子や関数呼び出しを含まないプログラムの特定地点で評価可能なブール式です。

オプションの probability 値は、0.0 から 1.0 までの実数、つまり整数の 0 または 1 であり、式が真となる可能性を示します。0.0 (または 0) の可能性は絶対に真にならないことを意味し、1.0 (または 1) は常に真になることを意味します。数値の指定がない場合、式は高い可能性で真とみなされますが、絶対ではありません。0 または 1 以外の可能性を持つ表明は「非確定表明」です。同様に、0 または 1 の可能性を持つ表明は「確定表明」です。

たとえば、DO ループが常に 10,000 より長いことがわかっている場合は、コンパイラにこれを示しておくと、より良いコードを生成できます。通常、次のループは、ASSUME プラグマがある場合の方がすばやく実行されます。


C$PRAGMA BEGIN ASSUME(__tripcount().GE.10000,1) !! a big loop
        do i = j, n
           a(i) = a(j) + 1
        end do
C$PRAGMA END ASSUME

特に ASSUME 指令の式クローズで使用するために、2 つの組み込み関数が用意されています。それらの名前の前には、2 つの下線が配置されます。

__branchexp()

ブール制御式を持つ分岐ステートメントの直前に配置された単一表明で使用します。分岐ステートメントを制御するブール式と同じ結果を生成します。 

__tripcount()

指令の直後または指令に閉じ込められたループのトリップカウントを生成します。単一表明で使用する場合、指令直後のステートメントは DO の最初の行となる必要があります。範囲表明で使用する場合、もっとも外側の閉じたループに適用します。

この特殊な組み込み関数のリストは、将来的なリリースで拡大する可能性があります。

-xassume_control コンパイラオプションとともに使用します。(「3.4.111 –xassume_control[ =keywords]」を参照) 。たとえば、-xassume_control=check を使用してコンパイルした場合、トリップカウントが 10,000 を下回ると警告が発せられます。

-xassume_control=retrospective を使用してコンパイルを実行すると、プログラムの終了時点ですべての表明の真と偽を示す要約レポートが生成されます。-xassume_control の詳細については、f95 のマニュアルページを参照してください。

もう 1 つの例


C$PRAGMA ASSUME(__tripcount.GT.0,1)
       do i=n0, nx

-xassume_control=check を使用して前述の例をコンパイルすると、トリップカウントが 0 かマイナスになるため、そのループを使用しないよう実行時の警告が発せられます。