ASSERT ディレクティブはコンパイラーに、DO ループの特性に関する情報を提供します。これは、コンパイラーがソース・コードを最適化するのに役立ちます。
ASSERT ディレクティブが有効なのは、-qsmp または -qhot コンパイラー・オプションのどちらかが指定されている場合に限られます。
構文
>>-ASSERT--(--assertion--)------------------------------------->< |
規則
ASSERT ディレクティブに続く最初の非注釈行 (他のディレクティブは含まない) は、DO ループでなければなりません。この行は、無限の DO または DO WHILE ループにすることはできません。 ASSERT ディレクティブは、ディレクティブの直後にある DO ループにのみ適用され、ネストされた DO ループには適用されません。
ITERCNT は、DO ループが通常実行する繰り返し回数のおおまかな見積もりをコンパイラーに提供します。この値は正確である必要はありません。 ITERCNT はパフォーマンスにのみ影響し、正確度には影響しません。
NODEPS を指定すると、ユーザーは、DO ループ内、または DO ループ内から呼び出されたプロシージャー内に、ループによる依存性が存在しないことを明示的にコンパイラーに宣言したことになります。ループによる依存性には、DO ループ内にあって相互に妨害する 2 つの繰り返しが関係しています。妨害は、次の状況で生じます。
互いに補完する 2 つの ASSERT ディレクティブを 1 つの DO ループに適用することは可能です。しかし、ASSERT ディレクティブの後に、同一の DO ループの矛盾した ASSERT ディレクティブを入れることはできません。
!SMP$ ASSERT (ITERCNT(10)) !SMP$ INDEPENDENT, REDUCTION (A) !SMP$ ASSERT (ITERCNT(20)) ! invalid DO I = 1, N A(I) = A(I) * I END DO
上記の例では、ASSERT(ITERCNT(20)) ディレクティブは、 ASSERT(ITERCNT(10)) ディレクティブと矛盾しているので、無効です。
ASSERT ディレクティブは、ASSERT ディレクティブが指定されている DO ループの -qassert コンパイラー・オプションをオーバーライドします。
例
例 1:
! An example of the ASSERT directive with NODEPS. PROGRAM EX1 INTEGER A(100) !SMP$ ASSERT (NODEPS) DO I = 1, 100 A(I) = A(I) * FNC1(I) END DO END PROGRAM EX1 FUNCTION FNC1(I) FNC1 = I * I END FUNCTION FNC1
例 2:
! An example of the ASSERT directive with NODEPS and ITERCNT. SUBROUTINE SUB2 (N) INTEGER A(N) !SMP$ ASSERT (NODEPS,ITERCNT(100)) DO I = 1, N A(I) = A(I) * FNC2(I) END DO END SUBROUTINE SUB2 FUNCTION FNC2 (I) FNC2 = I * I END FUNCTION FNC2
関連情報
CNCALL ディレクティブを DO ループの前に置くと、ユーザーは、DO ループから呼び出されたプロシージャー内にループによる依存性が存在しないことをコンパイラーに明示的に宣言したことになります。 CNCALL ディレクティブが有効なのは、-qsmp または -qhot コンパイラー・オプションのいずれかが指定されているときに限られます。
構文
>>-CNCALL------------------------------------------------------>< |
規則
CNCALL ディレクティブに続く最初の非注釈行は、 DO ループでなければなりません。この行は、無限の DO または DO WHILE ループにすることはできません。 CNCALL ディレクティブは、ディレクティブの直後にある DO ループにのみ適用され、ネストされた DO ループには適用されません。
CNCALL ディレクティブを指定すると、ユーザーは、DO ループ内で呼び出されたプロシージャーにはループによる依存性がないことをコンパイラーに明示的に宣言したことになります。 DO ループがプロシージャーを呼び出す場合、ループのそれぞれの繰り返しがそのプロシージャーを同時に呼び出せなければなりません。 CNCALL ディレクティブは、ループ内の他の操作に依存性がないと断定するものではありません。これは単にプロシージャーの参照についての断定です。
ループによる依存性は、DO ループ内にある 2 つの繰り返しが互いに妨害するときに生じます。妨害の定義については、ASSERTを参照してください。
例
! An example of CNCALL where the procedure invoked has ! no loop-carried dependency but the code within the ! DO loop itself has a loop-carried dependency. PROGRAM EX3 INTEGER A(100) !SMP$ CNCALL DO I = 1, N A(I) = A(I) * FNC3(I) A(I) = A(I) + A(I-1) ! This has loop-carried dependency END DO END PROGRAM EX3 FUNCTION FNC3 (I) FNC3 = I * I END FUNCTION FNC3
関連情報
COLLAPSE ディレクティブは、配列次元の下限のエレメントのみがアクセス可能であると指定することによって、配列次元全体を単一のエレメントまでに削減します。下限を指定しない場合は、デフォルトの 下限は 1 になります。
慎重に使用すれば、COLLAPSE ディレクティブは、複数次元の配列に関連した反復メモリー・アクセスを削減することによって、容易にパフォーマンスを向上させることができます。
構文
>>-COLLAPSE--(--collapse_array_list--)------------------------->< |
collapse_array の意味は次のとおりです。
>>-array_name--(--expression_list--)--------------------------->< |
ここで expression_list は、コンマで区切られた式のリストです。
規則
COLLAPSE ディレクティブには、最低でも 1 つの配列を含む必要があります。
COLLAPSE ディレクティブは、そのディレクティブが指定されている有効範囲単位に対してのみ適用されます。 COLLAPSE ディレクティブに含まれる配列の宣言は、そのディレクティブと同じ有効範囲単位内にある必要があります。使用関連付けまたはホスト関連付けによって有効範囲単位内でアクセス可能な配列は、その有効範囲単位内の COLLAPSE ディレクティブに指定してはなりません。
expression_list に指定できる下限の値は 1 です。上限の値は、対応する配列内の次元数より大きくすることはできません。
単一の有効範囲単位に複数の COLLAPSE 宣言を含むことができますが、配列は特定の有効範囲単位について一度だけしか指定できません。
1 つの配列を COLLAPSE ディレクティブと EQUIVALENCE ステートメントの両方に指定することはできません。
COLLAPSE ディレクティブは、派生型のコンポーネントである配列と一緒に使用することはできません。
1 つの配列に対して COLLAPSE と SUBSCRIPTORDER の両方のディレクティブを適用する場合は、最初に SUBSCRIPTORDER ディレクティブを指定する必要があります。
COLLAPSE ディレクティブは、以下の配列に適用されます。
例
例 1: 以下の例では、COLLAPSE ディレクティブは明示的形状配列 A および B に適用されます。内部ループの A(m,2:100,2:100) と B(m,2:100,2:100) の参照は、 A(m,1,1) と B(m,1,1) になります。
!IBM* COLLAPSE(A(2,3),B(2,3)) REAL*8 A(5,100,100), B(5,100,100), c(5,100,100) DO I=1,100 DO J=1,100 DO M=1,5 A(M,J,I) = SIN(C(M,J,I)) B(M,J,I) = COS(C(M,J,I)) END DO DO M=1,5 DO N=1,M C(M,J,I) = C(M,J,I) + A(N,J,I)*B(6-N,J,I) END DO END DO END DO END DO END
関連情報
SUBSCRIPTORDER ディレクティブの詳細については、SUBSCRIPTORDERを参照してください
EJECT は、ソース・リストの新しいページを開始するようコンパイラーに指示するためのものです。ソース・リストの要求がない場合、コンパイラーは、このディレクティブを無視します。
構文
>>-EJECT------------------------------------------------------->< |
規則
EJECT コンパイラー・ディレクティブには、インライン注釈やラベルを組み込めます。しかし、ステートメント・ラベルを指定しても、コンパイラーはそれを破棄します。したがって、EJECT ディレクティブ内のラベルを参照してはなりません。 EJECT ディレクティブの使用例としては、リスト内の複数ページに分割したくない重要な DO ループがある場合、そのループの前で使用します。ソース・リストをプリンターに送信すると、EJECT ディレクティブは改ページの役目を果たします。
INCLUDE コンパイラー・ディレクティブは、指定されたステートメントまたは一群のステートメントをプログラム単位に挿入します。
構文
>>-INCLUDE--+-char_literal_constant-+--+---+------------------->< '-(--name--)------------' '-n-' |
AIX オペレーティング・システムの場合、ファイルの絶対パスを指定する必要はありません。ただし、ファイル拡張子がある場合は、拡張子を指定する必要があります。
name には、XL Fortran の文字セットで使用可能な文字のみを入れます。 XL Fortran でサポートしている文字については、文字を参照してください。
char_literal_constant は文字リテラル定数です。
条件付き INCLUDE と呼ばれる機能は、コンパイル時に、Fortran ソース内の INCLUDE コンパイラー・ディレクティブを選択的に活動化状態にする方法を提供します。インクルード・ファイルの指定は、コンパイラー・オプション -qci を使用して行います。
固定ソース形式では、INCLUDE コンパイラー・ディレクティブは列 6 から始める必要があります。ラベルも付けられます。
インライン注釈を INCLUDE 行に追加することができます。
規則
インクルード・ファイルには、完全な Fortran ソース・ステートメントまたはコンパイラー・ディレクティブであれば、どのようなステートメント (他の INCLUDE コンパイラー・ディレクティブも含む) でも入れることができます。再帰的 INCLUDE コンパイラー・ディレクティブは使用できません。 END ステートメントは組み込まれるグループに含めてもかまいません。最初および最後の組み込み行は、継続行であってはなりません。インクルード・ファイルのステートメントは、組み込み先のファイルのソース形式で処理されます。
SOURCEFORM ディレクティブがインクルード・ファイル内にある場合、インクルード・ファイルの処理が完了すると、ソース形式は、組み込み先のファイルのソース形式に戻ります。すべてのグループを組み込んで完成した Fortran プログラムは、ステートメントの順序に関する Fortran のすべての規則に従うものでなければなりません。
XL Fortran は、左括弧と右括弧の構文を持つ INCLUDE コンパイラー・ディレクティブについて、-qmixed コンパイラー・オプションがオンになっている場合を除いて、ファイル名を小文字に変換します。
AIX ファイル・システムは、filename で指定されたファイルを次のようにして見つけます。
例
INCLUDE '/u/userid/dc101' ! full absolute file name specified INCLUDE '/u/userid/dc102.inc' ! INCLUDE file name has an extension INCLUDE 'userid/dc103' ! relative path name specified
INCLUDE (ABCdef) ! includes file abcdef
INCLUDE '../Abc' ! includes file Abc from parent directory ! of directory being searched
関連情報
「ユーザーズ・ガイド」の『-qci オプション』
INDEPENDENT ディレクティブを使用する場合は、 DO ループ、FORALL ステートメント、または FORALL 構造体の前に置かなければなりません。 INDEPENDENT ディレクティブは、FORALL ステートメントまたは FORALL 構造体の各演算をどの順序で行ってもプログラムのセマンティクスに影響しないで済むようにします。このディレクティブは、プログラムのセマンティクスに影響することなく、 DO ループ内で任意の順序で反復を行うことを指定します。
INDEPENDENT ディレクティブが有効なのは、-qsmp または -qhot コンパイラー・オプションのいずれかが指定されているときに限られます。
構文
.---------------------------------------------. V | >>-INDEPENDENT----+-----------------------------------------+-+->< +-,--NEW--(--named_variable_list--)-------+ '-,--REDUCTION--(--named_variable_list--)-' |
規則
INDEPENDENT に続く最初の非注釈行 (他のディレクティブは含まない) は、DO ループ、 FORALL ステートメント、または FORALL 構造体の最初のステートメントでなければなりません。この行は、無限の DO または DO WHILE ループにすることはできません。 INDEPENDENT ディレクティブは、ディレクティブの直後にある DO ループにのみ適用され、ネストされた DO ループには適用されません。
INDEPENDENT ディレクティブには、最大で 1 つの NEW 文節と最大で 1 つの REDUCTION 文節を組み込めます。
このディレクティブを DO ループに適用すると、ループの繰り返しは互いに妨害することはありません。妨害は、次の状況で生じます。
NEW 文節を指定する場合は、このディレクティブを DO ループに適用する必要があります。 NEW 文節は、このディレクティブとそのまわりにある INDEPENDENT ディレクティブを修正します。この修正は、NEW 文節がそのようなディレクティブによる断定を正しいと見なすことによって生じるもので、 NEW 文節で指定されている変数がループの繰り返しごとに修正される場合でも発生します。 NEW 文節で指定されている変数は、DO ループ本体のプライベート変数であるかのような働きをします。つまり、これらの変数 (およびそれと関連している変数) がループの繰り返しの前後に未定義になっても、プログラムには影響がありません。
NEW 文節または REDUCTION 文節で指定する変数には、次の制約事項があります。
FORALL の場合、INDEPENDENT ディレクティブによって影響を受けた指標値の組み合わせは、他の組み合わせによって要求されるまではアトミック記憶単位に割り振りを行いません。 DO ループ、FORALL ステートメント、または FORALL 構造体が同じ本体を持ち、それぞれの前に INDEPENDENT ディレクティブがある場合、これらはみな同じ機能を果たします。
REDUCTION 文節は、INDEPENDENT ループの REDUCTION ステートメント内で名前付き変数が更新されたと断定します。さらに並列セクション内では、REDUCTION 変数の中間値は、更新そのもの以外では使用されません。したがって、構造体の後の REDUCTION 変数の値は、縮約ツリーの結果になります。
REDUCTION 文節を指定する場合は、このディレクティブを DO ループに適用しなければなりません。 INDEPENDENT DO ループの REDUCTION 変数に対する唯一の参照は、縮約ステートメントになければなりません。
REDUCTION 変数は、組み込みタイプでなければなりませんが、タイプ文字であってはなりません。 REDUCTION 変数は割り振り可能配列にはできません。
REDUCTION 変数は、以下のものの中に入れることはできません。
REDUCTION ステートメントの形式は、次のいずれかになります。
>>-reduction_var_ref--=--expr--reduction_op--reduction_var_ref->< >>-reduction_var_ref--=--reduction_var_ref--reduction_op--expr->< >>-reduction_var_ref =--reduction_function--(expr,--reduction_var_ref)->< >>-reduction_var_ref =--reduction_function--(reduction_var_ref,--expr)->< |
それぞれの意味は次のとおりです。
REDUCTION ステートメントには次の規則が適用されます。
>>-reduction_var_ref-- = --expr-- - --reduction_var_ref-------->< |
例
例 1:
INTEGER A(10),B(10,12),F !IBM* INDEPENDENT ! The NEW clause cannot be FORALL (I=1:9:2) A(I)=A(I+1) ! specified before a FORALL !IBM* INDEPENDENT, NEW(J) DO M=1,10 J=F(M) ! 'J' is used as a scratch A(M)=J*J ! variable in the loop !IBM* INDEPENDENT, NEW(N) DO N=1,12 ! The first executable statement B(M,N)=M+N*N ! following the INDEPENDENT must END DO ! be either a DO or FORALL END DO END
例 2:
X=0 !IBM* INDEPENDENT, REDUCTION(X) DO J = 1, M X = X + J**2 END DO
例 3:
INTEGER A(100), B(100, 100) !SMP$ INDEPENDENT, REDUCTION(A), NEW(J) ! Example showing an array used DO I=1,100 ! for a reduction variable DO J=1, 100 A(I)=A(I)+B(J, I) END DO END DO
関連情報
#line ディレクティブは、cpp によって作成されるコードまたは Fortran ソース・コード生成プログラムを、プログラマーによって作成される入力コードと関連付けます。プリプロセッサーによりコード行が挿入されたり削除されたりすることがありますが、#line ディレクティブはオリジナルのソースのどの行からプリプロセッサーが中間ファイルの対応する行を生成したかを示すので、エラーの報告やデバッグの際に便利です。
構文
>>-#line--line_number--+----------+---------------------------->< '-filename-' |
#line ディレクティブは非注釈ディレクティブであり、このタイプのディレクティブの構文規則に従います。
規則
#line ディレクティブは、他の非注釈ディレクティブと同じ規則に従います。ただし、次のものは例外です。
#line ディレクティブは、現行ファイルのそのディレクティブに続くすべてのコードの起点を示します。別の #line ディレクティブが現れると、前のものは取り消されます。
filename を指定すると、現行ファイル内の続くコードは、その起点がその filename からであるときと同じようになります。 filename を省略し、現行ファイル内のそれよりも前に filename を指定した #line ディレクティブが存在しない場合、現行ファイルのコードは、指定された行番号の現行ファイルが起点になっているかのように扱われます。 filename が指定されている、前の #line ディレクティブが現行ファイルに存在する場合、その前のディレクティブの filename が使用されます。
line_number は、適切なファイル内の、ディレクティブに続くコードの行の位置を示します。そのファイル内の続く行は、別の #line ディレクティブが指定されるか、またはファイルが終了するまで、ソース・ファイルにある続く行と 1 対 1 で対応していると想定されます。
XL Fortran がファイルに対して cpp を起動するときに、プリプロセッサーは、#line ディレクティブを出力します。これは、-d オプションを指定すると行われません。
例
ファイル test.F の内容は以下のとおりです。
! File test.F, Line 1 #include "test.h" PRINT*, "test.F Line 3" ... PRINT*, "test.F Line 6" #include "test.h" PRINT*, "test.F Line 8" END
ファイル test.h の内容は以下のとおりです。
! File test.h line 1 RRINT*,1 ! Syntax Error PRINT*,2
C プリプロセッサー (/lib/cpp) で、デフォルト・オプションを指定してファイル test.F を処理した後は次のようになります。
#line 1 "test.F" ! File test.F, Line 1 #line 1 "test.h" ! File test.h Line 1 RRINT*,1 ! Syntax Error PRINT*,2 #line 3 "test.F" PRINT*, "test.F Line 3" ... #line 6 PRINT*, "test.F Line 6" #line 1 "test.h" ! File test.h Line 1 RRINT*,1 ! Syntax Error PRINT*,2 #line 8 "test.F" PRINT*, "test.F Line 8" END
コンパイラーは、C プリプロセッサーによって作成されたファイルを処理した後に、次のメッセージを表示します。
2 2 |RRINT*,1 !Syntax error ......a................ a - "t.h", line 2.6: 1515-019 (S) Syntax is incorrect. 4 2 |RRINT*,1 !Syntax error ......a................ a - "t.h", line 2.6: 1515-019 (S) Syntax is incorrect.
関連情報
PERMUTATION ディレクティブは、integer_array_name_list でリストされている各配列のエレメントが繰り返し値を持たないように指定します。このディレクティブは、配列エレメントが他の配列参照の添え字として使用されているときに便利です。
PERMUTATION ディレクティブが有効なのは、-qsmp または -qhot コンパイラー・オプションのいずれかが指定されているときに限られます。
構文
>>-PERMUTATION--(--integer_array_name_list--)------------------>< |
規則
PERMUTATION ディレクティブに続く最初の非注釈行 (他のディレクティブは含まない) は、DO ループでなければなりません。この行は、無限の DO または DO WHILE ループにすることはできません。 PERMUTATION ディレクティブは、ディレクティブの直後にある DO ループにのみ適用され、ネストされた DO ループには適用されません。
例
PROGRAM EX3 INTEGER A(100), B(100) !SMP$ PERMUTATION (A) DO I = 1, 100 A(I) = I B(A(I)) = B(A(I)) + A(I) END DO END PROGRAM EX3
関連情報
ソース・ファイルに @PROCESS コンパイラー・ディレクティブを入れることにより、個々のコンパイル単位に影響を与えるようにコンパイラー・オプションを指定することができます。構成ファイルまたはデフォルト設定あるいはコマンド行で指定したオプションをオーバーライドすることができます。
構文
.-+---+----------------------------. | '-,-' | V | >>-@PROCESS----option--+----------------------+-+-------------->< '-(--suboption_list--)-' |
規則
固定ソース形式では、@PROCESS は 1 桁目から、または 6 桁目より後から開始できます。自由ソース形式では、@PROCESS コンパイラー・ディレクティブは、どの桁からでも開始できます。
ステートメント・ラベルまたはインライン注釈を @PROCESS コンパイラー・ディレクティブと同じ行に入れることはできません。
デフォルト時には、@PROCESS コンパイラー・ディレクティブで指定するオプション設定は、ステートメントが存在するコンパイル単位に対してのみ有効です。ファイルが複数のコンパイル単位を持っている場合は、オプション設定は、次の単位がコンパイルされる前に、元の状態にリセットされます。 DIRECTIVE オプションによって指定されたトリガー定数は、ファイルの終わりまで (または、NODIRECTIVE が処理されるまで) 有効です。
@PROCESS コンパイラー・ディレクティブは、通常、コンパイル単位の最初のステートメントの前になければなりません。唯一の例外は、SOURCE および NOSOURCE を指定する場合です。この 2 つは、コンパイル単位内のいかなる場所にある @PROCESS ディレクティブでも使用できます。
関連情報
コンパイラー・オプションの詳細については、「ユーザーズ・ガイド」の『コンパイラー・オプションの詳細』を参照してください。
SNAPSHOT ディレクティブを使用して、デバッグ・プログラムでブレークポイントを設定できる安全な位置を指定できます。さらに、デバッグ・プログラムに対して可視にする必要のある変数のセットを提供できます。 SNAPSHOT ディレクティブは、 -qsmp コンパイラー・オプション (非マルチスレッド・プログラムでも使用できます) のサポートを提供します。
SNAPSHOT ディレクティブが設定されたポイントで、わずかなパフォーマンス低下がある場合があります。これは、デバッグ・プログラムがアクセスするために、変数をメモリーに保持する必要があるためです。 SNAPSHOT ディレクティブによって可視にされた変数は、読み取り専用です。これらの変数をデバッガーを通して変更すると、未定義の動作が発生します。慎重に使用してください。
構文
>>-SNAPSHOT--(--named_variable_list--)------------------------->< |
規則
SNAPSHOT ディレクティブを使用するには、コンパイル時に -qdbg コンパイラー・オプションを指定する必要があります。
例
例 1: 次の例では、プライベート変数の値をモニターするために、 SNAPSHOT ディレクティブが使用されています。
INTEGER :: IDX INTEGER :: OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM INTEGER, ALLOCATABLE :: ARR(:) ! ... !$OMP PARALLEL, PRIVATE(IDX) !$OMP MASTER ALLOCATE(ARR(OMP_GET_NUM_THREADS())) !$OMP END MASTER !$OMP BARRIER IDX = OMP_GET_THREAD_NUM() + 1 !IBM* SNAPSHOT(IDX) ! The PRIVATE variable IDX is made visible ! to the debugger. ARR(IDX) = 2*IDX + 1 !$OMP END PARALLEL
例 2: 次の例では、プログラムのデバッグで中間値をモニターするために、 SNAPSHOT ディレクティブが使用されます。
SUBROUTINE SHUFFLE(NTH, XDAT) INTEGER, INTENT(IN) :: NTH REAL, INTENT(INOUT) :: XDAT(:) INTEGER :: I_TH, IDX, PART(1), I, J, LB, UB INTEGER :: OMP_GET_THREAD_NUM INTEGER(8) :: Y=1 REAL :: TEMP CALL OMP_SET_NUM_THREADS(NTH) PART = UBOUND(XDAT)/NTH !$OMP PARALLEL, PRIVATE(NUM_TH, I, J, LB, UB, IDX, TEMP), SHARED(XDAT) NUM_TH = OMP_GET_THREAD_NUM() + 1 LB = (NUM_TH - 1)*PART(1) + 1 UB = NUM_TH*PART(1) DO I=LB, UB !$OMP CRITICAL Y = MOD(65539_8*y, 2_8**31) IDX = INT(REAL(Y)/REAL(2_8**31)*(UB - LB) + LB) !SMP$ SNAPSHOT(i, y, idx, num_th, lb, ub) !$OMP END CRITICAL TEMP = XDAT(I) XDAT(I) = XDAT(IDX) XDAT(IDX) = TEMP ENDDO !SMP$ SNAPSHOT(TEMP) ! The user can examine the value ! of the TEMP variable !$OMP END PARALLEL END
関連情報
-qdbg コンパイラー・オプションの詳細については、「ユーザーズ・ガイド」を参照してください。
SOURCEFORM コンパイラー・ディレクティブは、ファイルの終わりに到達するか、@PROCESS ディレクティブまたは別の SOURCEFORM ディレクティブが異なるソース形式を指定するまで、後続するすべての行を指定のソース形式で処理するように指示します。
構文
>>-SOURCEFORM--(--source--)------------------------------------>< |
規則
SOURCEFORM ディレクティブは、ファイルのどの位置にでも入れることができます。インクルード・ファイルは、インクルード・ファイルのソース形式でコンパイルされます。 SOURCEFORM ディレクティブがインクルード・ファイル内にある場合、インクルード・ファイルの処理が完了すると、ソース形式は、組み込み先のファイルのソース形式に戻ります。
SOURCEFORM ディレクティブでは、ラベルを指定することはできません。
ヒント |
---|
既存のファイルをインクルード・ファイルを含む Fortran 90 自由形式に変更するには、次のように行います。
|
例
@PROCESS DIRECTIVE(CONVERT*) PROGRAM MAIN ! Main program not yet converted A=1; B=2 INCLUDE 'freeform.f' PRINT *, RESULT ! Reverts to fixed form END
ファイル freeform.f には以下のコードが含まれています。
!CONVERT* SOURCEFORM(FREE(F90)) RESULT = A + B
STREAM_UNROLL ディレクティブはコンパイラーに対して、ソフトウェア・プリフェッチとループ・アンロールを結合した機能を反復カウントの大きな DO ループに適用することを指示します。ストリーム・アンロール機能は POWER4 以上のプラットフォームでのみ使用可能で、DO ループを最適化して複数のストリームを使用します。 STREAM_UNROLL は内部と外部の両方の DO ループに指定できます。コンパイラーは、可能であればストリームの適切な番号を使用してストリーム・アンロールを実行します。依存関係を持つループに STREAM_UNROLL を適用すると、予期しない結果が生じます。
構文
>>---STREAM_UNROLL--+---------------------+-------------------->< '-(--unroll_factor--)-' |
規則
-qhot、-qipa=level=2、または -qsmp コンパイラー・オプションを指定して、ストリーム・アンロールを可能にする必要があります。最適化レベルを -O4 以上にすることによっても、コンパイラーでストリーム・アンロールを実行できます。
ストリーム・アンロールを行う場合、STREAM_UNROLL ディレクティブは DO ループの前になければなりません。
STREAM_UNROLL ディレクティブを複数回指定することはできません。また、1 つの DO 構文で、このディレクティブを UNROLL、NOUNROLL、UNROLL_AND_FUSE、または NOUNROLL_AND_FUSE ディレクティブと結合することはできません。
STREAM_UNROLL ディレクティブを DO WHILE ループ および無限 DO ループに指定することはできません。
例
以下に、パフォーマンスを向上できる STREAM_UNROLL の例を示します。
integer, dimension(1000) :: a, b, c integer i, m, n !IBM* stream_unroll(4) do i =1, n a(i) = b(i) + c(i) enddo end
unroll factor は、次のようにして、反復数を n から n/4 まで減らします。
m = n/4 do i =1, n/4 a(i) = b(i) + c(i) a(i+m) = b(i+m) + c(i+m) a(i+2*m) = b(i+2*m) + c(i+2*m) a(i+3*m) = b(i+3*m) + c(i+3*m) enddo
読み取り操作と保管操作の増加数は、コンパイラーが決定したストリーム数に振り分けられ、計算時間が短縮されてパフォーマンスが向上します。
関連情報
SUBSCRIPTORDER ディレクティブは、配列の添え字を再配置します。ディレクティブが宣言で配列次元の順序を変更するので、この結果、新しい配列形状になります。配列に対するすべての参照は、新しい配列形状に一致させるために、それに応じて再配置されます。
慎重に使用すれば、SUBSCRIPTORDER ディレクティブは、キャッシュ・ヒット数およびデータ・プリフェッチの量を増やすことによって、パフォーマンスを向上させることができます。パフォーマンスを最大限に上げる配置が見つかるまで、このディレクティブを試さなければならない場合があります。通常キャッシュを使用しないハードウェア・アーキテクチャー用であったコードを移植するときは、特に SUBSCRIPTORDER が便利です。
PowerPC などのキャッシュを使用するハードウェア・アーキテクチャーでは、各データ・エレメントにアクセスするために、データのキャッシュ・ライン全体がプロセッサーにロードされることがよくあります。ストレージ配置の変更を使用して、連続してアクセスされるエレメントを隣接して保管することができます。参照される各キャッシュ・ラインのエレメントのアクセスが増えるに従って、パフォーマンスが向上します。さらに、連続してアクセスされる配列エレメントを隣接して保管すると、プロセッサーのプリフェッチ機能を活用するために役立ちます。
構文
.-,--------------------. V | >>-SUBSCRIPTORDER--(----subscriptorder_array-+--)-------------->< |
subscriptorder_array の意味は次のとおりです。
.-,---------------------. V | >>-array_name--(----subscriptorder_number-+--)----------------->< |
規則
SUBSCRIPTORDER ディレクティブは、subscriptorder_array リスト内の配列に対するすべての宣言または参照に先行する有効範囲単位で使用する必要があります。ディレクティブはその有効範囲単位のみに適用され、少なくとも 1 つの配列を含む必要があります。複数の有効範囲単位が 1 つの配列を共用する場合は、 SUBSCRIPTORDER ディレクティブを、同一の添え字配置で、適用できるそれぞれの有効範囲単位に適用する必要があります。有効範囲単位間で配列を共用する方法の例には、 COMMON ステートメント、USE ステートメント、およびサブルーチン引き数があります。
subscriptorder_number リスト内の最小の添え字の番号は、1 にする必要があります。最大番号は、対応する配列内の次元数と等しくなければなりません。これら 2 つの限界の間にある各整数の数値 (限界の値を含む) は、再配置の前の添え字の番号を示し、リストに正確に 1 度だけ含まれている必要があります。
有効範囲単位内の特定の配列に対し、SUBSCRIPTORDER ディレクティブを、複数回適用してはなりません。
配列の 1 つを SUBSCRIPTORDER ディレクティブで使用する場合、エレメント型プロシージャーに対する実際の引き数として配列を渡すときには、配列形状の一致を維持する必要があります。さらに、SHAPE、SIZE、LBOUND、および UBOUND 照会組み込みプロシージャーの実引き数、および大部分の変形可能組み込みプロシージャーの実引き数も調整する必要があります。
入力データ・ファイルのデータ、および SUBSCRIPTORDER ディレクティブ内で使用する配列の明示的初期化のデータは、手動で変更する必要があります。
さらに COLLAPSE ディレクティブも適用される配列上では、 COLLAPSE ディレクティブは、常に以前の subscriptorder 次元数を参照します。
想定サイズ配列の最後の次元を再配置してはなりません。
例
例 1: 次の例では、 SUBSCRIPTORDER ディレクティブは明示的形状配列に適用され、プログラム出力に影響を及ぼすことなく、配列のそれぞれの参照で添え字をスワップします。
!IBM* SUBSCRIPTORDER(A(2,1)) INTEGER COUNT/1/, A(3,2) DO J = 1, 3 DO K = 1, 2 ! Inefficient coding: innermost index is accessing rightmost ! dimension. The subscriptorder directive compensates by ! swapping the subscripts in the array's declaration and ! access statements. ! A(J,K) = COUNT PRINT*, J, K, A(J,K) COUNT = COUNT + 1 END DO END DO
上記のディレクティブがない場合は、配列の形状は (3,2) になり、配列エレメントは、次の順序で保管されます。
A(1,1) A(2,1) A(3,1) A(1,2) A(2,2) A(3,2)
上記のディレクティブがある場合、配列の形状は (2,3) になり、配列エレメントは、次の順序で保管されます。
A(1,1) A(2,1) A(1,2) A(2,2) A(1,3) A(2,3)
関連情報
COLLAPSE ディレクティブの詳細については、COLLAPSEを参照してください。
UNROLL ディレクティブはコンパイラーに対して、可能であればループ・アンロールを試みることを指示します。ループ・アンロールは DO ループの本体を複製して、ループを完了するために必要となる反復の回数を減らします。
-qunroll コンパイラー・オプションを指定して、ファイル全体のループ・アンロールを制御できます。特定の DO ループにディレクティブを指定すると、コンパイラー・オプションは必ずオーバーライドされます。
構文
>>-+-UNROLL--+---------------------+-+------------------------->< | '-(--unroll_factor--)-' | '-NOUNROLL------------------------' |
規則
ループ・アンロールを行う場合、UNROLL ディレクティブは DO ループの前になければなりません。
UNROLL ディレクティブを複数回指定することはできません。また、1 つの DO 構文で、このディレクティブを NOUNROLL、STREAM_UNROLL、UNROLL_AND_FUSE、または NOUNROLL_AND_FUSE ディレクティブと結合することはできません。
UNROLL ディレクティブを DO WHILE ループ および無限 DO ループに指定することはできません。
例
例 1: この例では、1 回の繰り返しで 2 回の繰り返し作業が実行されるよう、ループ本体が複製可能であることをコンパイラーに通知するために、UNROLL(2) ディレクティブが使用されています。コンパイラーがループをアンロールすると、コンパイラーは 1000 回の繰り返しを実行するのではなく、500 回だけ繰り返しを実行します。
!IBM* UNROLL(2) DO I = 1, 1000 A(I) = I END DO
コンパイラーが直前のループをアンロールすることを選択すると、コンパイラーはそのループが本質的に以下と同じになるようにそのループを変換します。
DO I = 1, 1000, 2 A(I) = I A(I+1) = I + 1 END DO
例 2: 最初の DO ループでは、 UNROLL(3) が使用されています。アンロールが実行されると、コンパイラーは 1 回の繰り返しで 3 回の繰り返し作業が行われるように、ループをアンロールします。 2 番目の DO ループでは、コンパイラーはパフォーマンスが最大になるようにループをアンロールする方法を決定します。
PROGRAM GOODUNROLL INTEGER I, X(1000) REAL A, B, C, TEMP, Y(1000) !IBM* UNROLL(3) DO I = 1, 1000 X(I) = X(I) + 1 END DO !IBM* UNROLL DO I = 1, 1000 A = -I B = I + 1 C = I + 2 TEMP = SQRT(B*B - 4*A*C) Y(I) = (-B + TEMP) / (2*A) END DO END PROGRAM GOODUNROLL
関連情報
UNROLL_AND_FUSE ディレクティブはコンパイラーに対して、可能であればループ・アンロールとヒューズを試みることを指示します。ループ・アンロールは、DO ループの複数の本体を複製して、必要な反復を 1 つのアンロール・ループに結合します。フューズ・ループを使用すると、ループ反復の必要数を最小化し、その上、キャッシュ・ミスの回数を減らすことができます。依存関係を持つループに UNROLL_AND_FUSE を適用すると、予期しない結果が生じます。
構文
>>-+-UNROLL_AND_FUSE--+---------------------+-+---------------->< | '-(--unroll_factor--)-' | '-NOUNROLL_AND_FUSE------------------------' |
規則
ループ・アンロールを行う場合、UNROLL_AND_FUSE ディレクティブは DO ループの前になければなりません。
UNROLL_AND_FUSE ディレクティブを最も内側の DO ループに指定することはできません。
UNROLL_AND_FUSE ディレクティブを複数回指定することはできません。また、1 つの DO の構文で、このディレクティブを NOUNROLL_AND_FUSE、NOUNROLL、UNROLL、または STREAM_UNROLL ディレクティブと結合することはできません。
UNROLL_AND_FUSE ディレクティブを DO WHILE ループ および無限 DO ループに指定することはできません。
例
例 1: 次の例では、UNROLL_AND_FUSE ディレクティブがループの本体を複製してフューズします。これにより、配列 B のキャッシュ・ミスの数が減少します。
INTEGER, DIMENSION(1000, 1000) :: A, B, C !IBM* UNROLL_AND_FUSE(2) DO I = 1, 1000 DO J = 1, 1000 A(J,I) = B(I,J) * C(J,I) END DO END DO END
下の DO ループは、UNROLL_AND_FUSE ディレクティブを適用した場合の、考えられる結果を示します。
DO I = 1, 1000, 2 DO J = 1, 1000 A(J,I) = B(I,J) * C(J,I) A(J,I+1) = B(I+1, J) * C(J, I+1) END DO END DO
例 2: 以下の例では、複数の UNROLL_AND_FUSE ディレクティブを使用します。
INTEGER, DIMENSION(1000, 1000) :: A, B, C, D, H !IBM* UNROLL_AND_FUSE(4) DO I = 1, 1000 !IBM* UNROLL_AND_FUSE(2) DO J = 1, 1000 DO k = 1, 1000 A(J,I) = B(I,J) * C(J,I) + D(J,K)*H(I,K) END DO END DO END DO END
関連情報
+--------------------------------IBM 拡張の終り-------------------------------+