Comments
Description
Transcript
C言語使用手引書
C 言語使用手引書 はじめに ■本書の目的 本書は、以下に示すオペレーティングシステム上で動作する C 言語処理系 ( 以降、本処理系と呼 びます ) の使用方法を記述しています。 ・ Solaris™ オペレーティングシステム ( 以降、Solaris OS) また、本書は、以下の C 言語規格書および OpenMP 仕様を元に、本処理系で拡張した言語仕様に ついても記述しています。 ・ 日本工業規格 プログラム言語 C JIS X 3010-1993(ISO/IEC 9899: 1990) 本書では JIS 規格および、その原規格である ISO 規格および ANSI 規格を総じて、一般的な表 現として C 言語規格または ANSI 規格と呼んでいます。 また、これらの規格で定義された仕様を、C89 仕様と呼びます。 ・ Programming languages -- C(ISO/IEC 9899:1999 (E)) 本書では本 ISO 規格を、一般的な表現として C99 言語規格と呼んでいます。 また、この規格で定義された仕様を C99 仕様と呼びます。 ・ OpenMP Application Program Interface Version2.5 (May 2005) この規格で定義された仕様を OpenMP 仕様と呼びます。 ■本書の読者 本書は、C 言語規格書で規定された言語仕様を前提に記述しています。規格仕様については、C 言語規格書を参照するか、または規格準拠の市販本をお読みください。 本書は、本処理系を使用して、C プログラムを処理する人および C プログラムを作成する人を対 象に記述しています。 本書を読むにあたっては、UNIX コマンド、ファイル操作およびシェルプログラミングの基本的 な操作知識が必要です。 ■本書の構成 第 1 章 処理手続き 本処理系を使用して、C プログラムを処理する場合の手続きについて記述しています。 第 2 章 翻訳から実行まで C プログラムの翻訳から実行までの手続きについて記述しています。 第 3 章 逐次最適化機能 逐次最適化機能を使用する場合に、利用者が注意しなければならない事項について記述してい ます。 第 4 章 並列化機能 自動並列化機能や OpenMP 仕様を利用したプログラムの高速化について、利用者が注意しなけ ればならない事項について記述しています。 第 5 章 出力情報 本処理系が出力する情報について記述しています。 第 6 章 言語仕様 C 言語規格の言語仕様を元に、本処理系で拡張した言語仕様について記述しています。 付録 A 処理系定義の動作 C 言語規格で処理系定義としている項目に対する、本処理系での動作について記述しています。 付録 B 翻訳限界 本処理系における翻訳限界について記述しています。 付録 C 高速数学関数 本処理系が提供する高速数学関数について記述しています。 付録 D 制限事項および注意事項 本処理系の制限および利用する上での注意事項を記述しています。 付録 E ISO/IEC 9899:1999 サポートについて C99 規格の本処理系でのサポート状況について記述しています。 付録 F Parallelnavi Parallelnavi 固有機能について記述しています。 ■本書の読み方 本処理系を使用するにあたり、最初に「付録 D.4 環境変数の設定」をお読みください。 本処理系を使用して、C プログラムの翻訳、結合編集、実行およびデバッグを行う場合、「第 1 章 処理手続き」および「第 2 章 翻訳から実行まで」をお読みください。また、本処理系の最適 化機能を使用する場合、 「第 3 章 逐次最適化機能」をお読みください。並列化機能を使用する場 合、 「第 4 章 並列化機能」をお読みください。本処理系が出力する情報については、 「第 5 章 出 力情報」をお読みください。C 言語規格の言語仕様を元に、本処理系で拡張した言語仕様を知り たい場合、 「第 6 章 言語仕様」をお読みください。C 言語規格で処理系定義としている項目につ いて、本処理系での動作を知りたい場合、 「付録 A 処理系定義の動作」をお読みください。本処 理系における翻訳限界を知りたい場合、 「付録 B 翻訳限界」をお読みください。本処理系で用 意している高速数学関数を知りたい場合、 「付録 C 高速数学関数」をお読みください。本処理系 の制限事項および注意事項を知りたい場合、 「付録 D 制限事項および注意事項」をお読みくださ い。C99 規格の本処理系でのサポート状況について知りたい場合、「付録 E ISO/IEC 9899:1999 サポートについて」をお読みください。Parallelnavi 固有機能について知りたい場合、 「付録 F Parallelnavi」をお読みください。 ■本書の注意事項 本書では、以下の記号および用語を用いて機能を記述しています。 [ 項目 ] : その項目を省略できることを意味します。 [ 項目 1| 項目 2] : 項目 1、項目 2 のどちらかを指定できることを意味します。項目が三つ以上 指定されている場合も同様です。 { 項目 1| 項目 2} : 項目 1、項目 2 いずれか一つを文脈により選択しなければならないことを意 味します。項目が三つ以上指定されている場合も同様です。 項目・・・ : 項目を任意の個数繰り返して指定できることを意味します。 ■商標 UNIX は、米国およびその他の国におけるオープン・グループの登録商標です。 Sun、Solaris は、米国 Sun Microsystems,Inc. の商標です。 すべての SPARC 商標は、米国 SPARC International,Inc. のライセンスを受けて使用している同 社の米国およびその他の国における商標または登録商標です。 SPARC 商標が付いた製品は、米国 Sun Microsystems 社が開発したアーキテクチャに基づくもの です。 OpenMP は、OpenMP Architecture Review Board の商標です。 INFORMIX は、米国 Informix Software,Inc. の登録商標です。 他の各製品名は、各社の商標、または登録商標です。 ■引用文献 本書は、プログラム言語 C(JIS X 3010-1993: 日本規格協会発行 ) の内容を部分的に引用してい るところがあります。 ■著作権 Copyright 1995- Globetrotter Software,Inc. Copyright 1995- Software Research Associates,Inc. All Rights Reserved. All Rights Reserved, Copyright(c) 富士通株式会社 1999-2006 お願い ・ 本書を無断で転載しないようお願いします。 ・ 本書は予告なしに変更されることがあります。 目次 第 1 章 処理手続き ..................................................... 1 1.1 1.2 1.3 1.4 1.5 翻訳........................................................................... 1 結合編集....................................................................... 1 実行........................................................................... 1 デバッグ....................................................................... 1 64 ビットアドレスモードの実行可能プログラムの作成 .............................. 1 第 2 章 翻訳から実行まで ............................................... 3 2.1 翻訳コマンド................................................................... 3 2.1.1 翻訳コマンドの形式 ......................................................... 3 2.1.2 翻訳コマンドの入力ファイル ................................................. 3 2.1.3 翻訳コマンドの復帰値 ....................................................... 4 2.2 翻訳時オプション............................................................... 4 2.2.1 翻訳時オプションの形式 ..................................................... 4 2.2.2 翻訳時オプションの意味 ..................................................... 4 2.2.3 翻訳時オプションの注意事項 ................................................. 18 2.3 翻訳時プロフィルファイル....................................................... 19 2.4 実行の手続き................................................................... 20 2.4.1 実行時環境変数 ............................................................. 20 2.4.2 実行時オプションの指定方法 ................................................. 21 2.4.3 実行時の注意事項 ........................................................... 21 第 3 章 逐次最適化機能 ................................................. 23 3.1 最適化の概要................................................................... 23 3.2 標準最適化..................................................................... 23 3.2.1 共通式の除去 ............................................................... 23 3.2.2 不変式の移動 ............................................................... 24 3.2.3 演算子の強さの縮小 ......................................................... 24 3.2.4 ループ・アンローリング ..................................................... 25 3.2.5 ソフトウェア・パイプライニング ............................................. 26 3.3 拡張最適化..................................................................... 26 3.3.1 インライン展開 ............................................................. 26 3.3.2 評価方法を変更する最適化 ................................................... 26 3.3.3 ポインタの最適化 ........................................................... 28 3.3.4 クロスファイル最適化 ....................................................... 29 3.4 最適化機能の活用方法........................................................... 29 3.4.1 最適化制御行 (OCL) の利用 ................................................... 29 3.4.2 プロファイル情報の利用 ..................................................... 31 3.4.3 実行マシン属性の選択 ....................................................... 32 3.4.4 最適化機能の選択の目安 ..................................................... 32 第 4 章 並列化機能 ..................................................... 35 4.1 並列処理の概要................................................................ 35 4.1.1 並列処理とは .............................................................. 35 4.1.2 並列処理の効果 ............................................................ 35 4.1.3 並列処理で効果を得るための条件 ............................................ 36 4.1.4 本処理系の並列機能の特徴 .................................................. 36 4.2 自動並列化.................................................................... 36 4.2.1 翻訳・実行の方法 .......................................................... 36 4.2.2 並列化プログラムのチューニング ............................................ 39 4.2.3 自動並列化処理の詳細 ...................................................... 39 4.3 OpenMP 仕様による並列化 ....................................................... 54 4.3.1 翻訳・実行の方法 .......................................................... 54 4.3.2 処理系依存の仕様 .......................................................... 57 4.3.3 プログラミングの注意事項 .................................................. 58 4.3.4 他のマルチスレッドプログラムとの結合 ...................................... 59 4.3.5 OpenMP プログラムのデバッグ ............................................... 59 4.3.6 並列実行情報 .............................................................. 59 第 5 章 出力情報 ....................................................... 61 5.1 翻訳時情報..................................................................... 61 5.1.1 ヘッダ ..................................................................... 61 5.1.2 ソースリスト ............................................................... 61 5.1.3 並列化メッセージ ........................................................... 63 5.1.4 統計情報 ................................................................... 63 5.2 実行時情報..................................................................... 64 5.2.1 トレースバック情報 ......................................................... 64 5.2.2 高速数学関数のエラー ....................................................... 65 第 6 章 言語仕様 ....................................................... 69 6.1 6.2 6.3 6.4 6.5 6.6 long long 型 ................................................................... 69 pragma 指令 .................................................................... 70 ident 指令 ..................................................................... 70 assert 指令 .................................................................... 70 unassert 指令 .................................................................. 71 あらかじめ定義されたマクロ名................................................... 71 付録 A 処理系定義の動作 ............................................... 73 A.1 翻訳........................................................................... 73 A.2 環境........................................................................... 73 A.3 識別子......................................................................... 73 A.4 文字........................................................................... 73 A.5 整数........................................................................... 74 A.6 浮動小数点数................................................................... 75 A.7 配列とポインタ................................................................. 76 A.8 レジスタ....................................................................... 77 A.9 構造体、共用体、列挙型およびビットフィールド................................... 77 A.10 修飾子........................................................................ 78 A.11 宣言子........................................................................ 78 A.12 文............................................................................ 78 A.13 前処理指令.................................................................... 78 A.14 ライブラリ関数................................................................ 79 A.15 OpenMP 仕様 ................................................................... 79 付録 B 翻訳限界 ....................................................... 81 付録 C 高速数学関数 ................................................... 83 付録 D 制限事項および注意事項 ......................................... 85 D.1 制限事項....................................................................... 85 D.2 注意事項....................................................................... 85 D.2.1 可変個の引数を持つ関数の呼出し ............................................. 85 D.3 移行上の注意事項............................................................... 85 D.3.1 -O4 ........................................................................ 85 D.3.2 -Kgs および -Kpreload ....................................................... 85 D.3.3 -Kmerge および -Kxi=N ....................................................... 85 D.3.4 -p ......................................................................... 85 D.4 環境変数の設定................................................................. 85 D.4.1 コマンドの起動 ............................................................. 85 D.4.2 オンラインマニュアル ....................................................... 85 D.5 整合性......................................................................... 86 D.5.1 アプリケーションプログラムとの整合性について ............................... 86 付録 E ISO/IEC 9899:1999 サポートについて .............................. 87 E.1 サポート状況................................................................... 87 E.1.1 言語 ....................................................................... 87 E.1.2 ライブラリ ................................................................. 87 E.2 オブジェクト互換............................................................... 87 E.3 アプリケーションバイナリインタフェース......................................... 87 E.4 処理系定義の動作............................................................... 88 付録 F Parallelnavi ................................................... 89 F.1 ラージページ機能............................................................... 89 F.1.1 翻訳 ....................................................................... 89 F.1.2 実行 ....................................................................... 90 F.1.3 ラージページ機能を利用するプログラムの判定 ................................. 90 F.1.4 制約事項 ................................................................... 90 F.2 CPU 数の管理 ................................................................... 91 F.2.1 自動並列化向けスレッド数の決定 ............................................. 91 F.2.2 OpenMP 向けスレッド数の決定 ................................................ 91 F.3 スレッド間ハードウェアバリア機能............................................... 92 F.3.1 翻訳 ....................................................................... 92 F.3.2 実行 ....................................................................... 92 F.3.3 スレッド間ハードウェアバリア機能を利用するプログラムの判定 ................. 93 F.3.4 制約事項 ................................................................... 93 図目次 4.1 並列処理のイメージ................................................ 4.2 並列処理による経過時間の短縮...................................... 4.3 ループスライスのイメージ.......................................... 4.4 ループスライスができないループの例................................ 4.5 多重ループでのループ交換.......................................... 4.6 ループの分割...................................................... 4.7 ループの融合...................................................... 4.8 リダクションによる自動ループスライス.............................. 4.9 回転数が小さく、演算数が少ないループ.............................. 4.10 関数の引用を含むループ........................................... 4.11 飛び出しのあるループ............................................. 4.12 serial 指示子のないプログラム例 .................................. 4.13 serial 指示子の使用例 ............................................ 4.14 parallel 指示子のないプログラム例 ................................ 4.15 parallel 指示子の使用例 .......................................... 4.16 disjoint 指示子のないループの例 .................................. 4.17 disjoint 指示子の使用例 .......................................... 4.18 temp 指示子のないプログラム例 .................................... 4.19 temp 指示子の使用例 .............................................. 4.20 independent 指示子のないループの例 ............................... 4.21 independent 指示子の使用例 ....................................... 4.22 reduction 指示子の使用例 ......................................... 4.23 noreduction 指示子の使用例 ....................................... 4.24 並列処理が入れ子になった場合..................................... 4.25 リダクションによる精度差......................................... 5.1 ヘッダの出力形式.................................................. 5.2 並列化表示の出力例................................................ 5.3 ループ・アンローリングの出力例.................................... 5.4 並列化メッセージの出力例.......................................... 5.5 統計情報の出力形式................................................ 5.6 クロスファイル最適化の統計情報.................................... 5.7 トレースバックマップの出力形式.................................... 5.8 高速数学関数エラーにおける処置例.................................. A.1 汎整数型の表現および値............................................ A.2 浮動小数点型の表現および値........................................ 35 35 39 40 41 42 42 43 44 44 44 46 47 47 48 48 48 49 49 50 50 51 51 52 53 61 62 63 63 63 64 65 67 75 76 表目次 2.1 2.2 2.3 2.4 2.5 2.6 3.1 3.2 4.1 5.1 A.1 B.1 C.1 E.1 fcc コマンドの形式 ................................................ 入力ファイルの形式................................................ fcc コマンドが設定する復帰値 ...................................... -X オプションで定義される値 ....................................... -Kcpu との組み合わせ .............................................. 実行時環境変数.................................................... 最適化制御行と有効範囲............................................ 最適化制御行に指定できる最適化指示子.............................. 自動並列化用の最適化指示子一覧.................................... 高速数学関数のエラー処理.......................................... 算術型の大きさと境界整列値........................................ 翻訳限界.......................................................... 高速数学関数一覧.................................................. 複素数型および _Bool 型の大きさと境界整列値........................ 3 3 4 10 11 20 30 31 45 65 77 81 83 87 第 1 章 処理手続き 本章では、本処理系を利用して C プログラムを処理する場合の手続きについて説明します。 1.1 翻訳 利用者は、翻訳コマンドである fcc を使用して、C 言語で記述されたソースプログラムを翻訳し ます。翻訳時には、オブジェクトプログラムの最適化などの豊富な機能が使用できます。これら の機能は、翻訳時オプションとして fcc コマンドのオペランドに指定することにより、使用でき ます。 1.2 結合編集 翻訳コマンド fcc は、結合編集のためにリンカ(ld コマンド)を呼び出す機能を提供します。利 用者は、fcc コマンドを使用して、翻訳の過程で生成されたオブジェクトプログラムと C 言語ラ イブラリなどを結合編集させて実行可能プログラムを生成します。 1.3 実行 利用者は、fcc コマンドを使用して作成した実行可能プログラムを実行コマンドとして起動しま す。 以下に、使用例として例題プログラム sample.c を翻訳して、実行するまでの手続きを示します。 例題プログラム sample.c #include <stdio.h> int main(void) { (void)printf("Hello,world.\n"); return 0; } 翻訳と結合編集 $ fcc sample.c 実行 $ ./a.out 結果 Hello,world. 1.4 デバッグ C ソースプログラムのデバッグの方法として、プログラミング支援ツール (Parallelnavi 環境 ) あるいは fdb コマンド ( 非 Parallelnavi 環境 ) で提供されるソースレベルによるデバッグ機能 があります。この機能を使用する場合は、C ソースプログラムを fcc コマンドの -g 指定で翻訳 しておく必要があります。 なお、-g を指定した場合、-Kparallel および -Kcrossfile は無効となります。 1.5 64 ビットアドレスモードの実行可能プログラムの作成 64 ビットアドレスモードの実行可能プログラムは、-KV9 を指定することにより、作成すること ができます。 例 : 64 ビットアドレスモードの実行可能プログラムの作成方法 $ fcc -KV9 foo.c または $ fcc -KV9 -c foo.c 1 C 言語使用手引書 $ fcc -KV9 foo.o 64 ビットアドレスモードの実行可能プログラムを作成するにあたり、以下の注意事項がありま す。 ・ -KV9 より後に、以下の翻訳時オプションを指定しないでください。もし、以下に示すオプ ションのうちいずれかが指定された場合、64 ビットアドレスモードのオブジェクトプログラム は作成されません(-KV9 が無効となり、32 ビット用のオブジェクトプログラムが作成されま す)。 -Kfast, -Kfast_GP, -Kfast_GP2, -Kfast_VI ・ 64ビットアドレスモードのオブジェクトプログラムおよび実行可能プログラムは、64ビット オペレーティングシステム上だけで作成することができます。 ・ 64 ビットアドレスモードの実行可能プログラムは、64 ビットオペレーティングシステム上だ けで実行することができます。 ・ -KV9 を指定して翻訳されていないオブジェクトプログラムは、-KV9 を指定して結合編集でき ません。 2 第 2 章 翻訳から実行まで 本章では、ソースプログラムを翻訳し実行するための手続きについて説明します。 2.1 翻訳コマンド 利用者は、C89 仕様で翻訳する fcc コマンド、または C99 仕様で翻訳する c99 コマンド ( 以降、 特にことわりがない限り、単に fcc コマンドと呼びます ) を使用することにより、ソースプログ ラムの翻訳から実行可能プログラムの作成まで行うことができます。fcc コマンドは、fcc コマ ンド行に指定された各種のオペランドを解析し、必要に応じてプリプロセッサ、コンパイラ、ア センブラ (as コマンド ) およびリンカ (ld コマンド ) を呼び出します。 2.1.1 翻訳コマンドの形式 利用者は、fcc コマンドのオペランドとして、プリプロセッサ、コンパイラ、アセンブラおよび リンカに対するオプションの並びとファイル名を指定することができます。 ここで、プリプロ セッサおよびコンパイラに対するオプションを翻訳時オプションといいます。コンパイラ (fcc コマンド )、アセンブラ (as コマンド ) およびリンカ (ld コマンド ) に対するオプションについ ては、man コマンドを使用して参照することができます。「表 2.1 fcc コマンドの形式」に、fcc コマンドの形式を示します。 表 2.1 fcc コマンドの形式 コマンド名 {fcc|c99} オペランド [ □オプションの並び ] □ファイル名の並び fcc: C89 仕様 (X3.159-1989(ANSI C 規格 ) および K&R 仕様 ) にもとづいて翻訳するコマンドです。 c99: C99 仕様 (ISO/IEC 9899:1999) にもとづいて翻訳するコマンドです。 □ : 一個以上の空白が必要であることを意味します。 備考 " オプションの並び " と " ファイル名の並び " の指定順序に制約はありません。例えば、" ファ イル名の並び " の後に " オプションの並び " を指定してもかまいませんし、混在していてもかま いません。 2.1.2 翻訳コマンドの入力ファイル 「表 2.2 入力ファイルの形式」に、fcc コマンドに入力ファイルとして指定できるファイルを示 します。 表 2.2 入力ファイルの形式 ファイルの種別 ファイルのサフィックス 渡し先 C ソースファイル .c, .i プリプロセッサおよびコンパイラ アセンブラソースファイル .s アセンブラ オブジェクトファイル .o リンカ 3 C 言語使用手引書 2.1.3 翻訳コマンドの復帰値 「表 2.3 fcc コマンドが設定する復帰値」に、fcc コマンドが設定する復帰値を示します。 表 2.3 fcc コマンドが設定する復帰値 復帰値 意味 0 正常に終了しました。 1 翻訳エラーまたはリンカでエラーが発生しました。 2.2 翻訳時オプション ここでは、fcc コマンドに指定できる翻訳時オプションの形式および意味について説明します。 2.2.1 翻訳時オプションの形式 fcc コマンドのオペランドで翻訳時オプションを指定することができます。 以下に、翻訳時オプションの形式を示します。 ■コンパイラ全般に関連するオプション [ [ [ [ -# ] [ -### ] [ -A- ] [ -Aname[(tokens)]] [ -Bc ] [ -C ] [ -c ] -dc ] [ -Dname[=tokens] ] [ -E ] [ -G ] [ -g ] [ -H ] [ -Idir ] -Ldir ] [ -lname ] [ -mt ] [ -opathname ] [ -P ] [ -Qc ] [ -Rdir ] -S ] [ -Uname ] [ -Wtool,arg1[,arg2, ... ] ] [ -Yitem,dir ] ■メッセージ関連オプション [ -V ] [ -w ] ■最適化関連オプション [ -Kopt ] [ -O[n] ] [ -x- ] [ -xfunc1[,func2, ... ] ] [ -xn ] ■言語仕様関連オプション [ -Xc ] 2.2.2 翻訳時オプションの意味 以下に、翻訳時オプションの意味を示します。 fcc( コンパイラドライバ ) が識別不可能なオプションは、リンカに渡されます。 2.2.2.1 コンパイラ全般に関連するオプション ここでは、翻訳で使用される一般的なオプションについて説明します。 -# fcc によって実行されるコマンドを表示します。ただし、プログラムの翻訳処理は行いません。 -### fcc によって実行されるコマンドを表示します。 -Aあらかじめ定義されたマクロ (_ _ で始まるものは除く ) と、あらかじめ定義されたアサーショ ンをすべて無効にします。 -Aname[(tokens)] #assert 前処理指令の機能と同様、name を述語とし、指定された tokens と関連づけます。 あらかじめ定義されたアサーションを、以下に示します。 ・ system(unix) ・ cpu(sparc) 4 第 2 章 翻訳から実行まで ・ machine(sparc) -Bc c には、dynamic または static を指定します。-lx の指定に対して、-Bdynamic を指定した場 合、リンカは最初に libx.so という名前のファイルを探し、次に libx.a という名前のファイ ルを探します。-Bstatic を指定した場合、リンカは libx.a だけを探します。 コマンド行では、各 -lx オプションの指定に対して、本オプションを別々に切り替えて指定す ることができます。 本オプションは、リンカに渡されます。 -C 前処理の段階で通常削除される注釈を、前処理指令の行にあるもの以外、この段階では削除され ないようにします。 本オプションが指定された場合、-Xt が有効とみなされます。 c99 コマンドに指定された場合、無効となります。 -c 翻訳処理の最後の段階である結合編集を行わないようにします。 それまでに作成されたオブジェクトファイルが削除されるようなことはありません。 -dc c には、y または n を指定します。-dy は、リンカに対してダイナミックリンクを指示します。 -dn は、リンカに対してスタティックリンクを指示します。省略時は、-dy が適用されます。 本オプションは、リンカに渡されます。 -Dname[=tokens] name を、#define 前処理指令のように、指定された tokens と関連づけます。=tokens が省略さ れた場合、1 が与えられます。 あらかじめ定義されたマクロ名を、以下に示します。これらの値については、「2.2.2.4 言語仕 様関連オプション」をお読みください。 ・ _ _ STDC_ _ ・ _ _ STDC_HOSTED_ _ (c99 コマンドの場合 ) ・ _ _ STDC_VERSION_ _ ・ _ _ unix ・ _ _ sparc ・ _ _ sparcv9 (-KV9 が有効な場合 ) ・ _ _ sun ・ _ _ BUILTIN_VA_ARG_INCR ・ _ _ PRAGMA_REDEFINE_EXTNAME ・ _ _ SVR4 ・ _ _ `uname -s`_`uname -r` ・ _OPENMP (-KOMP が有効な場合 ) ・ unix ・ sparc ・ sun -E 指定された C ソースファイルについて前処理だけを実行し、結果を標準出力に出力します。 出力は、処理系の次の過程で使用される前処理命令を含みます。 -G リンカに対して、ダイナミックリンク実行形式ファイルではなく、共有オブジェクトを作成する よう指示します。 本オプションは、-dn と同時には指定できません。 本オプションは、リンカに渡されます。 -g 5 C 言語使用手引書 fdb の使用に必要な追加情報を生成します。-g と -O を同時に指定した場合、ローカルな識別子 については表示できません。また、最適化によって式の移動が行われる可能性があるため、正し い行番号が表示されない場合があります。 本オプションと同時に -O4 または -O5 を指定した場合、-O3 が指定されたものとみなします。 本オプションと同時に -Kparallel または -Kcrossfile を指定した場合、-Kparallel または -Kcrossfile が無効となります。 -H 現在の翻訳中にインクルードされている各ファイルのパス名を、1 行ごとに標準エラー出力に出 力します。 -Idir 名前が / 以外で始まるインクルードファイルの検索を、dir で指定されたディレクトリを先に検 索して、その後、通常のディレクトリを検索するように変更します。複数の -I オプションでディ レクトリが複数指定された場合、指定された順に検索します。 二重引用符 (") で囲まれたファイルは、以下の順に検索します。 1. #include 前処理指令を含む現ディレクトリ 2. -I オプションで指定されたディレクトリ 3. 標準のディレクトリ 角括弧 (<>) で囲まれたファイルは、以下の順に検索します。 1. -I オプションで指定されたディレクトリ 2. 標準のディレクトリ インクルードファイルが絶対パス名で指定された場合、指定された絶対パス名だけ検索します。 ディレクトリが存在しない場合、本オプションは無効となります。 -Ldir リンカがライブラリを検索するディレクトリのリストに、dir を加えます。 本オプションは、リンカに渡されます。 -lname libname.so または libname.a という名前のオブジェクトライブラリをリンクします。 シンボルは指定された順序にライブラリで解決されるため、コマンド行でのライブラリの指定順 序が重要になります。本オプションは、ソースファイル名の後に指定してください。 本オプションは、リンカに渡されます。 -mt スレッドセーフオブジェクトを生成します。 ファイル名の並びに-mtを指定して翻訳されたオブジェクトプログラムが含まれているのであれ ば、-mt を指定する必要があります。 ユーザ固有のマルチスレッドプログラムの場合、-mt を指定する必要があります。 -opathname pathname で指定された名前のファイルを作成します。 -c を同時に指定した場合、pathname の名前でオブジェクトファイルが作成されます。 -G を同時に指定した場合、pathname の名前で共有オブジェクトファイルが作成されます。 その他の場合、省略時設定の a.out の代わりに、pathname の名前で実行可能プログラムが作成 されます。 -P 指定された C ソースファイルに対して前処理だけを実行し、結果をサフィックス .i の付いたファ イルに格納します。出力は前処理指令を含みません。 -Qc c には、y または n を指定します。-Qy の場合、 呼び出された各翻訳ツールについての識別情 報が、出力ファイルに追加されます。-Qn の場合、この情報を出力しません。省略時は、-Qy が 適用されます。 6 第 2 章 翻訳から実行まで -Rdir 実行時に検索するライブラリのディレクトリリストに、dir を加えます。 -S 指定された C ソースファイルを翻訳し、アセンブラ言語出力を、サフィックス .s の付いた対応 するファイルに残します。 -Uname #undef 前処理命令と同様に、name の定義を無効にします。 -D オプションと -U オプションに同一の name を指定した場合、その順序によらず、name は定義 されません。 -Wtool,arg1[,arg2, ...] 指定された arg1[,arg2,...] をそれぞれ別の引数として tool に渡します。各引数は、直前の引 数とコンマだけで区切られていなければなりません。 tool には、以下のいずれかの文字を指定します。 p: プリプロセッサ 0: コンパイラ a: アセンブラ l: リンカ -Yitem,dir 新しいディレクトリ dir を item の位置として指定します。 item には、以下のいずれかの文字を指定します。 p: プリプロセッサのパス名を dir/isocpp に変更します。 0: コンパイラのパス名を dir/ccom に変更します。 a: アセンブラのパス名を dir/as に変更します。 l: リンカのパス名を dir/ld に変更します。 I: 標準インクルードファイル ( 通常 /usr/include) を検索するディレクトリを dir に変更し ます。 P: 結合するライブラリのディレクトリを dir に変更します。dir には、コロンで区切ったパス リストを指定します。 S: 結合するスタートアップオブジェクトファイルのディレクトリを dir に変更します。 M: メッセージファイルのディレクトリを dir に指定します。 一つの item に対して複数の -Y オプションが指定された場合、最後の指定が有効になります。 2.2.2.2 メッセージ関連オプション ここでは、メッセージに関するオプションについて説明します。 -V 起動された各ツールについて、そのバージョン情報を標準エラー出力に出力します。 -w 警告メッセージの出力を抑止します。 2.2.2.3 最適化関連オプション ここでは、最適化機能を使用する際に指定するオプションについて説明します。 -K opt opt には、以下のいずれかを指定します。 a{1|2|4|8}, adr{44|64}, archi, {bcopy|nobcopy}, {cfunc|nocfunc}, {const|noconst}, cpu, {crossfile|nocrossfile}, {dalign|nodalign}, eopt, {eval|noeval}, {FMADD|NOFMADD}, fast, fast_GP[={0|1|2}], fast_GP2[={0|1|2|3}], fast_VI[={0|1|2|3}], {fconst|nofconst}, funcalign=N, {fuse|nofuse}, GREG, {GREG_APPLI|NOGREG_APPLI}, {GREG_SYSTEM|NOGREG_SYSTEM}, {hardbarrier|nohardbarrier}, {ilfunc|noilfunc}, instance=N, {iopt|noiopt}, 7 C 言語使用手引書 {largepage[={1|2}]|nolargepage}, {lib|nolib}, {line|noline}, loopiteration_max=N, looptype={f|n|s}, {memalias|nomemalias}, {mfunc|nomfunc}, {misalign|nomisalign}, NOFLTLD, {ns|nons}, {OMP|NOOMP}, {ocl|noocl}, {PIC|pic}, pagesize=N, pagesize_heap=N, pagesize_stack=N, {parallel|noparallel}, pg, pmsg, {popt|nopopt}, {preex|nopreex}, {prefetch[={1|2|3|4}]|noprefetch}, pu, {rdconv|nordconv}, {reduction|noreduction}, {restp|norestp}, SSL2, src, sta, staticlib, {unroll[=N]|nounroll}, {use_rodata|nouse_rodata}, {VIS1|VIS2|NOVIS} -K オプションは、複数の引数の指定を受け付けます。 例えば、-Klib -Kpopt の代わりに、-Klib,popt のように指定することができます。 なお、-K オプションの詳細は、「2.2.2.5 -K オプション」をお読みください。 -O[n] n には、最適化レベル 0、1、2、3、4 または 5 を指定します。最適化レベルが指定されていない 場合、-O3 が適用されます。最適化レベルが高いほど、実行時間が短縮されますが、翻訳時間は 増加します。高位の最適化レベルは、低位の最適化レベルを機能的に包含します。 本オプションは、.s ファイルには無効です。 最適化レベル 0 最適化されません。-O を指定しない場合と等価です。 最適化レベル 1 プログラムの流れを詳細に解析して最適化が行われます。 最適化レベル 2 最適化レベル 1 に加えて、以下の最適化が行われます。 ・ ループアンローリング オブジェクトプログラムサイズが増加する場合があります。 最適化レベル 3 最適化レベル 2 に加えて、以下の最適化が行われます。 ・ 最適化機能の繰返し実施 最適化機能の繰返し実施は、最適化レベル 1 で行われる最適化機能を、最適化の余地がなくなる まで繰り返して実施します。 最適化レベル 4 最適化レベル 3 に加えて、以下の最適化が行われます。 ・ ループ交換促進のためのループ分割 ・ -KGREG_APPLI 指定時の最適化 最適化レベル 5 最適化レベル 4 に加えて、以下の最適化が行われます。 ・ ソフトウェア・パイプライニング ・ 高度なレジスタ割当て -xソースプログラム上で定義されたすべての関数に対して、関数呼出しの代わりに、インライン 展開を行います。ただし、マクロ展開後の初期化のある宣言と実行文の数がインライン展開の 許容値 (m) を超える関数および再帰的に呼び出される関数については、インライン展開の対象 にはなりません。m の値はコンパイラが適切な値を決定します。 本オプションは、-O と同時に指定した場合に有効となります。 本オプションは、-Kcrossfile と同時に指定した場合、無効となります。 本オプションと -xn を同時に指定した場合、後に指定した方が有効となります。 -xfunc1[,func2, ....] ソースプログラム上で定義された関数 func1[,func2, ...] に対して、関数呼出しのインライン 展開を行います。ただし、再帰的に呼び出される関数についてはインライン展開の対象にはなり ません。 本オプションは、-O と同時に指定した場合に有効となります。 8 第 2 章 翻訳から実行まで 本オプションは、-Kcrossfile と同時に指定した場合、無効となります。 -xn 関数内の初期化のある宣言と、実行文の数が n で指定された数以下の関数に対して、インライン 展開を行います。ただし、再帰的に呼び出される関数については、インライン展開の対象にはな りません。n には、0 から 2147483647 の整数値を指定します。n が 0 のときは、インライン展開 を行いません。 本オプションと -x- を同時に指定した場合、後に指定した方が有効となります。 -x0 が指定された場合、-x-、-xn および -xfunc1[,func2,...] は無効となり、インライン展開を 行いません。 本オプションは、-O と同時に指定した場合に有効となります。 本オプションは、-Kcrossfile と同時に指定した場合、無効となります。 2.2.2.4 言語仕様関連オプション ここでは、言語仕様に関係するオプションについて説明します。 -Xc コンパイラ ( プリプロセッサを含む ) が解釈する言語仕様のレベルを指定します。 c には、以下のいずれかの文字を指定します。省略時は、-Xa が適用されます。 複数の -X オプションを指定した場合、最後に指定されたものが有効になります。 ■ fcc の場合 a(ANSI モード ) 翻訳の際に使用される C 言語の仕様が、C 言語規格 (ANSI 規格 ) の新しい仕様をすべて含むも のになります。省略時はこのモードになります。 新・旧の言語仕様によって動作が異なるプログラム構造の解釈は、C 言語規格の仕様になりま す。例えば、整数拡張の規則の変更に関係する警告メッセージは出力しますが、3 文字表記 ( トライグラフシーケンス)や追加されたエスケープシーケンスに関係する警告メッセージは出 力しません。 c(ANSI 準拠モード ) 翻訳の際に使用される C 言語の仕様と関連するヘッダが、より厳密に C 言語規格 (ANSI 規格 ) に準拠のものになります。 しかし、C 言語規格に厳密に準拠するプログラムに影響を与えない -Xa 指定での拡張仕様は含 んでおり、これらのいくつかについて警告メッセージを出力します。標準ヘッダ中の識別子に ついては、C 言語規格で定義されている識別子だけが可視になります。 t( 移行モード ) 翻訳の際に使用される C 言語の仕様が、(ANSI 規格以前の ) 従来仕様に互換性のある C 言語規 格 (ANSI 規格 ) 仕様を追加したものになります。 コンパイラ ( プリプロセッサを含む ) は、新・旧の言語仕様によって動作が異なるプログラム 構造に対して警告メッセージを出力し、旧仕様として解釈します。例えば、3 文字表記 ( トラ イグラフシーケンス ) や、\a などの新しいエスケープシーケンスに対するものや、整数拡張 の規則の変更に関係するものに対して警告メッセージを出力します。 ■ c99 の場合 a(ISO/IEC9899:1999 モード ) 翻訳の際に使用される C 言語の仕様は、C 言語規格 (ISO/IEC9899:1999 規格 ) に基づいたもの になります。 c(ISO/IEC9899:1999 モード ) 翻訳の際に使用される C 言語の仕様は、C 言語規格 (ISO/IEC9899:1999 規格 ) に基づいたもの になります。C 言語規格で定義されている識別子だけが可視になります。処理系独自仕様は機 能しなくなります。 9 C 言語使用手引書 「表 2.4 -X オプションで定義される値」に、-X オプションで定義される値を示します。 表 2.4 -X オプションで定義される値 識別子 -Xa -Xc -Xt _ _ STDC_ _ 0 1 0 _ _ unix 1 1 1 _ _ sparc 1 1 1 _ _ sparcv9(-KV9 有効時 ) 1 1 1 _ _ sun 1 1 1 _ _ BUILTIN_VA_ARG_INCR 1 1 1 _ _ PRAGMA_REDEFINE_EXTNAME 1 1 1 _ _ SVR4 1 1 1 _ _ `uname -s`_`uname -r` 1 1 1 200505 200505 200505 unix 1 - 1 sparc 1 - 1 sun 1 - 1 _ _ STDC_VERSION_ _ (fccのみ) 199409L 199409L - _ _ STDC_VERSION_ _ (c99のみ) 199901L 199901L - _ _ STDC_HOSTED_ _ (c99 のみ ) 1 1 - _OPENMP(-KOMP 有効時 ) 2.2.2.5 -K オプション -Ka{1|2|4|8} 外部変数および静的変数の最低の割り付け境界を指定します。例えば、-Ka4 を指定すると、1 ~ 4 バイト境界のデータを 4 バイト境界に割り付けます。省略時は、-Ka1 が適用されます。 -Kadr{44|64} 絶対アドレスを 44 ビットで表すオブジェクトプログラムを生成するか、それとも 64 ビットで表 すオブジェクトプログラムを生成するかを指示します。-Kadr44 が指定された場合、44 ビットで 表すオブジェクトプログラムを生成します。-Kadr64 が指定された場合、64 ビットで表すオブ ジェクトプログラムを生成します。 -Kadr44 および -Kadr64 は、-KV9 と同時に、かつ -KV9 より後に指定した場合に有効となります。 -Karchi archi には、以下のいずれかを指定します。詳細は、-Kcpu オプションをお読みください。 V8 SPARCV8 の命令セットを使用することを指示します。 V8PFMADD SPARCV8+ の命令セットおよび multiply add/subtract 命令を使用することを指示します。 -KV8PFMADD は、-KV8PLUS および -KFMADD を同時に指定した場合と等価です。 V8PLUS SPARCV8+ の命令セットを使用することを指示します。 ファイル名の並びに -KV8PLUS を指定して翻訳されたオブジェクトプログラムが含まれているの であれば、-KV8PLUS を指定する必要があります。 10 第 2 章 翻訳から実行まで V9 SPARCV9 の命令セットを使用することを指示します。 本オプションを指定した場合、-Kadr44 が指定されたものとみなします。 ファイル名の並びに -KV9 を指定して翻訳されたオブジェクトプログラムが含まれているのであ れば、-KV9 を指定する必要があります。 V9FMADD SPARCV9 の命令セットおよび multiply add/subtract 命令を使用することを指示します。 -KV9FMADD は、-KV9 および -KFMADD を同時に指定した場合と等価です。 -K{bcopy|nobcopy} メモリ転送のループを、memmove または memcpy 関数に変更するか否かを指示します。-Kbcopy が 指定された場合、変更します。省略時は、-Knobcopy が適用されます。 -Kbcopy は、-O と同時に指定した場合に有効となります。 c99 コマンドに指定された場合、無効となります。 -K{cfunc|nocfunc} 本処理系で用意している高速数学関数、ライブラリ関数 (malloc,calloc,realloc,free) および 高速文字関数 (memcpy,memset) を利用するか否かを指示します。-Kcfunc が指定された場合、利 用します。ただし、高速文字関数は、-KV8PLUS または -KV9 を同時に指定した場合に利用します。 省略時は、-Knocfunc が適用されます。 -Kcfunc は、-Kmfunc を機能的に包含しています。-Kcfunc と同時に -Kmfunc が指定された場合、 -Kcfunc が有効となります。 -Knocfunc または -Knomfunc が指定された場合、-Kcfunc および -Kmfunc が無効となります。 -Kcfunc は、-mt、-KOMP または -Kparallel と同時に指定した場合、無効となります。 -K{const|noconst} const 型修飾子が指定されたデータを、定数として取り扱うか否かを指示します。-Kconst が指 定された場合、定数として取り扱います。省略時は、-Kconst が適用されます。 c99 コマンドに指定された場合、無効となります。 -Kcpu cpu には、以下のいずれかを指定します。 SPARC64_GP SPARC64 GP に特有な最適化を行います。 SPARC64_GP2 SPARC64 V に特有な最適化を行います。 SPARC64VI SPARC64 VI に特有な最適化を行います。 ULTRA -KULTRA1 が指定されたものとみなします。 ULTRA1 UltraSPARC-1 に特有な最適化を行います。 ULTRA2 UltraSPARC-2 に特有な最適化を行います。 「表 2.5 -Kcpu との組み合わせ」に、-Kcpu と -Karchi の指定可能な組み合わせを示します。 表 2.5 -Kcpu との組み合わせ cpu/archi V8 V8PLUS V8PFMADD V9 SPARC64_GP ○ ○ ○ ○ ○ SPARC64_GP2 ○ ○ ○ ○ ○ SPARC64VI ○ ○ ○ ○ ○ ULTRA1 ○ ○ - ○ - V9FMADD 11 C 言語使用手引書 表 2.5 -Kcpu との組み合わせ cpu/archi ULTRA2 V8 V8PLUS V8PFMADD V9 ○ ○ - ○ V9FMADD - -K{crossfile|nocrossfile} クロスファイル最適化を行うか否かを指示します。-Kcrossfile が指定された場合、最適化を行 います。省略時は、-Knocrossfile が適用されます。 -Kcrossfile は、-O と同時に指定した場合に有効となります。 -Kcrossfile を指定した場合、-Kiopt が指定されたものとみなします。 -Kcrossfile は、-g、-KOMP または -Kparallel と同時に指定された場合、無効となります。 -Kcrossfile と -x 関連オプションまたは -Kmisalign を同時に指定した場合、-x 関連オプショ ンまたは -Kmisalign は無効となります。 本機能は、Parallelnavi 固有機能です。 なお、-Kcrossfile を使用する際は、「3.3.4 クロスファイル最適化」をお読みください。 -K{dalign|nodalign} ポインタにより参照される double 型および long double 型のデータが、8 バイト境界にあるも のとして命令を生成するか否かを指示します。-Kdalign が指定された場合、生成します。省略 時は、-Knodalign が適用されます。 -Kdalign を -Kmisalign と同時に指定した場合、後に指定した方が有効になります。 -Keopt 演算の評価方法を変更する最適化および不変式の先行評価の最適化を行うことを指示します。 本オプションを指定した場合、実行結果に副作用 ( 精度誤差および実行時の例外発生など ) が生 じることがありますので、利用者の意図した結果にならない場合があります。 本オプションは、-Keval および -Kpreex を指定したものと等価です。 本オプションは、-O と同時に指定した場合に有効となります。 -K{eval|noeval} 演算の評価方法を変更する最適化を行うか否かを指示します。-Keval が指定された場合、最適 化を行います。省略時は、-Knoeval が適用されます。 -Keval を指定した場合、実行結果に副作用 ( 精度誤差および実行時の例外発生など ) が生じる ことがありますので、利用者の意図した結果にならない場合があります。 -Keval は、-O と同時に指定した場合に有効となります。 -Kparallel が同時に指定されている場合、-Kreduction も有効となります。 -Knoeval が指定された場合、-Kreduction も無効となります。 -K{FMADD|NOFMADD} multiply add/subtract 命令を生成するか否かを指示します。-KFMADD が指定された場合、生成 します。省略時は、-KNOFMADD が適用されます。 -KFMADD を指定した場合、精度が変わる場合がありますので注意が必要です。 -KFMADD は、-O と -KV8PLUS または -KV9 を同時に指定した場合に有効となります。 ファイル名の並びに-KFMADDを指定して翻訳されたオブジェクトプログラムが含まれているので あれば、-KFMADD を指定する必要があります。 -KFMADD を指定して作成された実行形式プログラムは、SPARC64 GP、SPARC64 V および SPARC64 VI 以外の機種での動作を保証しません。 -Kfast 翻訳しているマシン上で、高速に実行させることを指示します。 本オプションは、-O3 -Kdalign,lib,{VIS1|VIS2} -x- および -Kcpu と -Karchi のそれぞれの中 から翻訳しているマシンに合わせた最適なオプションを自動的に選択したものと等価です。 -Kfast_GP[={0|1|2}] SPARC64 GP アーキテクチャ用の最適化レベルを指定します。 -Kfast_GP を指定した場合、-Kfast_GP=1 が適用されます。 -Kfast_GP=0 12 第 2 章 翻訳から実行まで -O5 -Kdalign,lib,SPARC64_GP,V8PLUS,VIS1 -x- を指定した場合と同様の最適化を実施します。 -Kfast_GP=1 -O5 -Kdalign,lib,SPARC64_GP,V8PLUS,VIS1,FMADD -x- を指定した場合と同様の最適化を実施し ます。 -Kfast_GP=2 -O5 -Kdalign,lib,SPARC64_GP,V8PLUS,VIS1,FMADD,eval -x- を指定した場合と同様の最適化を 実施します。 -Kfast_GP2[={0|1|2|3}] SPARC64 V アーキテクチャ用の最適化レベルを指定します。 -Kfast_GP2 を指定した場合、-Kfast_GP2=1 が適用されます。 -Kfast_GP2=3 は、Parallelnavi 固有機能です。 -Kfast_GP2=0 -O5 -Kdalign,lib,SPARC64_GP2,V8PLUS,VIS1 -x- を指定した場合と同様の最適化を実施します。 -Kfast_GP2=1 -O5 -Kdalign,lib,SPARC64_GP2,V8PLUS,VIS1 -x- を指定した場合と同様の最適化を実施します。 -Kfast_GP2=2 -O5 -Kdalign,lib,SPARC64_GP2,V8PLUS,VIS1,eval -x- を指定した場合と同様の最適化を実施し ます。 -Kfast_GP2=3 -O5 -Kdalign,lib,SPARC64_GP2,V8PLUS,VIS1,crossfile を指定した場合と同様の最適化を実施 します。 ただし、-g、-KOMP または -Kparallel が同時に指定されている場合、-Kcrossfile が無効となり ます。 -Kfast_VI[={0|1|2|3}] SPARC64 VI アーキテクチャ用の最適化レベルを指定します。 -Kfast_VI を指定した場合、-Kfast_VI=1 が適用されます。 -Kfast_VI=0 -O5 -Kdalign,lib,SPARC64VI,V8PLUS,VIS2 -x- を指定した場合と同様の最適化を実施します。 -Kfast_VI=1 -O5 -Kdalign,lib,SPARC64VI,V8PLUS,VIS2,FMADD -x- を指定した場合と同様の最適化を実施し ます。 -Kfast_VI=2 -O5 -Kdalign,lib,SPARC64VI,V8PLUS,VIS2,FMADD,eval -x- を指定した場合と同様の最適化を実 施します。 -Kfast_VI=3 -O5 -Kdalign,lib,SPARC64VI,V8PLUS,VIS2,FMADD,eval,preex -x- を指定した場合と同様の最適 化を実施します。 -K{fconst|nofconst} 接尾語が指定されていない浮動小数点定数を、float型として扱うか否かを指示します。-Kfconst が指定された場合、float 型として扱います。省略時は、-Knofconst が適用されます。 -Kfuncalign=N 関数の先頭アライメントを N バイトの境界に合わせることを指示します。 N には 1 から 9999 ま での整数値のうち、2 の累乗の値を指定します。 c99 コマンドに指定された場合、無効となります。 -K{fuse|nofuse} 隣接するループを融合するか否かを指示します。-Kfuse が指定された場合、融合します。省略 時は、-Knofuse が適用されます。 -Kfuse は、-O(-O3 以上 ) と同時に指定した場合に有効となります。 -KGREG 13 C 言語使用手引書 翻訳の段階で、g2 から g6(-KV9 指定時は g2、g3、g6) のグローバル・レジスタをレジスタ割付 けの対象にする最適化を行うことを指示します。 本オプションは、-KGREG_APPLI,GREG_SYSTEM を指定した場合と等価です。 -K{GREG_APPLI|NOGREG_APPLI} 翻訳の段階で、g2 から g4(-KV9 指定時は g2、g3) のグローバル・レジスタをレジスタ割付けの 対象にする最適化を行うか否かを指示します。これらのレジスタは、アプリケーションプログラ ムに使用します。-KGREG_APPLI を指定すると、レジスタ割付けの対象にします。省略時は、 -KNOGREG_APPLI が適用されます。 -KNOGREG_APPLI は、-O4 または -O5 と同時に指定された場合、無効となります。 -K{GREG_SYSTEM|NOGREG_SYSTEM} 翻訳の段階で、g5、g6(-KV9 指定時は g6) のグローバル・レジスタをレジスタ割付けの対象にす る最適化を行うか否かを指示します。これらのレジスタは、システムで予約されたレジスタで す。-KGREG_SYSTEM を指定すると、レジスタ割付けの対象にします。省略時は、 -KNOGREG_SYSTEM が適用されます。 -KGREG_SYSTEM は、-O と同時に指定した場合に有効となります。 -KGREG_SYSTEM は、-mt、-KOMP または -Kparallel と同時に指定した場合、無効となります。 -K{hardbarrier|nohardbarrier} スレッド間ハードウェアバリア機能を使用する実行可能プログラムを作成するか否かを指示し ます。 -Khardbarrierが指定された場合、作成します。省略時は、-Knohardbarrierが適用されます。 -Khardbarrier は、-Kparallel または -KOMP と同時に指定した場合に有効となります。 本機能は、Parallelnavi 固有機能です。スレッド間ハードウェアバリア機能については、 「付録 F Parallelnavi」をお読みください。 -K{ilfunc|noilfunc} 単精度および倍精度型の数学関数 sin、cos、log10、log および exp をインライン展開するか否 かを指示します。-Kilfunc が指定された場合、インライン展開します。省略時は、-Knoilfunc が適用されます。 -Kilfunc を指定した場合、精度差が発生する場合がありますので注意が必要です。 -Kilfunc を指定した場合、-Klib が指定されたものとみなされます。 -Knoilfunc または -Knolib が指定された場合、-Kilfunc および -Klib が無効となります。 -Kilfunc は、-O および -Klib と同時に指定した場合に有効となります。 -Kinstance=N 実行時のスレッド数 N を指定します。N は、2 から 128 の整数値です。 本オプションは、-Kparallel と同時に指定した場合に有効となります。 -K{iopt|noiopt} 関数間の最適化を行うか否かを指示します。-Kiopt が指定された場合、最適化を行います。省 略時は、-Knoiopt が適用されます。 -Kiopt を指定した場合、翻訳時間が長くなったり、翻訳時に使用する一時領域が増大したりす る可能性があります。また、標準ライブラリ関数と同じ名前の利用者定義関数が呼び出されてい る場合、正しく動作しない場合があります。 -Kiopt は、-Kcrossfile と同時に指定した場合に有効となります。 本機能は、Parallelnavi 固有機能です。 -K{largepage[={1|2}]|nolargepage} ラージページ機能を使用する実行可能プログラムを作成するか否かを指示します。-Klargepage が指定された場合、作成します。省略時は、-Knolargepage が適用されます。 -Klargepage だけが指定された場合、-Klargepage=1 が適用されます。 本機能は、Parallelnavi 固有機能です。ラージページ機能については、「付録 F Parallelnavi」 をお読みください。 -Klargepage=1 データ域およびヒープ域に対してラージページ機能を適用します。 -Klargepage=2 データ域およびヒープ域に加えて、スタック領域に対してもラージページ機能を適用します。 14 第 2 章 翻訳から実行まで -K{lib|nolib} 標準関数の動作を認識して、標準関数のインライン展開および同じ動作をするより高速な標準関 数に置き換える最適化を行うか否かを指示します。-Klib が指定された場合、最適化を行います。 省略時は、-Knolib が適用されます。 標準関数と同名の利用者が定義した関数を使用している場合、-Klib を指定すると利用者の意図 した結果にならない場合があります。 -Klib は、-O と同時に指定した場合に有効となります。 -K{line|noline} プログラミング支援ツール (Parallelnavi 環境 )、あるいは並列アナライザ ( 非 Parallelnavi 環境 ) で提供される実行時間のサンプリング機能に必要な追加情報を生成するか否かを指示し ます。-Kline が指定された場合、生成します。省略時は、-Knoline が適用されます。 c99 コマンドに指定された場合、無効となります。 -Kloopiteration_max=N ループの繰り返し回数の最大値 N を指定します。N は、1 から 2147483647 の整数値です。 本オプションは、-Kparallel と同時に指定した場合に有効となります。 -Klooptype={f|n|s} ループの継続条件および方向を指定します。省略時は、-Klooptype=f が適用されます。 -Klooptype=f 継続条件が常に真となるループはないが、逆向きループが含まれる可能性があることを指示しま す。 -Klooptype=n 継続条件が常に真となるループおよび逆向きループが含まれる可能性があることを指示します。 -Klooptype=s 継続条件が常に真となるループおよび逆向きループがないことを指示します。 -K{memalias|nomemalias} ポインタからの間接参照を行う場合に、型が異なるときはエイリアスがないとみなすか否かを指 示します。-Kmemalias が指定された場合、エイリアスがないとみなします。省略時は、 -Knomemalias が適用されます。 -Kmemalias は、-O と同時に指定した場合に有効となります。 c99 コマンドに指定された場合、無効となります。 -K{mfunc|nomfunc} 本処理系で用意している高速な数学関数を利用するか否かを指示します。-Kmfunc が指定された 場合、利用します。省略時は、-Knomfunc が適用されます。 -K{misalign|nomisalign} ポインタにより参照されるデータが、どのような境界の領域に割り付けられているか不明なもの として、命令を生成するか否かを指示します。-Kmisalign が指定された場合、命令を生成しま す。省略時は、-Knomisalign が適用されます。 -Kmisalign を -Kdalign と同時に指定した場合、後に指定した方が有効となります。 -Kmisalign は、-O(-O5 を除く ) と同時に指定した場合に有効となります。 -Kmisalign は、-O5、-Kcrossfile、-Kfast_GP、-Kfast_GP2 または -Kfast_VI と同時に指定した 場合、無効となります。 -KNOFLTLD non-faulting load を生成することを指示します。non-faulting load は与えられたアドレスが 不当なものであっても例外を発生しません。この命令を利用することで、メモリへのアクセス を、そのアドレスが正当なものかどうかを判定する前に実行することができます。 本オプションは、-O と -KV8PLUS または -KV9 を同時に指定した場合に有効となります。 -K{ns|nons} FPU を non-standard floating point mode で初期化するか否かを指示します。-Kns が指定され た場合、初期化します。省略時は、-Knons が適用されます。 15 C 言語使用手引書 -Kns を指定した場合、高速な性能を得るために、アンダフローの数値をゼロにすることがあり ます。 -Kns は、-O と同時に指定した場合に有効となります。 -K{OMP|NOOMP} OpenMP 仕様を受け入れるか否かを指示します。-KOMP が指定された場合、受け入れます。省略時 は、-KNOOMP が適用されます。 -KOMP が指定された場合、-mt が指定されたものとみなされます。 ファイル名の並びに-KOMPを指定して翻訳されたオブジェクトプログラムが含まれているのであ れば、-KOMP を指定する必要があります。 -K{ocl|noocl} 最適化制御行 (OCL) を有効にするか否かを指示します。-Kocl が指定された場合、有効にします。 省略時は、-Kocl が適用されます。 c99 コマンドに指定された場合、無効となります。 -K{PIC|pic} 位置独立コード (PIC) を生成することを指示します。 -KPIC と -Kpic を同時に指定した場合、後に指定した方が有効になります。 -Kpagesize=N 本オプションは、-Kpagesize_heap=N および -Kpagesize_stack=N を指定した場合と等価です。 -Kpagesize_heap=N ヒープ域のページサイズを設定します。N は、8K、64K、512K、4M、32M、256M、2G または 16G です。 なお、2G または 16G は、-KV9 が有効な場合に意味があります。 N には、システムがサポートしている有効なページサイズを指定してください。有効なページサ イズは、pagesize(1M) コマンドの -a オプションを使って確認することができます。有効なペー ジサイズを指定しなかった場合は、実行時に以下のメッセージが出力され、その要求は無視され ます。SIZE は、-Kpagesize_heap または -Kpagesize に指定した値です。 fjmpss runtime:The heap page size(SIZE) specified by -Kpagesize_heap or -Kpagesize cannot be used in this system. 本オプションは、-Klargepage と同時に指定できません。 本オプションは、翻訳時およびリンク時に指定する必要があります。 本オプションは、Solaris 9 以降の場合に有効です。 本オプションを指定すると、オペレーティングシステムにインストールされた MPSS(Multiple Page Size Support) 機能が、ヒープ域に任意のページサイズを割り当てます。MPSS 機能の詳細 については、Solaris マニュアルをお読みください。 -Kpagesize_stack=N スタック域のページサイズを設定します。N は、8K、64K、512K、4M、32M、256M、2G または 16G です。 なお、2G または 16G は、-KV9 が有効な場合に意味があります。 N には、システムがサポートしている有効なページサイズを指定してください。有効なページサ イズは、pagesize(1M) コマンドの -a オプションを使って確認することができます。有効なペー ジサイズを指定しなかった場合は、実行時に以下のメッセージが出力され、その要求は無視され ます。SIZE は、-Kpagesize_stack または -Kpagesize に指定した値です。 fjmpss runtime:The stack page size(SIZE) specified by -Kpagesize_stack or -Kpagesize cannot be used in this system. 本オプションは、-Klargepage と同時に指定できません。 本オプションは、翻訳時およびリンク時に指定する必要があります。 本オプションは、Solaris 9 以降の場合に有効です。 本オプションを指定すると、オペレーティングシステムにインストールされた MPSS(Multiple Page Size Support) 機能が、スタック域に任意のページサイズを割り当てます。MPSS 機能の詳 細については、Solaris マニュアルをお読みください。 -K{parallel|noparallel} 自動並列化機能を利用するか否かを指示します。-Kparallel が指定された場合、利用します。省 略時は、-Knoparallel が適用されます。 16 第 2 章 翻訳から実行まで -Kparallel を指定した場合、-O3 -mt -Klooptype=f が指定されたものとみなされます (-O0、 -O1 または -O2 を指定しても無効になります )。 -Kparallel は、-g と同時に指定した場合、無効となります。 ファイル名の並びに -Kparallel を指定して翻訳されたオブジェクトプログラムが含まれている のであれば、-Kparallel を指定する必要があります。 -Kpg 最適化を行うために、コンパイラが参照するプロファイル情報を生成するための命令列を生成す ることを指示します。 本オプションは、-O と同時に指定した場合に有効となります。 -Kpmsg 並列化の状況をメッセージとして出力することを指示します。 本オプションは、-Kparallel と同時に指定した場合に有効となります。 -K{popt|nopopt} ポインタにより参照される領域は、そのポインタでだけ参照されるものと限定解釈して、ポイン タにより指されるデータの最適化を行うか否かを指示します。-Kpopt が指定された場合、最適 化を行います。省略時は、-Knopopt が適用されます。 -Kpopt を指定し、同じ領域を複数のポインタで参照している場合、またはポインタによる参照 とポインタによらない参照が混在している場合、利用者の意図した結果にならない場合がありま す。 -Kpopt は、-O と同時に指定した場合に有効となります。 -K{preex|nopreex} 不変式の先行評価の最適化を行うか否かを指示します。-Kpreex が指定された場合、最適化を行 います。省略時は、-Knopreex が適用されます。 この最適化は、実行結果に副作用をおよぼす可能性がありますので、利用者の意図した結果にな らない場合があります。 -Kpreex は、-O と同時に指定した場合に有効となります。 -K{prefetch[={1|2|3|4}]|noprefetch} prefetch 命令を使用したオブジェクトプログラムを生成するか否かを指示します。-Kprefetch が指定された場合、生成します。省略時は、-Knoprefetch が適用されます。 -Kprefetch( レベル指定なし ) を指定した場合、-Kprefetch=2 が適用されます。 -Kprefetch は、-O と -KV8PLUS または -KV9 を同時に指定した場合に有効となります。 -Kprefetch=1 ループ内で使用される配列データに対して、ループ内に prefetch 命令を生成します。ただし、 多重ループの場合は、最内ループ内の配列データのみ対象とします。 -Kprefetch=2 -Kprefetch=1 に加えて、キャッシュのラインサイズよりも大きなストライドでアクセスされる 配列データを対象とします。 -Kprefetch=3 -Kprefetch=2 に加えて、プリフェッチするアドレスが翻訳時に確定しないループにおいて、ア ドレス計算するための命令を生成してプリフェッチすることを指示します。 -Kprefetch=4 -Kprefetch=3 に加えて、添字が複雑な場合でも連続アクセスとみなして積極的にプリフェッチ することを指示します。 -Kpu -Kpg の指定によって得たプログラム実行時のプロファイル情報を使用した最適化を行うことを 指示します。 CPU 数や最大のスレッド数は、-Kpg を指定して作成したプログラムの実行時と同じでなければな りません。 本オプションは、-O と同時に指定した場合に有効となります。 -K{rdconv|nordconv} 17 C 言語使用手引書 型変換命令をループの外に移動する最適化を行うか否かを指示します。-Krdconv が指定された 場合、最適化を行います。省略時は、-Knordconv が適用されます。 符号付き整数の加減算がオーバフローする場合、-Krdconv を指定したときと指定しないときと で結果が異なることがあります。 -Krdconv は、-O(-O3 以上 ) と同時に指定した場合に有効となります。 -K{reduction|noreduction} リダクションの最適化を行うか否かを指示します。-Kreduction が指定された場合、最適化を行 います。省略時は、-Knoreduction が適用されます。 -Kreduction は、-Kparallel と同時に指定した場合に有効となります。 リダクションの最適化の詳細は、「第 4 章 並列化機能」をお読みください。 -K{restp|norestp} ANSI C 言語規格に準拠した引数の最適化を行うか否かを指示します。-Krestp が指定された場 合、最適化を行います。省略時は、-Knorestp が適用されます。 -KSSL2 C-SSL Ⅱおよび BLAS/LAPACK を利用することを指示します。リンク時に C-SSL Ⅱライブラリが 結合されます。 -Ksrc ソースリストを出力することを指示します。 OpenMP 仕様のディレクティブによって並列化などを指示された文についての出力は、 「第 4 章 並 列化機能」をお読みください。 -Ksta 統計情報を出力することを指示します。 -Kstaticlib 本処理系が提供するライブラリを静的結合することを指示します。 本オプションは、リンク時に指定する必要があります。 -K{unroll[=N]|nounroll} ループ展開により展開するか否かを指示します。-Kunroll が指定された場合、展開します。-O0 または -O1 が有効な場合、省略時は、-Knounroll が適用されます。-O2 以上が有効な場合、省略 時は、-Kunroll が適用されます。 -Kunroll[=N] が有効な場合、ループ展開数の上限 N を指定します。N は、2 から 100 までの整数 値です。N の指定を省略した場合、コンパイラが自動的に最適な値を決定します。 -Kunroll は、-O と同時に指定した場合に有効となります。 -K{use_rodata|nouse_rodata} 文字列定数、浮動小数点定数、および auto の集成体の初期値を、書き込み禁止領域に割り付け るか否かを指示します。-Kuse_rodata が指定された場合、書き込み禁止領域に割り付けます。省 略時は、-Knouse_rodata が適用されます。 -K{VIS1|VIS2|NOVIS} VIS(Visual Instruction Set) バージョン 1.0 または 2.0 を出力するか否かを指示します。-KVIS1 が指定された場合、バージョン 1.0 を出力します。-KVIS2 が指定された場合、バージョン 2.0 を出力します。省略時は、-KNOVIS が適用されます。 -KVIS1 または -KVIS2 は、-KV8PLUS または -KV9 と同時に指定した場合に有効となります。 ファイル名の並びに -KVIS1 または -KVIS2 を指定して翻訳されたオブジェクトプログラムが含ま れているのであれば、-KVIS1 または -KVIS2 を指定する必要があります。 2.2.3 翻訳時オプションの注意事項 翻訳時オプションで注意すべき点について説明します。 ■ -K オプションの複数指定 18 第 2 章 翻訳から実行まで -K オプションは、その後ろにコンマ (,) で区切って複数のオプションを続けて指定することが できます。また、複数の -K オプションに分けて指定することもできます。 以下の例では、二つのコマンドは同じオプションが指定されたものとみなします。 例) fcc -o pgm.out -Kunroll -Kpreex -Keval pgm.c fcc -o pgm.out -Kunroll,preex,eval pgm.c ■空白の禁止 -K オプションに続いて指定するオプションには、空白を含むことはできません。 以下の例では、"unroll" の前に空白があるため、"unroll" は無効となります。 例) 誤った指定 : fcc -O -Kpreex, unroll pgm.c 正しい指定 : fcc -O -Kpreex,unroll pgm.c ■ c99 コマンドでは無効なオプション 以下のオプションは、c99 コマンドに指定された場合、無効となります。 -C, -K{bcopy|nobcopy}, -K{const|noconst}, -Kfuncalign=N, -K{line|noline}, -K{memalias|nomemalias}, -K{ocl|noocl}, -Xt ■ 64 ビットで動作する実行可能プログラム 翻訳時オプション -KV9 を指定することにより、64 ビットで動作する実行可能プログラムを作成 することができます。以下の注意が必要です。 ・ -KV9 を指定して翻訳したオブジェクトプログラムは、-KV9 を指定して結合編集してくださ い。また、-KV9 を指定して翻訳されていないオブジェクトプログラムは、-KV9 を指定して結 合編集できません。 ・ Solaris 8 OS 以降で翻訳および結合編集ができます。 ・ 64 ビット Solaris OS 上だけで実行することができます。 例 ) 64 ビットで動作する実行可能プログラムの作成例 $ fcc a.c -KV9 または、 $ fcc a.c -KV9 -c $ fcc a.o -KV9 ■ -Karchi または -Kcpu -Kfast、-Kfast_GP、-Kfast_GP2 または -Kfast_VI より前に -Karchi -Kcpu オプションを指定し た場合、指定した -Karchi -Kcpu が無効となります。(-Kfast、-Kfast_GP、-Kfast_GP2 または -Kfast_VI から導かれる -Karchi -Kcpu が有効となります ) -Karchi -Kcpu は、-Kfast、-Kfast_GP、-Kfast_GP2 または -Kfast_VI の後に指定してください。 ■ -dn または -Bstatic -dn または -Bstatic と同時に、-KV9、-KOMP、-Kparallel、-Klargepage、-Khardbarrier または -mt を指定することはできません。 Solaris 10 OS のシステムでは、-dn または -Bstatic を指定することはできません。 スタティックライブラリが提供されていないため、リンク時にエラーとなります。 ■ 2G バイトを超えるファイルの利用 32ビットアドレスモードの実行可能プログラムで2Gバイトを超えるファイルを使用したい場合、 以下の翻訳時オプションを指定してください。 -D_FILE_OFFSET_BITS=64 2.3 翻訳時プロフィルファイル 翻訳時プロフィルファイルを設定することにより、翻訳時オプションのデフォルトを変更するこ とができます。 C の翻訳時プロフィルファイル : /etc/opt/FSUNfcc/fcc_PROF C99 の翻訳時プロフィルファイル : /etc/opt/FSUNfcc/c99_PROF 翻訳時プロフィルファイルは、以下の形式に従って作成してください。 19 C 言語使用手引書 ・ 二重引用符 (") または一重引用符 (') で囲まれていない空白文字は、意味を持ちません。 ・ 文字列の開始および終了を表す二重引用符および一重引用符は、すべて等価です。ただし、 一連の文字列は、必ず開始を表す二重引用符および一重引用符と同一の文字または行末によっ て終了します。 ・ 文字列に含まれていない "#" から行末までは、コメントと解釈します。 以下に、翻訳時プロフィルファイルの指定例を示します。 例) #Default options -w -O 翻訳時オプションの指定の優先順位は、以下のように決定されます。 1) 翻訳コマンドのオペランド 2) 環境変数 C の環境変数 : fcc_ENV C99 の環境変数 : c99_ENV 3) プロフィルファイル 4) 標準値 2.4 実行の手続き ここでは、プログラムを実行するための手続きについて説明します。 2.4.1 実行時環境変数 実行時オプションは、環境変数に指定します。実行時環境変数は、並列化機能 (「第 4 章並列化 機能」参照 ) を使用時に有効になります。 「表 2.6 実行時環境変数」に、実行時に指定できる環 境変数を示します。 なお、 OpenMP仕様の環境変数については、 「4.3.1.2.2 OpenMP仕様の環境変数」をお読みください。 表 2.6 実行時環境変数 環境変数名 オペランド 意味 FLIB_C_MESSAGE なし 環境変数が存在する場合、ユーザプログラムの実行時に エラーが発生した場合にエラーメッセージを標準エラー 出力へ出力します。 FLIB_SPINWAIT unlimited, 並列処理を行う場合に、同期待ち処理を調節することが 0,<n>s できます。詳細は、「4.2.1.2.5 同期待ち処理」および 「4.3.1.2.1 実行時の環境変数」をお読みください。 または <n>ms FLIB_FASTOMP TRUE OpenMP による並列処理を行う場合に、高速実行時ライブ ラリを使用することができます。詳細は、 「4.3.1.2.1 実 行時の環境変数」をお読みください。 FLIB_NOHARDBARRIE R なし 本機能は、Parallelnavi 固有機能です。 詳細は、「付録 F Parallelnavi」をお読みください。 FLIB_HARDBARRIER_ MESSAGE なし 本機能は、Parallelnavi 固有機能です。 詳細は、「付録 F Parallelnavi」をお読みください。 FLIB_PARALLEL_INF O 1 または 2 並列実行情報を出力することができます。詳細は、 「4.3.6 並列実行情報」をお読みください。 MPCL trace ユーザプログラムの実行時にエラーが発生した場合にエ ラートレース情報を標準エラー出力へ出力します。 PARALLEL n 自動並列で使用されるスレッドの最大数を指定します。 n は使用可能なスレッド数で、1~ 2147483647 の整数値 です。 20 第 2 章 翻訳から実行まで 表 2.6 実行時環境変数 環境変数名 THREAD_STACK_SIZE オペランド n 意味 スレッド毎のスタック領域の大きさを K バイト単位で指 定することができます。 詳細は、「2.4.3 実行時の注意事項」をお読みください。 n は使用可能なスレッド数で、32 ビットプログラムの場 合、1~ 2147483647 の整数値、64 ビットプログラムの 場合、1 ~ 18446744073709551615 の整数値です。 2.4.2 実行時オプションの指定方法 setenv コマンドを用いて、環境変数に実行時オプションを設定します。 例) $ setenv MPCL trace $ a.out 2.4.3 実行時の注意事項 本処理系で作成されたプログラムを実行する場合の注意事項を、以下に示します。 ■実行時の変数割付け 本処理系で作成されたプログラムは、手続き内でローカルな変数およびプライベート変数をス タック領域に割り付けます。手続き内でローカルな変数およびプライベート変数に必要な領域が 巨大な場合には、スタック領域を十分な大きさに拡張する必要があります。 プロセスのスタック領域は、limit(1) コマンドで設定できます。 21 C 言語使用手引書 22 第 3 章 逐次最適化機能 本章では、逐次最適化機能の概要および有効に活用する方法について説明します。 3.1 最適化の概要 最適化の目的は、プログラムを可能な限り高速に実行できるようなオブジェクトプログラム(命 令列およびデータ域)を生成することです。最適化機能を使用することにより、プログラムの実 行時間を短縮することができます。コンパイラの最適化機能は、C ソースプログラムからオブ ジェクトプログラムを生成する過程で、以下に示すことを行います。 削除 同じ結果をもたらす文や式がある場合、無駄な部分を削除します。また、実行しても意味がない 文や式があれば、それらも削除します。 移動 繰り返し実行する部分(ループと呼ばれる)に、何回繰り返しても同じ結果になる文や式があれ ば、それらをループの外側に移動します。また、繰り返して実行しなくても最終的な結果が分か る場合は、必要な部分だけをループの中に残し、他の部分はループの外側に移動します。 変更 演算式の演算子を、計算誤差が生じない範囲で変更することがあります。また、演算の対象にな るデータも変更することがあります。たとえば、一度だけ定数が代入されて、それ以後は値が変 わらない変数の引用がある場合、その変数の引用は定数の引用に変更します。 展開 ライブラリ関数や利用者定義の関数を引用(呼び出し)している場合、可能であれば関数の本体 が引用しているところに展開します。引数や関数値の受け渡しおよび呼び出しや復帰のための命 令列が不要になるので、実行時間が短縮されます。 実行 文の実行結果や式の演算結果が翻訳時に分かる場合、文の実行や式を計算する命令列は出力せず に、翻訳時に実行または計算した結果を使用します。 その他 ハードウェアの機能・特徴(命令の種類、レジスタの種類と個数、アドレッシング方法など)を 最大限に利用して高速に実行できる命令列およびデータ域を出力します。 最適化機能を使用することによって実行時間を短縮することができます。しかし、翻訳時間と翻 訳作業域は増加します。また、最適化の内容によっては、オブジェクトプログラムの大きさが大 幅に増加したり、実行結果に副作用を及ぼす可能性がある最適化もあります注。このため、最適 化機能を使用するかどうかは、翻訳時オプションにより選択できるようになっています。 3.2 標準最適化 最適化レベル 1(-O1) から最適化レベル 5(-O5)が指定されると、標準最適化が実施されます。 標準最適化の代表的な機能について説明します。 3.2.1 共通式の除去 等しい演算結果をもたらす二つの式(共通式)が存在する場合、後の式では演算せずに前の式の 演算結果を利用します。 共通式の除去の対象となるのは、算術演算、関係演算、論理演算および一部のライブラリ関数の 引用です。 注 . 実行結果に副作用を及ぼす可能性がある最適化機能項目は、利用者が翻訳時オプション で指定しない限り実施されないので、通常の使用で副作用が発生することはありません。 23 C 言語使用手引書 以下に、共通式の除去の例を示します。 例 : 共通式の除去 t = x * y; a = t + c; ... b = t + d; a = x * y + c; ... ... b = x * y + d; [ 説明 ] 代入式の右辺の一部である x*y が共通式です。2 度目の計算を除去して最初の計算結果 t を 使用するように変更します。t はコンパイラが生成した変数です。 3.2.2 不変式の移動 ループ内で値が変化しない式(不変式)を、ループの外側に移動します。不変式の移動の対象と なるのは、算術演算、関係演算、論理演算および一部のライブラリ関数の引用です。 以下に、不変式の移動の例を示します。 例 : 不変式の移動 for(i=0; i<n; i++){ y = a[j] * 2; x = x + y * z; } y = a[j] * 2; t = y * z; for(i=0; i<n; i++){ x = x + t; } [ 説明 ] 文全体の y = a[j]*2; および式の一部の y*z をループ外に移動します。t はコンパイラが生 成した変数です。 この最適化により移動するのは、通常はループ内で必ず実行される文の一部または全体です。た だし、-Kpreex を指定した場合は、判定文などにより、ループ内で選択的に実行される文に含ま れる不変式も移動します。この最適化を、通常の不変式の移動とは区別して、不変式の先行評価 と呼びます。不変式の先行評価を実施することにより、より実行時間を短縮することができま す。しかし、移動による副作用が生じることがあるので注意が必要です。 不変式の先行評価による副作用については、「3.3.2.1 不変式の先行評価」をお読みください。 3.2.3 演算子の強さの縮小 演算子の強さとは、演算に要する実行時間の相対的な大小関係をいいます。強い演算子ほど実行 時間を多く必要とします。一般に、加算と減算の強さは同じです。乗算は加減算よりも強く、除 算は乗算よりも強くなります。また、整数型と浮動小数点型の間の型変換は、加減算よりも強く 乗算より弱くなります。演算子の強さの縮小とは、" 乗算は加減算に " というように、演算子の 強さをより弱い方向に変更することにより、実行時間を短縮する最適化のことです。 この最適化は、ループ内で値が階段状に規則的に変化する整数型の変数注 と、その変数を引用 している式を対象に、加減算への縮小を行います。 以下に、強さの縮小の例を示します。 注 . このような性質を持つ変数を誘導変数と呼びます。このため、演算子の強さの縮小は、誘 導変数の最適化とも呼びます。 24 第 3 章 逐次最適化機能 例 1: 演算子の強さの縮小(乗算から加算への縮小) ... for(i=1; i<10; i++){ ... j = k + i * 100; ... } t = 100; for(i=1; i<10; i++){ ... j = k + t; ... t = t + 100; } [ 説明 ] 誘導変数 i に対する演算 i*100 に対して最適化を行い、ループ内の演算 i*100 を加算 t = t+100 に変換します。t はコンパイラが生成した変数です。 例 2: 演算子の強さの縮小(型変換から加算への縮小) ... for(i=1; i<10; i++){ ... x = (float)i; ... } t = 1.0; for(i=1; i<10; i++){ ... x = t; ... t = t + 1.0; } [ 説明 ] 誘導変数 i に対する演算 (float)i に対して最適化を行い、整数型から浮動小数点型への型変 換を、浮動小数点型の加算 t = t+1.0 に変換します。t はコンパイラが生成した浮動小数点 型の変数です。 3.2.4 ループ・アンローリング ループ・アンローリングとは、ループ内のすべての実行文をループ内に n 重に展開し、その代わ りループの回転数を n 分の 1 に縮小する最適化です。ループ外からの飛び込みがないループに対 して行われます。 展開数 n は、ループの回転数、ループ内の実行文の数と種類、および使われているデータの型な どから、コンパイラにより最適な値が決められます。また、最適化制御行 (OCL) により、ソース プログラム上に展開数を指定することもできます。この機能については、「3.4.1 最適化制御行 (OCL) の利用」をお読みください。 回転数が縮小され、かつ、多重に展開された実行文がループ内で一体になって最適化されるの で、高速なオブジェクトプログラムが得られます。ただし、ループ内の実行文が多重に展開され るので、オブジェクトプログラムの大きさが増加します。 ループ・アンローリングは、最適化レベル 2(-O2)以上の場合に行われます。また、-Knounroll を指定することにより、抑止することができます。 以下に、ループ・アンローリングの例を示します。 例:ループ・アンローリング int i,j,k; float a[400][400],b[400][400],c[400][400]; for(i=0; i<400; i++) for(j=0; j<400; j++){ c[i][j]=0.0; for(k=0; k<400; k++) c[i][j]+=a[i][k]*b[k][j]; } 25 C 言語使用手引書 たとえば、展開数が 4 の場合、オブジェクトプログラムを生成する過程で、最も内側のループ が以下のように変形されます。 for(k=0; k<400; k+=4){ c[i][j]+=a[i][k ]*b[k ][j]; c[i][j]+=a[i][k+1]*b[k+1][j]; c[i][j]+=a[i][k+2]*b[k+2][j]; c[i][j]+=a[i][k+3]*b[k+3][j]; } 3.2.5 ソフトウェア・パイプライニング ソフトウェア・パイプライニングとは、命令レベルの並列化が可能なマシンにおいて、ループ内 の命令ができるだけ並列実行されるように命令を並び替える最適化です。 ソフトウェア・パイプライニングは、ループの任意の回転における実行文と、それ以降の回転に おける実行文を重ね合わせた命令スケジューリングを行います。 このため、ループ・アンローリングと同様、オブジェクトモジュールの大きさが増加します。 ソフトウェア・パイプライニングは、最適化レベル 5(-O5) が指定された場合に行われます。 3.3 拡張最適化 拡張最適化機能のオプションが指定されると、標準最適化に加えて、拡張最適化が実施されます。 ここでは、拡張最適化の代表的な機能について説明します。 拡張最適化の機能項目によっては、コンパイラが出力するオブジェクトプログラム(命令列およ びデータ域)の大きさが大幅に増加したり、実行結果に副作用が生じることがあるので、注意が 必要です。 3.3.1 インライン展開 インライン展開とは、関数の引用(呼び出し)がある場合に、その引用箇所に関数の本体を直接 展開する最適化です。展開することによって、引数や関数値の受け渡しおよび呼び出しと復帰の ためのオーバヘッド(レジスタの退避・復元と分岐)が削除されます。また、展開された部分が 呼び出し元と一体化されるので、他の最適化が促進されます。したがって、実行時間を大幅に短 縮することができますが、オブジェクトプログラムの大きさが増加します。 標準関数のインライン展開 標準関数の動作を認識して、標準関数のインライン展開および同じ動作をする、より高速な標準 関数への置き換えを行います。このため、標準関数と同じ名前の関数を利用者が定義している場 合は、利用者の意図した結果にならない場合があります。 標準関数のインライン展開は、-Klib オプションで制御することができます。 ソース上で定義された関数のインライン展開 C ソースプログラム上で定義されたすべての関数に対して、関数呼び出しのインライン展開を行 います。 C ソースプログラム上で定義された関数のインライン展開は、-x オプションで制御することがで きます。 3.3.2 評価方法を変更する最適化 不変式の先行評価および演算評価方法の変更による最適化について説明します。 3.3.2.1 不変式の先行評価 if 文などにより、ループ内で選択的に実行される文に含まれる不変式を、ループの外側に移動 します。不変式の先行評価を実施することにより、より実行時間を短縮できますが、移動により 副作用が生じることがあるので注意が必要です。 不変式の先行評価は、-Kpreex オプションで制御することができます。 26 第 3 章 逐次最適化機能 不変式の先行評価により、プログラムの論理上実行されないはずの命令が実行され、エラーにな る場合があります。ただし、計算結果およびその精度に影響を与えることはありません。 実行場所の移動による影響は、ライブラリ関数の引用、配列要素の引用および除算で発生する可 能性があります。以下に、不変式の先行評価による影響の例を示します。 例 1: 配列要素の引用 int a[10],b[10]; ... for(i=0; i<10; i++){ if(j<10) a[i] = b[j] * f; } ... int a[10],b[10]; ... t = b[j] * f; for(i=0; i<10; i++){ if(j<10) a[i] = t; } ... [ 説明 ] 左側のプログラムでは、変数 j が 9 以下のときだけ配列要素 b[j] を引用しているので、配列 b の宣言範囲を超えることはありません。 不変式の先行評価により、配列要素 b[j] がループ外に移動されて、j の値に関係なく引用さ れます。その結果、たとえば j の値が 10 以上であれば、配列の宣言範囲を超えて引用されます。 j の値が非常に大きい場合は、不当な領域を参照して、プログラムの実行が中断することがあ ります。t はコンパイラが生成した int 型の変数です。 例 2:除算 int a[100],b,f; ... for(i=0; i<n; i++){ if(f != 0) a[i] = b / f; else a[i] = 0; } ... int a[100],b,f; ... t = b/f; for(i=0; i<n; i++){ if(f != 0) a[i] = t; else a[i] = 0; } ... [ 説明 ] 左側のファイルでは、変数 f が 0 でないときだけ除算を行っているので、除算例外のエラーが 発生することはありません。 不変式の先行評価により、除算 b/f がループ外に移動されて、f の値に関係なく実行されま す。その結果、たとえば変数 f の値が 0 であれば、プログラムの実行が中断します。t はコン パイラが生成した int 型の変数です。 3.3.2.2 演算評価方法の変更 演算の評価方法を変更して実行時間を短縮します。変更により副作用が生じることがあるので注 意が必要です。 演算順序の変更 定数どうしの翻訳時計算、不変式の移動、命令スケジューリングなどの最適化を促進するため、 演算順序を変更します。演算例外(オーバフローやアンダフロー)が発生しなかった計算が、演 算順序を変更することによって、演算例外が発生する場合があります。また、浮動小数点演算で は、各演算項の有効桁によっては、演算結果の精度が異なる場合があります。演算順序の変更 は、-Keval オプションで制御することができます。 以下に、演算順序の変更の例を示します。 27 C 言語使用手引書 例:演算順序の変更 double a[100],b[100],c[100]; double x,y; ... for(i=0; i<100; i++){ a[i] = b[i] * x * c[i] * y; double a[100],b[100],c[100]; double x,y; ... t = x * y; for(i=0; i<100; i++){ a[i] = b[i] * c[i] * t; ... [ 説明 ] 不変項どうしの演算が集められた後、x*y が不変式としてループの外側に移動されます。 配列 b,c および変数 x,y の値によっては、左側の計算では演算例外が発生せず意図したとお り計算できたものが、右側の計算では演算例外が発生し意図した結果が得られない場合があり ます。t はコンパイラが生成した double 型の変数です。 なお、演算順序の変更により演算例外が発生したり演算結果の精度が異なるようなプログラム は、もともと限界値に近い値を処理したり精度に敏感な計算をしているプログラムであるとも いえます。したがって、本最適化を実施して副作用が発生したとしても、本最適化が根本的な 原因ではない場合もあります。 除算の乗算化 ループ内で不変な除算を乗算に変更します。この除算の乗算化により、実行速度を短縮すること ができますが、実行結果の精度に影響を与える場合があるので注意が必要です。除算の乗算化 は、-Keval オプションで制御することができます。 以下に、除算の乗算化の例およびその影響を示します。 例:除算の乗算化 float a[10],b[10],v; ... for(i=0; i<10; i++) a[i] = b[i] / v; float a[10],b[10],v; ... t = 1.0 /v; for(i=0; i<10; i++) a[i] = b[i] * t; [ 説明 ] ループ内の演算 b[i]/v を乗算 b[i]*t に変換します。t はコンパイラが生成した float 型 の変数です。 右側のプログラムでは、最適化により 1.0/v がループの外に移動されて t の乗算に変更さ れ、精度誤差が生じる可能性があります。 3.3.3 ポインタの最適化 ポインタの最適化を行わない場合 ( 通常 ) は、ポインタ変数がどこを指しているかわからないと いう前提のもとに、安全側に立って最適化を行います。これに対して、ポインタの最適化は、以 下の前提条件を付けて最適化を行います。 ・ 前提条件1 同じ領域を異なるポインタ変数が指すことはない。 ・ 前提条件2 同じ領域に対して、ポインタ変数でアクセスする場合とポインタ変数を使わずに直接アクセス する場合が混在することはない。 たとえば、ポインタ変数でアクセスする領域が、malloc 関数などで動的に確保した領域に限ら れていることが明らかな場合は、前提条件 2 を満足します。 28 第 3 章 逐次最適化機能 これらの前提条件を付けることにより、共通式の除去や不変式の移動などの最適化が、ポインタ 変数を使わずにアクセスする場合と同様に行われるので、高速なオブジェクトプログラムが得ら れます。 ただし、上記の前提条件を満足しないプログラムに対して、ポインタの最適化を行った場合は、 使用者が意図した結果が得られないことがあります。 ポインタの最適化は、-Kpopt オプションで制御することができます。 例1:ポインタの最適化(前提条件1の説明) a1 = *p + 100; *q = 0; a2 = *p + 100; a1 = *p + 100; *q = 0; a2 = a1; /* 共通式の除去により変更 */ [ 説明 ] ポインタ変数 p とポインタ変数 q は、同じ領域を指していないという前提で最適化します。 その結果、*p+100 は共通式とみなされます。もし、ポインタ変数 p とポインタ変数 q が同じ 領域を指している場合は、利用者が意図した結果になりません。 例2:ポインタの最適化(前提条件2の説明) a1 = *p + b; x = 0; a2 = *p + b; a1 = *p + b; x = 0; a2 = a1; /* 共通式の除去により変更 */ [ 説明 ] ポインタ変数 p は、変数 a1,a2,b,x を指していないという前提で最適化します。 その結果、*p+b は共通式とみなされます。もし、ポインタ変数 p が変数 a1 または変数 x を 指している場合は、利用者が意図した結果になりません。 3.3.4 クロスファイル最適化 複数のソースファイルからなるプログラムの場合、コンパイラにソースファイルのすべてを一度 参照させます。そして、定義された関数について関数呼出しのインライン展開を行い、かつデー タの依存関係や制御依存関係を解析することで、最適化をより効果的にすることができます。こ のような最適化をクロスファイル最適化と呼びます。 クロスファイル最適化は、-Kcrossfile オプションで制御することができます。 オブジェクトプログラムを構成するために必要なソースファイルは、すべて一度に指定しなけれ ばなりません. 例:クロスファイルの指定方法 fcc sample1.c sample2.c sample3.c -Kfast -Kcrossfile 3.4 最適化機能の活用方法 最適化機能を有効に活用するための機能について説明します。 3.4.1 最適化制御行 (OCL) の利用 最適化にとって有効な情報をソースプログラム上に記述することにより、最適化の効果をより高 めることができます。 #pragma 行に以下の記述がある場合、それを最適化制御行と呼びます。 最適化制御行は、-Kocl オプションで制御することができます。 29 C 言語使用手引書 3.4.1.1 最適化制御行 (OCL) の種類 最適化制御行の種類とその有効範囲を「表 3.1 最適化制御行と有効範囲」に示します。 表 3.1 最適化制御行と有効範囲 前処理字句列 最適化制御行の名称 最適化の有効範囲 global global 行 翻訳単位内 procedure procedure 行 関数内 loop loop 行 直後のループ statement statement 行 直後の文 global 行 指定された最適化指示子を翻訳単位内すべてに有効にします。 書式 #pragma global 最適化指示子 挿入位置 対象にしたい翻訳単位の先頭に記述します。 procedure 行 指定された最適化指示子を関数内で有効にします。 書式 #pragma procedure 最適化指示子 挿入位置 対象にしたい関数の宣言文 ( 宣言と同時に初期値を設定している文も含みます ) と最初の実行文 の間に記述します。 loop 行 指定された最適化指示子を直後のループで有効にします。 書式 #pragma loop 最適化指示子 挿入位置 対象にしたいループの直前に記述します。 statement 行 指定された最適化指示子を直後の文で有効にします。 書式 #pragma statement 最適化指示子 挿入位置 対象にしたい文の直前に記述します。 注意 最適化指示行に指定できる最適化指示子は1つです。global 行、procedure 行および loop 行で は、複数の最適化指示行を連続して記述することにより、複数の最適化指示子が有効となります。 statement 行を連続して記述した場合、最後の statement 行が有効となります。 30 第 3 章 逐次最適化機能 3.4.1.2 最適化指示子の種類 「表 3.2 最適化制御行に指定できる最適化指示子」に、逐次最適化に対する最適化指示子を以下 に示します。 表 3.2 最適化制御行に指定できる最適化指示子 最適化指示子 機能説明 指定できる最 適化制御行注 G P L S eval noeval 演算の評価方法を変更する最適化を行うか否か を指示します。 ○ ○ ○ × fmadd nofmadd 加減算と乗算を含む式の最適化を行うか否かを 指示します。 ○ ○ ○ × if p if 文の条件式が真である確率 p を百分率(パーセ ント)で指定します。 × × × ○ preex nopreex 不変式の先行評価を行うか否かを指示します。 ○ ○ ○ × norecurrence [(ary,...)] ループスライス可能な配列 ary を指示します。 ○ ○ ○ × unroll[ml] 対応するループをアンローリングすることを指 ○ 示します。 ml はループ・アンローリングの展開数(多重度) を指定します。ml は 2 ~ 100 の 10 進数です。 ○ ○ × 注. G: global 行 P: procedure 行 L: loop 行 S: statement 行 ○:最適化指示子を最適化制御行に指定できます。 ×:最適化指示子を最適化制御行に指定できません。 3.4.2 プロファイル情報の利用 プログラムの実行状況を示す情報 ( プロファイル情報と呼びます ) をいったんファイルに出力し て、それをコンパイラが参照しながら最適化することにより、より高速なオブジェクトプログラ ムを生成することができます。 プロファイル情報を利用した最適化は、以下の 2 段階を経て行われます。 第 1 段階 : プロファイル情報の生成 通常のオプションの他に、-Kpg を指定して翻訳します。 -Kpg を指定して翻訳したプログラム を実行すると、プロファイル情報ファイルにプロファイル情報が生成されます。 第 2 段階 : プロファイル情報の利用 通常のオプションの他に、-Kpu を指定して翻訳します。 -Kpu を指定して翻訳すると、第 1 段 階で作成されたプロファイル情報を最適化に活かした、より高速なオブジェクトプログラムが 得られます。 第 1 段階と第 2 段階は、一緒に行うことはできません。また、-Kpg と一緒に指定した翻訳時オ プションと、-Kpu と一緒に指定した翻訳時オプションは、並び順も含めて内容が一致しなけれ ばなりません。異なる場合、メッセージが出力され翻訳が中断します。 以下に、プロファイル情報を利用してロードモジュールを作成し、それを実行するまでのコマン ドの例を示します。 31 C 言語使用手引書 1.fcc sample.c -Kfast -Kpg : プロファイル情報を生成する準備 2.a.out : プロファイル情報を実際に生成 3.fcc sample.c -Kfast -Kpu : プロファイル情報を利用して最適化 4.a.out : より高速化されたロードモジュールの実行 上記の (1) および (2) が第 1 段階、(3) が第 2 段階です。 プロファイル情報は、ソースプログラムの名前の後ろに .d を付加した名前のプロファイル情報 ファイルに生成されます。すでにファイルがある場合、累積する形で情報が書き込まれます。そ のとき、以前に作成したときと翻訳時オプションが一致しているか否かが調べられ、一致しない 場合、実行が中断されます。 以下に、3 つの入力データについてプログラム実行し、プロファイル情報を累積するコマンドの 例を示します。これらは、すべて第 1 段階の作業です。 1.fcc sample.c -Kfast -Kpg 2.[rm sample.c.d] 3.a.out < case1.data 4.a.out < case2.data 5.a.out < case3.data 最適化制御行で if 文の条件の成立確率が指定されている場合、プロファイル情報が優先し、そ の最適化制御行は無効になります。 なお、分岐 (if 文など ) が全くないプログラムや最適化により分岐がすべて削除された場合、プ ロファイル情報は生成されませんし、参照もされません。 クロスファイル最適化とプロファイル情報を併用して利用するときの方法は、単にプロファイル 情報だけを利用するときの方法と同じです。なお、-Kpg -Kcrossfile 指定で翻訳したときは、統 計情報に -Kcrossfile の情報は表示されません。 3.4.3 実行マシン属性の選択 実行可能プログラムを実行するマシンの種別を翻訳時オプションで指定することにより、そのマ シンに最も適したオブジェクトプログラムが出力され、より高速化することができます。 マシンの属性としては、以下の 2 種類があります。 CPU の種類を示すもの これを指定する翻訳時オプションとして、-Kcpu があります。cpu には、SPARC64_GP、SPARC64_GP2、 SPARC64VI、ULTRA、ULTRA1 または ULTRA2 が指定できます。-Kcpu が指定されない場合には、 -KULTRA2 が指定されたものと見なされます。 -Kcpu を指定することにより、各 CPU に最適な命令選択と命令スケジューリングが行われます。 SPARC アーキテクチャの世代を示すもの これを指定する翻訳時オプションとして、-Karchi があります。archi には、V8、V8PFMADD、 V8PLUS、V9 または V9FMADD が指定できます。-Karchi が指定されない場合には、-KV8 が指定さ れたものと見なされます。 マシン属性の自動選択 翻訳時オプション -Kfast を指定することにより、マシンの属性をコンパイラに自動的に選択さ せることができます。 -Kfast が指定された場合、コンパイラは、コンパイラが動作しているマシンの属性を実行マシ ンの属性として採用します。すなわち、コンパイラは、-KSPARC64_GP、-KSPARC64_GP2、 -KSPARC64VI、-KULTRA、-KULTRA1 または -KULTRA2 の中から、コンパイラが動作しているマシン に適したオプションを自動的に選択します。 実行マシンの注意事項 -KV8PFMADD または -KV9FMADD が有効な場合、multiply add/subtract 浮動小数点演算命令が生成 されます。この命令は、浮動小数演算精度に影響を与えることがあります。 この命令を抑止するには、-KNOFMADD を指定してください。 3.4.4 最適化機能の選択の目安 ここでは、プログラムを高速に実行できるようなオブジェクトプログラムを生成するために、最 適化機能をどのように使用したらよいかの目安について説明します。 最適化機能を使用しない場合 32 第 3 章 逐次最適化機能 最適化に関する翻訳時オプションを何も指定しなければ、最適化は行われません。通常、デバッ グ中のプログラムは、最適化機能を使用しないで翻訳します。 一般的なプログラムを平均的に高速化する場合 一般的なプログラムを、平均的に高速に実行できるようなオブジェクトプログラムを生成するた めに、最適化機能の一般的な使用方法について説明します。 以下に示すような、翻訳時オプションの指定と再翻訳だけでソースに手を入れることなく性能向 上が可能です。 実行マシン属性からの選択 実行マシンの属性 (「3.4.3 実行マシン属性の選択」を参照 ) を考慮して、以下の翻訳時オプショ ンを指定します。 翻訳マシンと同じマシン属性上で実行することを前提とした場合 -Kfast を指定します。 翻訳マシンと異なるマシン属性上で実行することを想定した場合 -O オプションを指定します。 関数のインライン展開の選択 関数をインライン展開 (「3.3.1 インライン展開」を参照 ) する場合は、以下の翻訳時オプショ ンを指定します。 標準関数のインライン展開の選択 -Klib を指定します。 標準関数と同じ名前の関数を利用者が定義している場合、利用者の意図した結果にならない場 合があります。 なお、-Klib は、-Kfast に含まれていますので、-Kfast を指定した場合、-Klib を指定する必 要はありません。 ソースプログラム上で定義された関数のインライン展開の選択 -x オプションを指定します。 -x n で指定する値 n は、一般的に 10 ~ 50 の範囲が妥当です。 プログラムの性質を活かした最適化を行う場合 プログラムを、より高速に実行できるようなオブジェクトプログラムに生成する場合に有効で す。-O オプションおよび拡張最適化機能 (-K opt) の中から、プログラムの性質に見合った翻訳 時オプションを指定します。 さらにプログラムを高速に実行したい場合、ツール注 などを使用しながら、性能ネックとなる 部分を確認することも必要です。その結果、最適な翻訳時オプションとなるように調整し、場合 によってはソースプログラムに手を加えることなども必要です。 注 . 性能ネックを検出するツールには、プログラミング支援ツール (Parallelnavi 環境 )、あ るいは並列アナライザ ( 非 Parallelnavi 環境 ) があります。 33 C 言語使用手引書 34 第 4 章 並列化機能 この章では、本処理系を使用して、C 言語プログラムを並列処理する方法について記述していま す。 4.1 並列処理の概要 ここでは、C 言語プログラムの並列処理の概要と、本処理系の並列機能の特徴について説明して います。 4.1.1 並列処理とは 並列処理という言葉は広い意味に使われていますが、ここで述べる並列処理とは、独立に動作可 能な複数の CPU を同時に使って、一つのプログラムを実行することを意味します。ここでは、複 数のプログラムを同時に実行するマルチジョブのことを、並列処理とは言わないことにします。 「図 4.1 並列処理のイメージ」に、同時に複数の CPU を利用して並列処理する様子を示します。 for(i=0; i<1000; i++){ a[i] = b[i] + c[i]; } for ループを分割して、複数の CPU 上で同時に実行する。 for(i=0; i<500; i++){ a[i] = b[i] + c[i]; } for(i=500; i<1000; i++){ a[i] = b[i] + c[i]; } CPU1 CPU0 図 4.1 並列処理のイメージ 4.1.2 並列処理の効果 並列処理の効果は、複数の CPU を同時に使うことによってプログラムの経過時間が短縮されるこ とです。例えば、「図 4.1 並列処理のイメージ」に示すように、for ループを分割して 2 個の for ループを並列実行できたとすると、この for ループを実行するのにかかる時間は、理想的に は半分になります(「図 4.2 並列処理による経過時間の短縮」)。 CPU0 経 過 時 間 for(i=0; i<500; i++) for(i=500; i<1000; i++) 1 個の CPU 上で逐次処理 CPU1 for(i=0; i<500; i++) for(i=500; i<1000; i++) 2 個の CPU で同時に実行されることにより、経過時 間が短縮される。 2 個の CPU 上で並列処理 図 4.2 並列処理による経過時間の短縮 35 C 言語使用手引書 しかし、並列処理によってプログラム実行の経過時間の短縮は可能ですが、プログラム実行に要 する CPU 時間を減らすことはできません。なぜなら、並列処理では複数の CPU を利用しますが、 それぞれの CPU の消費する CPU 時間の合計は、プログラムを逐次的に実行した場合の CPU 時間と 同等か、または、並列処理に必要なオーバヘッドの分だけ増加するためです。 並列処理プログラムの性能は、一般に、実行に要した CPU 時間の短縮ではなく、経過時間の短縮 で評価することに注意してください。逐次的に動作していたプログラムを並列処理によって実行 した場合、並列処理のためのオーバヘッドによってプロセッサ全体で消費する CPU 時間の合計 は、逐次処理時の CPU 時間よりも大きくなります。 4.1.3 並列処理で効果を得るための条件 並列処理で経過時間を短縮するためには、複数の CPU を同時に使える計算機環境が必要です。本 処理系を使用して作成した並列処理プログラムは、単一の CPU しかもたないハードウェアでも実 行可能ですが、この場合には経過時間の短縮は望めません。また、複数の CPU をもつハードウェ ア上でも、他のジョブが動いていて計算機全体として CPU 時間が不足しているような状況下で は、経過時間の短縮は難しくなります。これは、並列処理プログラムの実行のために、同時に複 数の CPU が割り当てられる機会が少なくなるためです。 つまり、並列処理で効果を得るためには、複数の CPU をもつハードウェア上で、かつ、システム 全体としてCPU処理能力に余裕のある環境下で、並列処理プログラムを実行する必要があります。 また、並列処理のためのオーバヘッドを相対的に小さくするため、ループの繰返し数またはルー プ中の実行文数が多いことが必要です。 4.1.4 本処理系の並列機能の特徴 本処理系は、自動並列化機能および OpenMP 仕様に基づいた並列化機能を提供します。 自動並列化は、本処理系が自動的にプログラムを並列処理することです。自動並列化の対象とな るのは、本処理系が並列化可能であると認識できる for ループ、while ループおよび if-goto ループ(以降、単にループと呼びます)に限られますが、プログラムの書き換えなどのユーザ負 担を軽減できます。 自動並列化の機能を利用する場合、逐次実行可能なソースプログラムに、何ら手を加える必要は ありません。したがって、プログラムが C 言語規格に合致している限り、他の処理系ソースプロ グラムを移植するのは容易です。 また、本処理系には、自動並列化を促進する最適化制御行が用意されています。最適化制御行 は、利用者がコンパイラに自動並列化の参考になる情報を通知し、効率の良いオブジェクト生成 を促進するために用いられます。 自動並列化については、「4.2 自動並列化」をお読みください。 OpenMP 仕様による並列化については、「4.3 OpenMP 仕様による並列化」をお読みください。 4.2 自動並列化 ここでは、本処理系で提供している自動並列化について説明します。 4.2.1 翻訳・実行の方法 ここでは、自動並列化機能を使うための翻訳および実行の方法について説明します。 4.2.1.1 翻訳の方法 自動並列化の機能を使用するには、翻訳時オプションとして -Kparallel を指定します。 4.2.1.1.1 自動並列化のための翻訳時オプション 自動並列化機能に関連するオプションの形式と意味を以下に説明します。 -Kparallel[,reduction,instance=N,ocl,pmsg] -Kparallel 自動並列化を行います。 -O3 が誘導されます。-O0、-O1 または -O2 を同時に指定した場合、指定の順序に関係なく -O3 に 変更されます。 -g オプションと同時に指定できません。同時に指定した場合、-Kparallel は無効になります。 36 第 4 章 並列化機能 -Kparallel は、結合編集時にも指定する必要があります。-Kparallel を指定して翻訳されたオ ブジェクトプログラムが含まれる場合は、結合編集時に -Kparallel を指定する必要があります。 例: $ fcc a.c -Kparallel -c $ fcc a.o -Kparallel -Kreduction -Kparallel と同時に指定した場合に有効です。 リダクションの最適化(「4.2.3.1.7 リダクションによるループスライス」を参照)を行います。 この最適化を行うと、結果に精度差が生じる可能性があります。利用者は、翻訳時の診断メッ セージにより、この最適化が行われたかどうか知ることができます。 -Kparallel と -Keval を同時に指定した場合にも、リダクションの最適化を行います。 -Kinstance=N -Kparallel と同時に指定した場合に有効です。 コンパイラは実行時のスレッドの数を N に想定したオブジェクトプログラムを出力します。これ によって、自動並列化された for ループの回転数を計算する命令が軽減されて、実行性能が向上 します。 翻訳時オプション -Kparallel,instance=N で、並列動作のスレッド数を指定する場合、実行時の スレッド数と同じ値でなければなりません。N の値が実行時のスレッド数と異なる場合、実行結 果を保証できません。 -Kocl -Kparallel と同時に指定した場合に有効です。 自動並列化を促進する最適化制御行(「4.2.3.2 最適化制御行」を参照)を有効にします。 -Kpmsg -Kparallel と同時に指定した場合に有効です。 翻訳時メッセージにより、自動並列化されたループを通知します。 4.2.1.2 実行の方法 自動並列化されたプログラムを実行させるときは、環境変数 PARALLEL で、並列に動作させるス レッドの数を指定することができます。また、環境変数 THREAD_STACK_SIZE で、スレッド毎のス タック領域の大きさを指定することができます。さらに、環境変数 FLIB_SPINWAIT で、スレッド の同期待ちの方法を変更することができます。 その他の実行に関する手続きは、逐次実行のときと同じです。 4.2.1.2.1 環境変数 PARALLEL 環境変数 PARALLEL で、並列に動作させるスレッドの数を指定することができます。スレッド数 の決定方法の詳細については、「4.2.1.2.2 スレッド数」をお読みください。 4.2.1.2.2 スレッド数 並列に動作するスレッドの数は、まず以下の優先順位で決定されます。 1.環境変数 PARALLEL の指定値注 2.環境変数 OMP_NUM_THREADS の指定値 3.Solaris プロセッサセットの CPU 数 4.1 上記の優先順位で決まったスレッド数と、CPU 数の上限値を比較して、小さい方を最終的なス レッド数として採用します。 なお、CPU 数の上限値は、次のように決定されます。 Solaris プロセッサセットが定義されている場合 注 . 結合編集時に -KOMP が指定され、かつ環境変数 FLIB_FASTOMP に TRUE が設定されている とき、環境変数 OMP_NUM_THREADS の指定値があれば、その値と一致していなければなり ません。一致していない場合には、小さい方の値が採用されます。この時に、環境変数 FLIB_C_MESSAGE が存在する場合には、mpc1042i-w のメッセージが出力されます。 37 C 言語使用手引書 ・ プロセッサセット内では、プロセッサセットの CPU 数 ・ プロセッサセット外では、システムの CPU 数 ただし、自動並列のスレッド数が 128 を超えた場合の動作は保証されません。 環境変数 PARALLEL に指定する値は 128 以下にしてください。 Solaris プロセッサセットが定義されていない場合 ・ システムの CPU 数 環境変数 OMP_NUM_THREADS については、 「4.3.1.2.2 OpenMP 仕様の環境変数」をお読みください。 Parallelnavi 環境下で実行する場合のスレッド数については、 「付録 F Parallelnavi」をお読み ください。 4.2.1.2.3 環境変数 THREAD_STACK_SIZE 環境変数 THREAD_STACK_SIZE で、スレッド毎のスタック領域の大きさを K バイト単位で指定する ことができます。スタック領域の詳細については、 「4.2.1.2.4 実行時の領域」をお読みください。 4.2.1.2.4 実行時の領域 自動並列化されたループ内でローカルな変数は、スタック領域に割り付けられます。これらの変 数が多い場合には、スタック領域を十分な大きさに拡張する必要があります。プロセスのスタッ ク領域は、limit(1) コマンドで設定が可能です。スレッド毎のスタック領域は、プロセスのス タック領域と同じ大きさで確保されます。ただし、プロセスのスタック領域の制限値が、使用可 能な実装メモリと仮想メモリの大きさの小さい方をスレッド数で割った値より大きい場合、本シ ステムがスレッド毎のスタック領域の大きさを次のように仮定して確保します。なお、仮想メモ リの大きさとは、limit(1) コマンドの仮想記憶の最大サイズとして表示される値です。 S = ( M/T ) / 5 S: スレッド毎のスタック領域の大きさ(byte) M: 実装メモリと仮想メモリの小さい方の大きさ(byte) T: スレッド数 ス レ ッ ド 毎 の ス タ ッ ク 領 域 の 大 き さ を、特 定 の 大 き さ で 確 保 し た い 場 合 に は、環 境 変 数 THREAD_STACK_SIZE を使用してください。 4.2.1.2.5 同期待ち処理 環境変数 FLIB_SPINWAIT で、同期待ち処理を調節することができます。デフォルトは unlimited です。 unlimited: 同期が獲得できるまでスピン待ちを行います。 0: スピン待ちを行わず、サスペンド待ちを行います。 <n>s:n 秒間スピン待ちし、その後サスペンド待ちに移ります。 <n>ms:n ミリ秒間スピン待ちし、その後サスペンド待ちに移ります。 <n> は 0 以上の整数 スピン待ちとは、スレッド間で同期を待ち合うとき、CPU 時間を消費する方法で待たせる方式で す。逆に、サスペンド待ちは CPU 時間を消費せずに待たせます。スピン待ちを行う方が並列処理 のオーバヘッドが少ないため、経過時間を重視する場合には、unlimited を選択してください。 CPU 時間を重視する場合は、0 を選択してください。 4.2.1.3 翻訳・実行の例 例 1: $ fcc -Kparallel,reduction,ocl test1.c $ ./a.out 例 1 は、リダクションの最適化と最適化制御行を有効にして、ソースプログラムを翻訳します。 このプログラムは、1 個のスレッドを使用して動作します。 例 2: $ $ $ $ $ fcc -Kparallel test2.c setenv PARALLEL 2 a.out setenv PARALLEL 4 a.out 38 第 4 章 並列化機能 環境変数 PARALLEL に値 2 を設定して、2 個のスレッドを使用して動作させます。 次に、環境変数 PARALLEL に値 4 を設定して、4 個のスレッドを使用して動作させます。 例 3: $ psrinfo 0 on-line since 30/06/00 09:29:00 1 on-line since 30/06/00 09:29:00 2 on-line since 30/06/00 09:29:00 3 on-line since 30/06/00 09:29:00 $ fcc -Kparallel test3.c $ setenv PARALLEL 3 $ a.out まず、psrinfo コマンドで、アクティブ CPU 数(on-line の CPU 数)が 4 であることを確認しま す。次に、環境変数 PARALLEL に値 3 を設定して、3 個のスレッドを使用して動作させます。 なお、これは、Parallelnavi がインストールされていないシステムにおいてプログラムを並列 に動作させている例です。Parallelnavi がインストールされているシステムに関しては、 「付録 F Parallelnavi」をお読みください。 4.2.2 並列化プログラムのチューニング 並列化したプログラムをチューニングする手段として、実行時間のサンプリング機能を利用する ことができます。実行時間の情報により、プログラムのどの文の実行コストが高いかを知ること ができます。プログラムを高速に実行させるには、実行コストの高い文が並列に動作するように プログラミングします。 4.2.3 自動並列化処理の詳細 ここでは、自動並列化処理の各機能の詳細および留意事項について説明します。 最初に自動並列化について説明し、次に自動並列化を促進するための最適化制御行について説明 します。最後に自動並列化機能を使うときの留意事項について説明します。 4.2.3.1 自動並列化 ここでは、本処理系のもつ自動並列化機能について説明します。 4.2.3.1.1 自動並列化の対象 自動並列化機能は、C 言語ソースプログラム中のループ(多重ループも含みます)とポインタ演 算を並列化の対象にします。 4.2.3.1.2 ループスライスとは 自動並列化機能は、ループを複数に分割します。そして分割されたループを並列に実行すること で、経過時間の短縮を図ります。この並列化をループスライスと呼びます。「図 4.3 ループス ライスのイメージ」に、ループスライスのイメージを示します。 for(i=0; i<10000; i++){ a[i] = b[i] + c[i]; } for(i=0; i<5000; i++){ a[i] = b[i] + c[i]; } for(i=5000; i<10000; i++){ a[i] = b[i] + c[i]; } 図 4.3 ループスライスのイメージ 39 C 言語使用手引書 4.2.3.1.3 コンパイラによる自動ループスライス 本処理系は、ループスライスを行ってもデータの定義引用順序が変わらないようなループを自動 並列化の対象として選択して、並列実行の結果が逐次実行の結果と同じになるようにします。 「図 4.4 ループスライスができないループの例」に、自動ループスライスの対象にならない例 を示します。この for ループでは、本来、for 文の制御変数 i が 4999 の時に定義された配列要 素 a[4999] の値を、for 文の制御変数 i が 5000 のときに引用しなければなりません。しかし、こ の for ループを単純にループスライスして並列に実行すると、a[4999] を定義する前に引用する 可能性があり、実行結果を誤ることになります。 for(i=1; i<10000; i++){ a[i] = a[i-1] + b[i]; } for(i=1; i<5000; i++){ a[i] = a[i-1] + b[i]; } for(i=5000; i<10000; i++){ a[i] = a[i-1] + b[i]; } 図 4.4 ループスライスができないループの例 4.2.3.1.4 ループ交換と自動ループスライス 多重ループに対してループスライスを実施する場合、本処理系は、ループスライスが可能なルー プを選択し、可能ならばループの交換を行い、できるだけ外側のループをループスライスしま す。これは、できるだけ並列処理制御の回数を少なくしてオーバヘッドを削減し、実行性能を向 上させるためです。 ループ交換は、-Kparallel に加え、-Keval が指定されたときにだけ行われます。 40 第 4 章 並列化機能 「図 4.5 多重ループでのループ交換」に、多重ループにおいて for ループが交換されてループ スライスされた例を示します。制御変数 i について並列化されますが、i を外側のループにする ことで、並列処理制御の回数を少なくすることができます。 for(i=0; i<10000; i++){ for(j=1; j<10; j++){ a[j][i] = a[j][i] + b[j][i]; } } for(j=1; j<10; j++){ for(i=0; i<10000; i++){ a[j][i] = a[j][i] + b[j][i]; } } for(j=1; j<5; j++){ for(i=0; i<10000; i++){ a[j][i] = a[j][i] + b[j][i]; } } 交換 for(j=5; j<10; j++){ for(i=0; i<10000; i++){ a[j][i] = a[j][i] + b[j][i]; } } 図 4.5 多重ループでのループ交換 4.2.3.1.5 ループ分割と自動ループスライス 「図 4.6 ループの分割」のループでは、配列 a は、ループスライスを行うとデータの定義引用 順序が変わるため、ループスライスすることができません。配列 b は、データの定義引用順序が 変わらないので、ループスライスできます。このような場合、配列 a を定義している文と配列 b を定義している文を 2 つのループに分割して、配列 b を定義するループの方をループスライスし ます。 「図 4.6 ループの分割」に、for ループが分割されてループスライスされた例を示します。 41 C 言語使用手引書 for(i=1; i<10000; i++){ a[i] = a[i-1] + c[i]; b[i] = b[i] + c[i]; } for(i=1; i<10000; i++){ a[i] = a[i-1] + c[i]; } 分割 for(i=1; i<10000; i++){ b[i] = b[i] + c[i]; } 2つ目のループを並列化 for(i=5000; i<10000; i++){ b[i] = b[i] + c[i]; } for(i=1; i<5000; i++){ b[i] = b[i] + c[i]; } 図 4.6 ループの分割 4.2.3.1.6 ループ融合と自動ループスライス 「図 4.7 ループの融合」では、回転数の同じループが二つ連続しています。このような場合、 ループを一つに融合することで、ループ制御のオーバヘッドを軽減するとともに、並列処理制御 の回数を減らすことができます。 「図 4.7 ループの融合」に、ループを融合してループスライスされた例を示します。 for(i=0; a[i] = } for(i=0; d[i] = } i<10000; i++){ b[i] + c[i]; i<10000; i++){ e[i] + f[i]; for(i=0; i<10000; i++){ a[i] = b[i] + c[i]; d[i] = e[i] + f[i]; } for(i=0; i<5000; i++){ a[i] = b[i] + c[i]; d[i] = e[i] + f[i]; } 融合 for(i=5000; i<10000; i++){ a[i] = b[i] + c[i]; d[i] = e[i] + f[i]; } 図 4.7 ループの融合 42 第 4 章 並列化機能 4.2.3.1.7 リダクションによるループスライス 翻訳時オプションに -Kparallel と -Kreduction を同時に指定したときに、自動並列化される場 合があります。この並列化は、逐次実行のときと計算結果に精度差を生じる可能性があります が、加算および乗算などの交換可能な演算の順序を変更してループスライスを行います。 リダクションの対象になるのは、ループ内に以下の演算が含まれる場合です。 ・ 総和を求める演算がある場合 例: s = s + a[i]; ・ 積を求める演算がある場合 例: p = p * a[i]; ・ 内積を求める演算がある場合 例: p = p + a[i] * b[i]; ・ 最小値を求める演算がある場合 例: x = min(x, a[i]); ・ 最大値を求める演算がある場合 例: y = max(y, a[i]); ・ ビット OR 演算がある場合 例: n = n | a[i]; ・ ビット AND 演算がある場合 例: m = m & a[i]; 「図 4.8 リダクションによる自動ループスライス」に、リダクションによるループスライスの 例を示します。 sum = 0; for(i=0; i<10000; i++){ sum = sum + a[i]; } sum1 = 0; for(i=0; i<5000; i++){ sum1 = sum1 + a[i]; } sum2 = 0; for(i=5000; i<10000; i++){ sum2 = sum2 + a[i]; } sum = sum + sum1 + sum2; 図 4.8 リダクションによる自動ループスライス 4.2.3.1.8 ループスライスされないループ 以下に示すループは、ループスライスの対象となりません。 ・ 並列実行しても実行時間が短縮されないと予想される場合 ・ 関数の引用を含む場合 ・ ループの形が複雑な場合 ・ 標準関数を含む場合 ・ データの定義引用順序が逐次実行のときと変わるおそれがある場合 43 C 言語使用手引書 並列実行しても実行時間が短縮されないと予想される場合 ループの回転数が小さい場合や、ループ内の演算数が少ない場合は、並列実行に伴うオーバヘッ ドのため、ループスライスを行うと、逐次処理した場合よりも性能が低下することがあります。 そのため、性能が向上しないと予想されるループについては、本処理系はループスライスを行い ません。 「図 4.9 回転数が小さく、演算数が少ないループ」に、回転数が小さく、演算数が少ないルー プの例を示します。 for(i=0; i<10; i++){ a[i] = a[i] + b[i]; } 回転数が小さく、かつ演算数も少ないため、 ループスライスの対象となりません。 図 4.9 回転数が小さく、演算数が少ないループ 関数の引用を含む場合 関数の引用を含むループはループスライスの対象となりません。内部ループに、関数の引用が含 まれているループも同様です。 ただし、最適化制御行によって、並列化を促進することができます。詳細については、 「4.2.3.2 最適化制御行」をお読みください。また、関数がインライン展開された場合は、並列化の対象に なります。 「図 4.10 関数の引用を含むループ」に、関数の引用を含むループの例を示します。 for(j=0; j<10; j++){ for(i=0; i<10000; i++){ a[j][i] = a[j][i] + b[j][i]; func(a); } } 関数呼出しの引用が含まれ るため、ループスライスの 対象となりません。 図 4.10 関数の引用を含むループ ループの形が複雑な場合 以下に示すループは、形が複雑なため、ループスライスの対象となりません。 ・ ループの内側から外側へ飛び出しがあるループ 「図 4.11 飛び出しのあるループ」に、飛び出しのあるループの例を示します。 for(j=0; j<10; j++){ for(i=0; i<10000; i++){ a[j][i] = a[j][i] + b[j][i]; if(a[j][i]<0) goto out; } } out:; for ループ外への飛び出しが あるため、ループスライス の対象となりません。 図 4.11 飛び出しのあるループ 標準関数を含む場合 標準関数は、ループスライスの対象になるものとならないものがありますが、診断メッセージに よって知ることができます。 データの定義引用順序が逐次実行のときと変わるおそれがある場合 44 第 4 章 並列化機能 「図 4.4 ループスライスができないループの例」の例で説明したように、データの定義引用順 序が逐次実行のときと変わるループはループスライスの対象となりません。 4.2.3.1.9 自動並列化状況の表示 自動並列化が行われたかどうか、行われたとしたらどのように行われたかを知りたいときは、翻 訳時オプションに -Kparallel と -Kpmsg を同時に指定してください。翻訳時の診断メッセージに よって、知ることができます。 自動並列化が行われなかった理由も、同様に知ることができます。 4.2.3.2 最適化制御行 本処理系には、自動並列化を促進するために、最適化制御行が用意されています。 自動並列化を促進する最適化制御行を有効にするには、-Kparallel と -Kocl を同時に指定して ください。 4.2.3.2.1 最適化指示子の種類 最適化制御行は、指定される最適化指示子の種類によって、機能が異なります。 「表 4.1 自動並列化用の最適化指示子一覧」に、最適化指示子の種類と機能を示します。自動 並列化用の最適化指示子は、利用者がコンパイラに自動並列化の参考になる情報を通知し、効率 の良いオブジェクトプログラムを生成するために用いられます。 表 4.1 自動並列化用の最適化指示子一覧 指定できる最 適化指示行 意味概略 global 行 procedure 行 loop 行 serial 自動並列化機能を無効にすることを指示し ます。 ○ ○ ○ parallel 自動並列化機能を有効にすることを指示し ます。 ○ ○ ○ norecurrence [ary,..] disjoint [ary,...] ループスライス可能な配列 ary を指示しま す。 ○ ○ ○ temp [var,...] ループ内で一時的に使用している変数 var を 指示します。 ○ ○ ○ independent [ext,...] 関数 (ext)引用のあるループスライスを指示 します。 × ○ ○ reduction noreduction リダクション演算を並列化するか否かを指 示します。 ○ ○ ○ 最適化指示子 ○:指定可能 ×:指定不可 備考: ary,ext,var は使用する前に宣言してください。 4.2.3.2.2 自動並列化の最適化指示子 自動並列化用の最適化指示子を指定した場合であっても、ループスライスの対象とならない for ループについては、最適化指示子の効果は無効になります。ループスライスの対象とならない for ループについては、「4.2.3.1.8 ループスライスされないループ」をお読みください。 45 C 言語使用手引書 4.2.3.2.3 自動並列化用の最適化指示子 自動並列化用の最適化指示子には、次の種類があります。 serial 指示子 serial 指示子は、ループのループスライスを抑止する場合に使用します。 例えば、このループは逐次実行させた方が速いと分かっている場合に使用します。 「図 4.12 serial 指示子のないプログラムの例」のプログラムで、ループ 2 をループスライスし たくない場合、 「図 4.13 serial 指示子の使用例」のように serial を指定することにより、ルー プ 2 のループスライスを止めることができます。 for(j=0; j<10; j++){ for(i=0; i<l; i++){ ループ 1 a1[j][i] = a1[j][i] + b1[j][i]; } } ・ ・ ・ for(j=0; j<10; j++){ for(i=0; i<m; i++){ ループ 2 a2[j][i] = a2[j][i] + b2[j][i]; } } ・ ・ ・ for(j=0; j<10; j++){ for(i=0; i<n; i++){ ループ 3 a3[j][i] = a3[j][i] + b3[j][i]; } } 並 列 動 作 並 列 動 作 並 列 動 作 図 4.12 serial 指示子のないプログラム例 46 第 4 章 並列化機能 for(j=0; j<10; j++){ for(i=0; i<l; i++){ ループ 1 a1[j][i] = a1[j][i] + b1[j][i]; } } ・ ・ ・ #pragma loop serial for(j=0; j<10; j++){ for(i=0; i<m; i++){ ループ 2 a2[j][i] = a2[j][i] + b2[j][i]; } } ・ ・ ・ for(j=0; j<10; j++){ for(i=0; i<n; i++){ ループ 3 a3[j][i] = a3[j][i] + b3[j][i]; } } 並 列 動 作 逐 次 動 作 並 列 動 作 図 4.13 serial 指示子の使用例 parallel 指示子 parallel 指示子は、serial の効果を打ち消して、一部のループだけをループスライスの対象と する場合に使用します。 「図 4.14 parallel 指示子のないプログラム例」で、ループ 2 のループだけをループスライスの 対象にしたい場合、 「図 4.15 parallel 指示子の使用例」のように serial と parallel を併用す ることにより、ループ 2 のループだけをループスライスの対象にすることができます。 for(j=0; j<10; j++){ for(i=0; i<l; i++){ ループ 1 a1[j][i] = a1[j][i] + b1[j][i]; } } ・ ・ ・ for(j=0; j<10; j++){ for(i=0; i<m; i++){ ループ 2 a2[j][i] = a2[j][i] + b2[j][i]; } } ・ ・ ・ for(j=0; j<10; j++){ for(i=0; i<n; i++){ ループ 3 a3[j][i] = a3[j][i] + b3[j][i]; } } 並 列 動 作 並 列 動 作 並 列 動 作 図 4.14 parallel 指示子のないプログラム例 47 C 言語使用手引書 #pragma global serial for(j=0; j<10; j++){ for(i=0; i<l; i++){ ループ 1 a1[j][i] = a1[j][i] + b1[j][i]; } } ・ ・ ・ #pragma loop parallel for(j=0; j<10; j++){ for(i=0; i<m; i++){ ループ 2 a2[j][i] = a2[j][i] + b2[j][i]; } } ・ ・ ・ for(j=0; j<10; j++){ for(i=0; i<n; i++){ ループ 3 a3[j][i] = a3[j][i] + b3[j][i]; } } 逐 次 動 作 並 列 動 作 逐 次 動 作 図 4.15 parallel 指示子の使用例 disjoint 指示子および norecurrence 指示子 disjoint 指示子および norecurrence 指示子は、ループ内の演算対象となる配列の定義引用順序 がループスライスを行っても逐次実行の時と変わらないことを、本処理系に指示します。 norecurrence 指示子は、disjoint 指示子と等価です。 これにより、配列の定義引用順序が不明でループスライスできなかったループを、ループスライ スの対象にします。 「図 4.16 disjoint 指示子のないループの例」の場合、配列 a の添字式が別の配列要素 l[i] で あるため、本処理系は配列 a がループスライスしても問題がないか判断できません。したがっ て、この外側のループはループスライスされません。 for(j=0; j<1000; j++){ for(i=0; i<1000; i++){ a[j][l[i]] = a[j][l[i]] + b[j][i]; } } 図 4.16 disjoint 指示子のないループの例 もし配列 a がループスライスしても問題がないと分かっているのであれば、 「図 4.17 disjoint 指示子の使用例」のように disjoint を使用することにより、この外側のループはループスライ スされます。 #pragma loop disjoint a for(j=0; j<1000; j++){ for(i=0; i<1000; i++){ a[j][l[i]] = a[j][l[i]] + b[j][i]; } } 並 列 動 作 図 4.17 disjoint 指示子の使用例 48 第 4 章 並列化機能 注意事項 disjoint 指示子をループスライス不可能な配列に対して指定した場合、本処理系は誤ったルー プスライスを行うことがあります。 temp 指示子 temp 指示子は、ループ内で引用されている変数がそのループの中で一時的に使用されているこ とを、本処理系に指示するために使用します。 これにより、並列化したループの実行性能を向上させることができます。 「図 4.18 temp 指示子のないプログラム例」の場合は、変数 t がループの中でしか使用されてい なくても、t が外部変数であるため、本処理系は t が関数 func の中で参照されていると判断し、 t の値が正しくなるようなループスライスを行います。 int t; main() { ・ ・ ・ for(j=0; j<50; j++){ for(i=0; i<1000; i++){ t = a[j][i] + b[j][i]; c[j][i] = t + d[j][i]; } } ・ ・ ・ func(); 並 列 動 作 } 図 4.18 temp 指示子のないプログラム例 この場合、ループの終了時の t の値が、関数 func の中で参照されないことが分かるのであれば、 「図 4.19 temp 指示子の使用例」のように temp で t を指定します。これにより、ループ終了時 の t の値を正しくする命令が不要になるので、実行性能が向上します。 int t; main() { ・ ・ ・ #pragma loop temp t for(j=0; j<50; j++){ for(i=0; i<1000; i++){ t = a[j][i] + b[j][i]; c[j][i] = t + d[j][i]; } } ・ ・ ・ func(); } 並 列 動 作 図 4.19 temp 指示子の使用例 49 C 言語使用手引書 注意事項 temp 指示子に、一時的に使用されている変数以外の変数を誤って指定した場合、本処理系は誤っ たループスライスを行うことがあります。 independent 指示子 independent指示子は、ループ内の関数を引用しても逐次実行のときと動作が変わらないことを、 本処理系に指示します。これにより、関数の引用のあるループをループスライスの対象にします。 independent 指示子にはループスライスに影響しない関数名を指定できます。また、関数名を省 略すると、対象範囲内のすべての関数に有効となります。independent 指示子に指定した関数は、 -Kparallel を指定して翻訳しなければなりません。 「図 4.20 independent 指示子のないループの例」の場合、関数 func を引用しているため、本処 理系はループがループスライス可能であるかどうか判断できません。 #include <math.h> main() { double a[10000],j; double func(double); for(i=0; i<10000; i++){ j = 1; a[i] = func(j); } ・ ・ ・ } double func(double j) { return sqrt(pow(j,2) + 3*j + 6); } 図 4.20 independent 指示子のないループの例 もし関数funcの引用のあるループをループスライスしても、実行結果に影響を与えないと分かっ ているのであれば、「図 4.21 independent 指示子の使用例」のように independent を使用する ことにより、このループはループスライスされます。 #include <math.h> main() { double a[10000],j; double func(double); #pragma loop independent func for(i=0; i<10000; i++){ j = 1; a[i] = func(j); } ・ ・ ・ } double func(double j) { return sqrt(pow(j,2) + 3*j + 6); } 並 列 動 作 図 4.21 independent 指示子の使用例 注意事項 50 第 4 章 並列化機能 independent 指示子に、ループスライス不可能な手続きを誤って指定した場合、本処理系は誤っ たループスライスを行うことがあります。なお、ループスライス不可能な手続きの例として、以 下のようなループがあります。 ・ 手続き間で依存関係がある手続き reduction 指示子 reduction 指示子は、リダクション演算が含まれるループを並列化することを、本処理系に指示 します。 「図 4.22 reduction 指示子の使用例」の場合、-Kreduction を指定しなくても、reduction 指示 子を指定することにより、リダクション演算を含むループを並列化することができます。 #pragma loop reduction for(i=0; i<5000; i++){ s = s + a[i]; } 並 列 動 作 図 4.22 reduction 指示子の使用例 noreduction 指示子 noreduction 指示子は、リダクション演算が含まれるループを並列化しないことを、本処理系に 指示します。 「図 4.23 noreduction 指示子の使用例」の場合、noreduction 指示子を指定することにより、リ ダクション演算を含むループの並列化を抑止することができます。 #pragma loop noreduction for(i=0; i<5000; i++){ s = s + a[i]; } 逐 次 動 作 図 4.23 noreduction 指示子の使用例 4.2.3.3 自動並列化機能を使うときの留意事項 本処理系の自動並列化機能を使用する場合の留意事項について説明します。 4.2.3.3.1 並列処理の入れ子での注意 ループスライスされたループ内で関数を引用していて、引用先の関数中にループスライスされる ループを含む場合、結果的に並列実行部分が入れ子になります。このような場合、内側のループ は逐次実行されます。このようなループを含むソースプログラムは -Kparallel,instance=N を指 定して翻訳してはなりません。 51 C 言語使用手引書 「図 4.24 並列処理が入れ子になった場合」に、スライスされたループが逐次実行される例を示 します。このようなループを含むソースプログラムを -Kparallel,instance=N を指定して翻訳す ると、実行結果は保証されません。 #include <stdio.h> #define M 4000 double a[M][M]; void f1(int); void f2(int); main() { f1(M); printf("%e\n",a[0][0]); } void f1(int n) { int i; #pragma loop independent for(i=0; i<n; i++){ f2(i); } } void f2(int i) { int j; for(j=0;j<i+1; j++){ a[i][j] = 3.8; } } このループは並列実行される このループは逐次実行される 図 4.24 並列処理が入れ子になった場合 a.c のソースプログラムを以下のように翻訳した場合、実行結果は保証できません。 $ fcc -Kparallel,instance=4 a.c(誤った使い方) このような誤りを防ぐために、ループスライスされるループ内で引用している関数に、serial 指示子を以下のように指定します。 #pragma procedure serial void f2(int i) { int j; for(j=0; j<i+1; j++){ a[i][j] = 3.8; } } 逐次化 4.2.3.3.2 -Kparallel,reduction 指定時の注意 -Kparallel,reduction を指定して翻訳したとき、並列実行の結果が、逐次実行の結果と異なる ことがあります。これは、並列実行のときの演算順序が、逐次実行の演算順序と異なる場合があ るためです。 「図 4.25 リダクションによる精度差」は、 「4.2.3.1.6 リダクションによるループスライス」の 説明で使用した例です。変数 sum は、逐次実行では、配列要素 a[0] から a[9999] まで順次に加 52 第 4 章 並列化機能 算されます。並列実行では、配列要素 a[0] から a[4999] まで順次に加算した値を変数 sum1 とし て、配列要素 a[5000] から a[9999] まで加算した値を sum2 とします。そして、sum1 と sum2 を 加算した値を sum とします。 つまり、逐次実行と並列実行では、配列 A の要素の値を累計する順番が違うので、演算結果に精 度差が生じることがあります。 sum = 0; for(i=0; i<10000; i++){ sum = sum + a[i]; } sum1 = 0; for(i=0; i<5000; i++){ sum1 = sum1 + a[i]; } sum2 = 0; for(i=5000; i<10000; i++){ sum2 = sum2 + a[i]; } sum = sum + sum1 + sum2; 図 4.25 リダクションによる精度差 4.2.3.3.3 最適化制御行の使い方の注意 本処理系は、最適化指示子の使い方が誤っている場合、誤ったループスライスを行います。 disjoint 指示子、temp 指示子および independent 指示子の誤った使い方を、以下に示します。 以下のプログラムは、配列 a に対して、誤った disjoint 指示子を指定しています。ループスラ イスを行うと配列 a の定義引用順序が変わるため、誤った動作をすることがあります。 #pragma loop disjoint a for(i=1; i<10000; i++){ a[i] = a[i-1] + b[i]; } 以下のプログラムは、変数 t に対して、誤って temp 指示子を指定しています。ループの実行後、 変数 t の値は保証されないので、変数 last に期待した値が代入されないことがあります。 #pragma loop temp t for(i=0; i<1000; i++){ t = a[i] + b[i]; c[i] = t + d[i]; } last = t; 53 C 言語使用手引書 以下のプログラムは、関数 func に対して、誤って independent 指示子を指定しています。関数 func の引用によって配列 a の定義・引用の順序が変わるため、結果が正しくない場合があります。 int a[1000],b[1000]; #pragma procedure independent func main() { int i; void func(int); for(i=1; i<1000; i++){ a[i] = b[i] + 1; func(i-1); } } void func(int j) { a[j] = a[j] + 1; } 4.2.3.3.4 並列処理中の標準関数 ループスライスされたループ内で関数を引用していて、引用先の関数中にループスライスの対象 とならない標準関数を含む場合、動作は保証されません。並列実行に伴うオーバヘッドのため、 逐次処理した場合より実行性能が低下する場合があります。 4.3 OpenMP 仕様による並列化 ここでは、本処理系で提供している OpenMP 仕様による並列化について説明します。 本処理系は、OpenMP Application Program Interface Version2.5(May 2005) にもとづいて記述 されたプログラムを翻訳するコンパイラです。 OpenMP Application Program Interface Version2.5(May 2005) については、以下の URL をお読 みください。 http://www.openmp.org 4.3.1 翻訳・実行の方法 ここでは、OpenMP 仕様で記述されたソースプログラムの翻訳および実行の方法について説明し ます。 4.3.1.1 翻訳の方法 ソースプログラムの翻訳および結合編集を行うには、翻訳時オプション -KOMP を指定します。 4.3.1.1.1 OpenMP プログラムを翻訳するための翻訳時オプション ここでは、OpenMP プログラムを翻訳するための翻訳時オプションについて説明します。 -KOMP -KOMP は、OpenMP 仕様の指示子を有効にし、ソースプログラムを翻訳します。 -KOMP は、結合編集時にも指定する必要があります。-KOMP を指定して翻訳されたオブジェクト プログラムが含まれる場合は、結合編集時に -KOMP を指定する必要があります。 例: $ fcc a.c -KOMP -c $ fcc a.o -KOMP 54 第 4 章 並列化機能 4.3.1.1.2 OpenMP プログラムの最適化情報を表示するための翻訳時オプション ここでは、OpenMP プログラムの最適化情報を表示するための翻訳時オプションについて説明し ます。 -Ksrc -KOMP と -Ksrc が同時に指定された場合、OpenMP 仕様のディレクティブによって指示された実行 文に対する並列化情報の表示は、以下のようになります。 ・ 並列に実行される可能性がある文に対しては、p が表示されます。冗長に実行される文に対 しては、表示されません。for 指示構文または sections 指示構文に直接囲まれた実行文がこれ に該当します。 ・ 同時に 1 スレッドだけで実行される文に対しては、s が表示されます。master 指示構文、 single 指示構文、critical 指示構文または ordered 指示構文に直接囲まれた実行文がこれに 該当します。atomic 指示構文の直後の実行文に対しては、その全体が排他的に 1 スレッドで 実行される場合、s が表示されます。 ・ 一つの実行文の中で、並列に実行される可能性がある部分と、1 スレッドだけで実行される 部分が混在している場合、m が表示されます。 ネストした並列実行では、その実行文を囲む最も内側のパラレルリージョンに対する並列化情報 を表示します。そのパラレルリージョンがどのように呼ばれるか(並列実行中に呼ばれるか、そ れとも逐次実行中に呼ばれるか)は、表示に影響を与えません。 4.3.1.2 実行の方法 OpenMP プログラムを実行させる手続きは、逐次実行のときと同じです。 4.3.1.2.1 実行時の環境変数 FLIB_SPINWAIT 環境変数 FLIB_SPINWAIT で、同期待ち処理を調節することができます。デフォルトは unlimited です。 unlimited: 同期が獲得できるまでスピン待ちを行います。 0: スピン待ちを行わず、サスペンド待ちを行います。 <n>s:n 秒間スピン待ちし、その後サスペンド待ちに移ります。 <n>ms:n ミリ秒間スピン待ちし、その後サスペンド待ちに移ります。 ここで、<n> は 0 以上の整数。 スピン待ちとは、スレッド間で同期を待ち合うとき、CPU 時間を消費する方法で待たせる方式で す。逆に、サスペンド待ちは CPU 時間を消費せずに待たせます。スピン待ちを行う方が並列処理 のオーバヘッドが少ないため、経過時間を重視する場合には、unlimited を選択してください。 CPU 時間を重視する場合は、0 を選択してください。 FLIB_FASTOMP 環境変数 FLIB_FASTOMP に TRUE を設定することにより、利用者は高速実行時ライブラリを使用す ることができます。デフォルトでは高速実行時ライブラリは使用されません。高速実行時ライブ ラリは、以下のような特徴を持ちます。 ・ ・ ネストした並列化がないことと、スレッドが CPU に一対一に対応付けられていることを前提 とすることにより、高速化を図っています。 Parallelnavi 環境では、高速なハードウェアバリアを使用することができます。 ただし、高速実行時ライブラリを使用できるプログラムには、以下の制限があります。 ・ num_threads 節および omp_set_num_threads 関数で指定するスレッド数は、 実行時環境によっ て決まるスレッド数と一致していなければなりません。 実行時環境によって決まるスレッド数は、「4.3.1.2.3 実行時の注意事項」(Parallelnavi 環境 の場合には、「付録 F Parallelnavi」)をお読みください。 高速実行時ライブラリを使用するとき、OpenMP 仕様の環境変数と OpenMP 仕様による実行の制御 は、以下のように制限を受けます。 ・ 環境変数 OMP_NESTED と omp_set_nested 関数による設定に関わらず、ネストしたパラレルリー ジョンは常に逐次化されます。 55 C 言語使用手引書 ・ 環境変数 OMP_DYNAMIC と omp_set_dynamic 関数による設定に関わらず、スレッド数は使用可 能な CPU 数を超えることはできません。 使用可能な CPU 数については、「4.3.1.2.3 実行時の注意事項」(Parallelnavi 環境の場合には 「付録 F Parallelnavi」)をお読みください。 THREAD_STACK_SIZE(1 ≦ THREAD_STACK_SIZE ≦ 2147483647) 利用者は、環境変数 THREAD_STACK_SIZE の値として、スレッド毎のスタック領域の大きさを K バ イト単位で指定することができます。詳細については、「4.3.1.2.3 実行時の注意事項」をお読 みください。 4.3.1.2.2 OpenMP 仕様の環境変数 利用者は、以下の OpenMP 仕様の環境変数を使用することが可能です。OpenMP 仕様の環境変数の 詳細については、OpenMP 仕様書をお読みください。 OMP_SCHEDULE schedule 節に runtime を持つ、for 指示子または parallel for 指示子に対して、実行すべきス ケジュールの種類と chunk_size を指定します。 OMP_NUM_THREADS 実行中に使用するスレッドの数を指定します。 OMP_DYNAMIC 動的スレッド調整機能の有効または無効を指定します。 OMP_NESTED パラレルリージョンのネスト機能の有効または無効を指定します。 4.3.1.2.3 実行時の注意事項 本処理系の OpenMP 仕様による並列化機能を使用する場合の注意事項を、以下に示します。 実行時の変数割付け 本処理系の OpenMP 仕様による並列化機能を使用したプログラムは、関数内でローカルな変数お よび private 変数をスタック領域に割り付けます。関数内でローカルな変数および private 変数 に必要な領域が巨大な場合には、スタック領域を十分な大きさに拡張する必要があります。 プロセスのスタック領域の制限値は、limit(1) コマンドで、設定が可能です。 スレッド毎のスタック領域は、プロセスのスタック領域と同じ大きさで確保されます。ただし、 プロセスのスタック領域の制限値が、使用可能な実装メモリと仮想メモリの大きさの小さい方を スレッド数で割った値より大きい場合、本システムがスレッド毎のスタック領域の大きさを次の ように、仮定して確保します。なお、仮想メモリの大きさとは、limit(1) コマンドの仮想記憶 の最大サイズとして表示される値です。 S = ( M/T ) / 5 S:スレッド毎のスタック領域の大きさ(byte) M:実装メモリと仮想メモリの小さい方の大きさ(byte) T:スレッド数 ス レ ッ ド 毎 の ス タ ッ ク 領 域 の 大 き さ を、特 定 の 大 き さ で 確 保 し た い 場 合 に は、環 境 変 数 THREAD_STACK_SIZE を使用してください。 環境変数 THREAD_STACK_SIZE については、「4.3.1.2.1 実行時の環境変数」をお読みください。 CPU 数の上限 以下の値を、CPU 数の上限値とします。 Solaris プロセッサセットが定義されている場合 プロセッサセット内では、プロセッサセットの CPU 数 プロセッサセット外では、システムの CPU 数 Solaris プロセッサセットが定義されていない場合 システムの CPU 数 スレッド数 56 第 4 章 並列化機能 並列実行のスレッド数は、高速実行時ライブラリを使用するとき OpenMP と自動並列化で共通と なり、そうでないときそれぞれ独立に決定されます。高速実行時ライブラリの使用は、環境変数 FLIB_FASTOMP の設定によって制御することができます。詳細は、 「4.3.1.2.1 実行時の環境変数」 をお読みください。 高速実行時ライブラリを使用するとき(FLIB_FASTOMP が TRUE のとき) スレッド数は以下の優先順位で決定されます。 1.環境変数 OMP_NUM_THREADS の指定値注 2.環境変数 PARALLEL の指定値 3.Solaris プロセッサセットの CPU 数 4.1 この優先順位で決まるスレッド数が CPU 数の上限値を超えるとき、スレッド数は CPU 数の上限 値となります。 num_threads 節および omp_set_num_threads 関数によって指定する値は、ここで決まるスレッ ド数と一致していなければなりません。異なる値を指定した場合には、プログラムの実行が終 了されます。この時に、環境変数 FLIB_C_MESSAGE が存在する場合には mpc1041i-s のメッセー ジが出力されます。 高速実行時ライブラリを使用しないとき(FLIB_FASTOMP が TRUE でないとき) OpenMP のスレッド数は、以下の優先順位で決定されます。自動並列化のスレッド数は、「4.2 自動並列化」の記述に従います。 1.parallel 指示子の num_threads 節の指定値 2.omp_set_num_threads 関数の指定値 3.環境変数 OMP_NUM_THREADS の指定値 4.環境変数 PARALLEL の指定値 5.Solaris プロセッサセットの CPU 数 6.1 動的スレッド調整機構が有効な場合には、この優先順位で決まるスレッド数が CPU 数の上限値 を超えるとき、スレッド数は CPU 数の上限値になります。 動的スレッド調整機構が無効な場合、1CPU 当たりのスレッド数が 1 を超える場合には、並列 に実行されることを意図したスレッドが時分割で実行されることになります。このような場 合、スレッド間の同期処理のオーバヘッドが大きくなり、実行性能が低下することがありま す。システムによる負荷も考慮して、1CPU 当たりのスレッド数が 1 以下になるようにスレッ ド数を設定することをお勧めします。 なお、Parallelnavi 環境下で実行する場合のスレッド数については、 「付録 F Parallelnavi」を お読みください。 4.3.1.2.4 複数のスレッドからの出力情報 プログラムの実行時に同一プログラム内で複数のスレッドからエラーが検出された場合、トレー スバックマップは、スレッド単位に出力されます。したがって、パラレルリージョン内では、ス レッド数分の情報が出力されます。 4.3.2 処理系依存の仕様 OpenMP 仕様において、処理系の実現に任されている仕様については、本処理系では以下のよう に実現しています。各項目の詳細については、OpenMP 仕様書をお読みください。 メモリモデル 4 バイトを超えるか 4 バイト境界を跨ぐ変数に対して、2 つのスレッドからの書き込みが同時に 起こるとき、明示的な排他制御が行われなければ、変数の値はどちらの値にもならず不定となる ことがあります。 4 バイトを超えるか 4 バイト境界を跨ぐ変数に対して、2 つのスレッドから書き込みと読み出し が同時に起こるとき、明示的な排他制御が行われなければ、読み出される変数の値は書き込み前 の値でも書き込み後の値でもなく不定となることがあります。 注 . 結合編集時に -Kparallel が指定されているとき、環境変数 PARALLEL の指定値があれば、 その値と一致していなければなりません。一致していない場合には小さい方の値が採用 されます。この時に、環境変数 FLIB_C_MESSAGE が存在する場合には mpc1042i-w のメッ セージが出力されます。 57 C 言語使用手引書 内部制御変数 以下の環境変数またはライブラリルーチンによって設定される値は、それぞれ内部制御変数に格 納されます。内部制御変数は、全スレッドで共有されます。 ・ OMP_NUM_THREADS または omp_set_num_threads() ・ OMP_DYNAMIC または omp_set_dynamic() ・ OMP_NESTED または omp_set_nested() ・ OMP_SCHEDULE パラレルリージョンのネスト機能 本処理系の OpenMP 仕様による並列化機能では、ネスト並列化機能を実現しています。システム で使用できるスレッドの数やスタック領域などの資源が許す限り、ネストのレベルに上限はあり ません。ただし、環境変数 FLIB_FASTOMP に TRUE が設定されている場合には、ネスト並列は抑止 されます。 動的スレッド調整機能 本処理系の OpenMP 仕様による並列化機能では、動的スレッド調整機能を実現しています。この 機能の効果は、「4.3.1.2.3 実行時の注意事項」をお読みください。 デフォルトの状態では、動的スレッド調整機能は有効です。 スレッド数 スレッド数については、「4.3.1.2.3 実行時の注意事項」をお読みください。 schedule 節 本処理系の OpenMP 仕様による並列化機能では、schedule 節が省略された場合、デフォルトは "schedule(static)”となります。 環境変数 OMP_SCHEDULE 本処理系の OpenMP 仕様による並列化機能では、スケジュールタイプが runtime の for 指示子に 対して、環境変数OMP_SCHEDULEが省略された場合、 デフォルトは“schedule(static)”となります。 sections 構文 スレッドは、sections 領域に到達するか、その中の一つの section 領域の実行を終了したとき、 その順序で次の section 構文と対応付けられます。 single 構文 single 領域は、最初にその領域に到達したスレッドによって実行されます。 atomic 構文 複数の atomic 領域が同時に実行されるとき、すべてが排他的に実行されます。 実行時ライブラリルーチンと環境変数 引数に 0 以下の値を与えて omp_set_num_threads ルーチンを呼び出すと、何の効果もありませ ん。環境変数 OMP_NUM_THREADS に 0 以下の値を設定すると、1 を設定した場合と同じ効果をもち ます。これらの値として、システムがサポートするスレッド数を超える数値を設定してはなりま せん。 活動状態の parallel 領域の中で、omp_set_num_threads、omp_set_dynamic または omp_set_nested ルーチンを呼び出してはなりません。 活動状態の parallel 領域の中で、omp_get_max_threads、omp_get_dynamic および omp_set_nested ルーチンに結合するスレッドは、遭遇するスレッドです。 4.3.3 プログラミングの注意事項 ここでは、OpenMP 仕様のプログラミングにおける注意事項について説明します。 4.3.3.1 パラレルリージョンの実現 パラレルリージョンの静的範囲は、翻訳処理により、内部関数化されます。 生成された関数名は、“.OMP_ 通し番号”という名前が付加されます。 58 第 4 章 並列化機能 4.3.3.2 OpenMP プログラムの自動並列化 -KOMP と -Kparallel は、同時に指定可能です。同時に指定した場合、自動並列化されるループ は以下のように制限されます。 ・ OpenMP のパラレルリージョンの静的範囲内にあるループは、自動並列化の対象とはなりませ ん。 ・ ・ OpenMP 指示子を静的に内部に含むループは、自動並列化の対象とはなりません。 OpenMP 指示子で並列化されるループがある場合、以下のループは自動並列化の対象とはなり ません。 OpenMP 指示子で並列化されるループ自身 OpenMP 指示子で並列化されるループの内側にあるループ 4.3.4 他のマルチスレッドプログラムとの結合 OpenMP プログラム以外の、マルチスレッドプログラムのオブジェクトプログラムとの結合につ いて、制限事項を示します。 本処理系の自動並列化プログラム 本処理系で-Kparallelを指定して作成した自動並列化プログラムのオブジェクトプログラムは、 本処理系で -KOMP を指定して作成したオブジェクトプログラムと結合可能です。 4.3.5 OpenMP プログラムのデバッグ 実行可能プログラムでエラーが発生したとき、異常終了したとき、または利用者が目的とした結 果を得られないときは、その原因を追求し、ソースプログラムの修正を行う必要があります。 fdb は、マルチスレッドプログラムに対応したシンボリック・デバッガです。fdb を利用して OpenMP プログラムのデバッグが可能です。ただし、Solaris 10 OS 上でデバッグを行う場合は、 マスタスレッドのみ可能です。詳細は、fdb コマンドの man マニュアルをお読みください。 4.3.6 並列実行情報 並列実行情報は、プログラムの実行環境、プログラムが並列で実行されている割合などを示しま す。また、パラレルリージョンごとの実行時間から、並列の効果などを知ることができます。 4.3.6.1 並列実行情報として出力される情報 並列実行情報として出力される情報を、以下に示します。 ++=======================================++ || PARALLEL EXECUTION INFORMATION || ++=======================================++ +--------------------+--------------------+ | Number of CPU(s) | 2 | +--------------------+--------------------+ | Number of thread(s) | +--------------------+--------------------+-------------------+-------------------+ | Automatic | | | | | Parallelization | 2 | OpenMP | 2 | +--------------------+--------------------+-------------------+-------------------+ | Execution mode information | +--------------------+--------------------+-------------------+-------------------+ | FLIB_FASTOMP | FALSE | FLIB_SPINWAIT | SPIN MODE | +--------------------+--------------------+-------------------+-------------------+ | Memory Information | +--------------------+--------------------+-------------------+-------------------+ | Largepage | disable | Thread stack size | 8388608 | +--------------------+--------------------+-------------------+-------------------+ |Barrier Information | +--------------------+--------------------+ | Barrier kind | Softbarrier | 59 C 言語使用手引書 +--------------------+--------------------+ 環境変数 FLIB_PARALLEL_INFO に 1 を指定した場合、以下の情報が出力されます。 Number of CPU(s) 使用可能な CPU 数。 Number of thread(s) 自動並列および OpenMP で使用したスレッド数。 Execution mode information 環境変数 FLIB_FASTOMP( 高速ライブラリ使用の有無 ) の設定、FLIB_SPINWAIT( 待機スレッ ドの処理が SPIN MODE であるか、SUSPEND MODE であるか ) の設定。 Memory Information ラージページ機能の使用の有無、および全スレッドで獲得したスレッドスタックの総量。 Barrier Information 使用されたバリア種別。 環境変数 FLIB_PARALLEL_INFO に 2 を指定した場合、1 で出力される情報に加えて、以下の情報 が出力されます。 Barrier number of times 自動並列および OpenMP のバリア同期回数。 The parallelization number of times 自動並列および OpenMP で並列化された回数。 The percentage of parallel region for master thread プログラムが並列で実行している割合。 " マスタスレッドのパラレルリージョン実行時間 ÷ real time"。 The percentage of parallel region for all thread 逐次プログラムからの並列化率の目安。 " 全スレッドのパラレルリージョン実行時間の合計 ÷ ( 全スレッドのパラレルリージョン 実行時間の合計 + マスタスレッドの逐次リージョン実行時間 )"。 Parallel region information of Automatic Parallelization 自動並列化されたパラレルリージョンの手続き名、アドレス、実行時間およびパラレルリー ジョンのコスト分布一覧。ただし、Fortran と結合した場合、アドレスは表示されません。 Parallel region information of OpenMP OpenMP で並列化されたパラレルリージョンの手続き名、アドレス、実行時間およびパラレ ルリージョンのコスト分布一覧。ただし、Fortran と結合した場合、アドレスは表示されま せん。(OpenMP のネストされた並列実行は含みません。) 60 第 5 章 出力情報 ここでは、C 言語で記述されたプログラムの翻訳および実行において、本処理系が出力する情報 について説明します。 5.1 翻訳時情報 ここでは、C 言語で記述されたプログラムの翻訳において、本処理系が出力する情報について説 明します。 5.1.1 ヘッダ 翻訳時オプション -Ksrc または -Ksta のうち少なくとも一つが指定された場合、翻訳時に出力す る各情報に対して「図 5.1 ヘッダの出力形式」のようにヘッダを出力します。 Fujitsu C/C++ Version バージョン 日付 バージョン:コンパイラのバージョンを出力します。 日付:翻訳した日を asctime 関数の形式で出力します。 図 5.1 ヘッダの出力形式 5.1.2 ソースリスト ソースリストを標準出力ファイルに出力することができます。 並列翻訳した場合、以下のオプションに従って、ソースリスト上に並列化表示記号が付加されて 出力されます。 ・ -Ksrc 並列化表示ソースリストを出力します。 ・ 省略時 並列化表示ソースリストを出力しません。 並列化表示ソースリストの例を「図 5.2 並列化表示の出力例」に示します。この例では、7 行目 の for 文に含まれる文が並列化されたことを示しています。 61 C 言語使用手引書 Compilation information Current directory : ディレクトリ名 Source file : ソース名 (line-no.)(optimize) 1 #include <stdio.h> 2 float sub(int i); 3 int main(){ 4 int i; 5 float a[1000]; 6 7 p for(i=0; i<1000; i++){ 8 p a[i] = i; 9 p } 10 11 printf("%lf \n", a[0]); 12 13 s for(i=0; i<1000; i++){ 14 s a[i] = sub(i); 15 s } 16 17 printf("%lf \n", a[0]); 18 } 19 20 float sub(int j){ 21 return (float)j; 22 } 図 5.2 並列化表示の出力例 並列化表示ソースリストで、並列化および最適化の表示は、行位置と文の間に次の記号で示され ます。 並列化の表示記号 並列化の表示記号は、次の条件で出力します。 ・ for 文、while 文、do-while 文または if-goto 文のループ制御文のある行では、ループ制御 文に対する表示記号を出力します。 ・ 複数のループ制御文がある行では、一番左にあるループ制御文に対する表示記号を出力しま す。 並列化の表示記号には、以下に示すループ制御文に対する表示記号とループ制御文以外の文に対 する表示記号があります。 for 文、while 文または do-while 文に対する表示記号 p : 並列化されたことを示します。 m : 並列化された部分とされなかった部分があることを示します。 s : 並列化されなかったことを示します。 空白 : 並列化対象ループでないことを示します。 for 文、while 文または do-while 文以外に対する表示記号 p : 並列化されたことを示します。 ただし、for 文、while 文または do-while 文に対する表示記号が s の場合、コンパイ ラは並列化効果が得られないと判断し、並列化を行いませんが、並列化可能であった ことを意味します。 m : 並列化された部分とされなかった部分があることを示します。 ただし、for 文、while 文または do-while 文に対する表示記号が s の場合、コンパイ 62 第 5 章 出力情報 ラは並列化効果が得られないと判断し、並列化を行いませんが、並列化可能であった 部分と不可能であった部分があったことを意味します。 s : 並列化されなかったことを示します。 空白 : 並列化対象ループでないことを示します。 最適化の表示記号 最適化の表示記号には、以下に示す表示記号があります。 u : ループ・アンローリングされたことを示します。 i : 関数呼出しがその位置にインライン展開されたことを示します。 ループ・アンローリングによって展開された文と関数呼出しがインライン展開された 文が同一の行にある場合、"u" を表示します。 ループ・アンローリングの出力例を「図 5.3 ループ・アンローリングの出力例」に示します。 この例では、行番号 7 のループに含まれる文がループ・アンローリングされています。 (line-no.)(optimize) ... 7 p u for(i=0; i<1000; i++){ 8 p u a[i] = i; 9 p } 図 5.3 ループ・アンローリングの出力例 5.1.3 並列化メッセージ 並列化メッセージは、並列化できなかった原因、またはどのように並列化および最適化されたか を示します。 -Kpmsg を指定することで、並列化メッセージを標準エラー出力に出力することができます。 「図 5.2 並列化表示の出力例」で使用したプログラムでは、-Kparallel を指定した場合、 「図 5.4 並列化メッセージの出力例」に示すメッセージが出力されます。 Parallelization messages "a.c", line 7: このループはループ変数 i で並列化されました。 "a.c", line 14: ループ内に自動並列化の制約となる手続引用が存在します。 図 5.4 並列化メッセージの出力例 5.1.4 統計情報 以下のオプションにより、統計情報を標準出力ファイルに出力することができます。 ・ -Ksta 統計情報を出力します。 ・ 省略時 統計情報を出力しません。 統計情報で表示するのは、有効な最適化関連オプションだけです。したがって、表示されていな い最適化関連オプションは無効であることを意味します。 5.1.4.1 表示形式 プログラム単位の統計情報を「図 5.5 統計情報の出力形式」の形式で出力します。 Statistics information Options : 有効な最適化関連オプションの一覧 図 5.5 統計情報の出力形式 63 C 言語使用手引書 -Ksta と同時に -Kcrossfile を指定した場合は、すべてのプログラム単位の統計情報を出力した 後に、クロスファイル最適化の統計情報を「図 5.6 クロスファイル最適化の統計情報」の形式 で1回だけ出力します。 Crossfile statistics information Options : 有効なクロスファイル最適化オプションの一覧 図 5.6 クロスファイル最適化の統計情報 5.1.4.2 表示対象外のオプション 統計情報では、最適化関連オプションを表示対象としています。 ld 関連オプションなどは表示対象外です。 ・ 表示対象外のオプション -# / -### / -A- / -Aname[(tokens)] / -Bc / -C / -c / -dc / -Dname[=tokens] / -E / -G / -H / -Idir / -Ldir / -lname / -opathname / -P / -Rdir / -S / -Uname / -Wtool,arg1[,arg2] / -Yitem,dir / -V 5.1.4.3 コンパイラが解釈して表示するオプション 以下のオプションは、統計情報にそのままでは表示されません。ご注意ください。 -Keopt : -Keval と -Kpreex に分解して表示 -KGREG : -KGREG_APPLI と -KGREG_SYSTEM に分解して表示 -Kfast : 誘導されるオプションで表示 -Kfast_GP[={0|1|2}] : 誘導されるオプションで表示 -Kfast_GP2[={0|1|2|3}] : 誘導されるオプションで表示 -Kfast_VI[={0|1|2|3}] : 誘導されるオプションで表示 -KV8PFMADD : -KV8PLUS と -KFMADD に分解して表示 -KV9FMADD : -KV9 と -KFMADD に分解して表示 5.2 実行時情報 ここでは、C 言語で記述されたプログラムの実行において、本処理系が出力する情報について説 明します。 5.2.1 トレースバック情報 環境変数 MPCL に trace が指定されており、ユーザプログラムの並列実行時にエラーが発生した 場合、トレースバックマップを標準エラー出力へ出力します。この機能により、主プログラムか らエラーが発生したプログラム単位までの呼出し関係を知ることができます。 主プログラムからエラーが発生したプログラム単位までの呼出し関係を、 「図 5.7 トレースバッ クマップの出力形式」の形式で出力します。なお、標準関数または数学関数でエラーが発生した 場合、標準関数または数学関数を呼び出したプログラム名からの呼出し関係が表示されることが あります。 The program was terminated abnormally with signal SIG. signal identifier = SIG_ID error occurs at f1 line s1 loc xxxxxxxx offset yyyyyyyy f1 at loc xxxxxxxx called from loc xxxxxxxx in f2 f2 at loc xxxxxxxx called from loc xxxxxxxx in f3 f3 at loc xxxxxxxx called from loc xxxxxxxx in main main at loc xxxxxxxx called from o.s. SIG SIG_ID f1 line s2 line s2 : シグナル : 詳細コード : エラーが発生したプログラム単位の入り口名または組込み関数名 64 第 5 章 出力情報 fn : fn-1(n >1) を呼び出したプログラム単位の入り口名または組込み関数名 xxxxxxxx : エラーが発生した文の絶対番地 (16 進数表示 ) yyyyyyyy : エラーが発生した文のプログラム単位の先頭からの相対番地 (16 進数表示 ) s1 s2 組込み関数でエラーが発生した場合出力されません。 : エラーが発生した文の文番号 ただし、標準関数または数学関数でエラーが発生した場合出力されません。 : 各関数を呼び出している文の文番号 ただし、-Kline が有効でない場合出力されません。 図 5.7 トレースバックマップの出力形式 5.2.2 高速数学関数のエラー 高速数学関数でエラーが発生した場合、各関数で定義されている値が復帰値として返されます。 また、エラー番号に対応するエラー値が設定され、エラーメッセージが出力されます。 高速数学関数は、エラーが発生すると必ず matherr 関数を呼び出します。したがって、利用者 は、プログラム中に matherr という名前の関数を含めることによって、エラーの扱いを変更する ことができます。matherr のインタフェースについては、「図 5.8 高速数学関数エラーにおける 処置例」をお読みください。 数学関数のエラー条件、エラー発生時の復帰値、エラー番号に設定される値、matherr 関数に渡 されるエラータイプ、およびエラーメッセージの出力の有無 ( エラーメッセージが出力される場 合、そのメーセージの種類 ) を「表 5.1 高速数学関数のエラー処理」に示します。 エラー番号に設定される値については、"man intro(2)" をお読みください。エラータイプにつ いては、"man matherr(3M)" をお読みください。 表 5.1 高速数学関数のエラー処理 復帰値 関数名 エラー番号 エラー条件 メッセージ エラータイプ -Xa -Xc -Xt -Xa -Xc -Xt -Xa -Xc -Xt sin(x) |x| ≧ 3.53e+15 √ 0.5 ERANGE TLOSS TLOSS cos(x) |x| ≧ 3.53e+15 √ 0.5 ERANGE TLOSS TLOSS tan(x) |x| ≧ 3.53e+15 1.0 ERANGE TLOSS TLOSS x が特異点 HUGE ERANGE SING - asin(x) |x| > 1.0 0.0 EDOM DOMAIN 注1 - 注2 acos(x) |x| > 1.0 0.0 EDOM DOMAIN 注1 - 注2 atan2(x,y) x = y = 0.0 0.0 EDOM DOMAIN 注1 - 注2 sinh(x) x ≦ -709.782 -HUGE_VAL -HUGE ERANGE OVERFLOW 注1 - 注1 x ≧ 709.782 HUGE_VAL HUGE ERANGE OVERFLOW 注1 - 注1 cosh(x) |x| ≧ 709.782 -HUGE_VAL -HUGE ERANGE OVERFLOW 注1 - 注1 exp(x) x ≦ -709.782 0.0 ERANGE OVERFLOW 注1 - 注1 x ≧ 709.782 HUGE_VAL HUGE ERANGE OVERFLOW 注1 - 注1 x = 0.0 -HUGE_VAL -HUGE EDOM 注1 - 注3 x < 0.0 -HUGE_VAL -HUGE EDOM 注1 - 注2 log10(x) ERANGE EDOM DOMAIN DOMAIN SING 65 C 言語使用手引書 表 5.1 高速数学関数のエラー処理 復帰値 関数名 gamma(x) lgamma(x) メッセージ エラータイプ -Xa pow(x,y) エラー番号 エラー条件 -Xc x = 0.0, y < 0.0 -HUGE_VAL x = 0.0, y = 0.0 -Xt 0.0 -Xa -Xc -Xt -Xa -Xc -Xt EDOM DOMAIN 注1 - 注2 0.0 EDOM DOMAIN 注1 - 注2 x < 0.0, |y| ≦ MAXLONG 0.0 EDOM DOMAIN 注1 - 注2 アンダフロー 0.0 ERANGE UNDERFLOW 注1 - 注2 オーバフロー ± HUGE_VAL ± HUGE ERANGE OVERFLOW 注1 - 注2 x ≦ 0.0 HUGE_VAL HUGE EDOM SING 注1 - 注3 x ≧ 171.6243 HUGE_VAL HUGE ERANGE OVERFLOW 注1 - 注1 x ≦ 0.0 HUGE_VAL HUGE EDOM SING 注1 - 注3 x≧ HUGE_VAL HUGE ERANGE OVERFLOW 注1 - 注1 2.556348e+305 hypot(x,y) オーバフロー HUGE_VAL ERANGE OVERFLOW - - - scalb(x,y) アンダフロー 0.0 ERANGE UNDERFLOW 注1 - 注1 オーバフロー ± HUGE_VAL ± HUGE ERANGE OVERFLOW 注1 - 注1 x = 0.0 -HUGE_VAL -HUGE EDOM 注1 - 注3 x < 0.0 -HUGE_VAL -HUGE EDOM 注1 - 注2 x = -1.0 -HUGE_VAL EDOM 注1 - 注3 x < -1.0 -HUGE_VAL EDOM 注1 - 注2 log(x) loglp(x) ERANGE EDOM DOMAIN SING DOMAIN ERANGE EDOM DOMAIN DOMAIN SING 注1:エラーメッセージは出力されません。ただし、利用者定義の matherr 関数を作成するこ とにより、エラーメッセージを出力可能です。 注2:DOMAIN のエラーメッセージが出力されます。また、利用者定義の matherr 関数を作成 することにより、エラーメッセージを出力可能です。 注3:SING のエラーメッセージが出力されます。また、利用者定義の matherr 関数を作成す ることにより、エラーメッセージを出力可能です。 「図 5.8 高速数学関数エラーにおける処置例」では、asin 関数でエラーが発生したとき、復帰値 として 0.0 を返すように matherr 関数を作成しています。 66 第 5 章 出力情報 #include <math.h> #include <string.h> main() { double a[10] = {0.0,0.2,0.4,0.8,1.0,1.2,0.1,0.3,0.5,0.7 }; double b[10] ; int i; for(i=0;i<10;i++) b[i] = asin(a[i]); } int matherr(struct exception *p){ if(p->type==DOMAIN && strcmp(p->name,"asin")==0) { p->retval=0.0; return(1); }else{ return(0); } } 図 5.8 高速数学関数エラーにおける処置例 67 C 言語使用手引書 68 第 6 章 言語仕様 本章では、C 言語規格の言語仕様を元に、本処理系で拡張した言語仕様について説明します。 説明に入る前に、本章で使用する構文記法を説明します。構文要素(非終端記号)は、英数字を 含む日本語で示し、リテラル語および文字集合の要素(終端記号)は英数字および特殊記号で示 します。非終端記号に続くコロン (:) は、その後に非終端記号の定義があることを示します。選 択可能な定義は、" 次のいずれか " と前置きしている場合を除き、別々の行に表示します。省略 可能な記号は、添字 "opt" で示します。したがって、{ 式 opt} は、中括弧が省略可能な式を囲ん でいることを示します。 6.1 long long 型 signed char、 short int、 int および long int の 4 つの符号付き整数型に加えて、long long int 型が追加されています。 ■接尾語 整数接尾語: 符号なし接尾語 長語接尾語 opt 長語接尾語 符号なし接尾語 opt 符号なし接尾語 長長語接尾語 opt 長長語接尾語 符号なし接尾語 opt 符号なし接尾語: 以下のいずれか u U 長長語接尾語: 長語接尾語 長語接尾語 長語接尾語: 以下のいずれか l L ■意味規則 整数定数の型は、次の並びのうちでその値を表現できる最初の型とします。 接尾語なしの 10 進数 : int, long int, unsigned long int, long long int, unsigned long long int 接尾語なしの 8 進数または 16 進数 : int, unsigned int, long int, unsigned long int, long long int, unsigned long long int 文字 u または U が接尾語として付く場合 : unsigned int, unsigned long int, unsigned long long int 文字 l または L が接尾語として付く場合 : long int, unsigned long int, long long int, unsigned long long int 文字 u または U、および文字 l または L の両方が接尾語として付く場合 : unsigned long int, unsigned long long int 文字 l または L、および文字 l または L の両方が接尾語として付く場合 : long long int, unsigned long long int ■型指定子としての制約 型指定子の各並びは、以下の組のいずれか一つに属していなければなりません。一つの項目に二 つ以上の組がある場合は、コンマで区切っています。型指定子はどんな順序で記述してもよく、 また、ほかの宣言指定子と混在して記述することもできます。 ・ long long, signed long long, long long int, signed long long int ・ unsigned long long, unsigned long long int 69 C 言語使用手引書 記述例 long long int lli=10LL; unsigned long long int ulli=10ULL; 6.2 pragma 指令 pragma 指令は、処理系への動作を指示します。 ■意味 #pragma 前処理字句列 opt 改行 処理系に、以下の方法で動作することを指示します。 #pragma ident 文字列リテラル 改行 文字列リテラル内の文字列を、オブジェクトプログラムの中に注釈として付加することを、処理 系に指示します。これは、#ident 指令と同じ意味を持つ #pragma 指令です。一般に、オブジェ クトプログラム中にバージョン管理情報を付加するために利用します。 #pragma weak 識別子 改行 識別子をウィーク・シンボルとして定義することを、処理系に指示します。 #pragma weak 識別子 1= 識別子 2 改行 識別子 1 を識別子 2 と同じ値および型を持つウィーク・シンボルとして定義することを、処理系 に指示します。 #pragma unknown_control_flow ( 識別子の並び ) 改行 上記の形式の前処理指令は、識別子で指定された関数が処理系で認識できない制御の流れを持つ ことを、処理系に指示します。 #pragma int_to_unsigned 識別子 改行 識別子で指定された関数が旧 C 言語では返却値が型 int を持っていることを、処理系に指示しま す。ただし、指定される関数の返却値は、型 unsigned でなければなりません。 #pragma redefine_extname < 旧関数名 > < 新関数名 > 改行 オブジェクトコードの中の < 旧関数名 > である外部参照名をすべて < 新関数名 > に置き換えるこ とを、処理系に指示します。 6.3 ident 指令 ident 指令は、C プログラムに注釈を付加することを指示します。 ■意味 # ident 文字列リテラル 改行 指定した文字列リテラルがオブジェクトプログラムの ".comment セクション " に置かれます。 ".comment セクション " は、プログラムの実行時に記憶域にローディングされないセクションで す。 # ident 前処理字句 改行 指定した前処理字句が通常のテキストとして処理され、現在マクロ名として定義している各識別 子は、その置換えの並びで置き換えられます。置換え後のすべての #ident 指令は、前の形式と 一致しなければなりません。 6.4 assert 指令 assert 指令は、プレディケート名を定義し、アサーション字句をプレディケート名に関連付け ることを指示します。 ■意味 # assert 識別子 アサーション指定子 opt 改行 #assert 指令に続く識別子がプレディケート名であると定義します。また、プレディケート名に 続くアサーション指定子の識別子の並びがアサーション字句であると定義します。 70 第 6 章 言語仕様 #assert 指令は、プレディケート名を定義し、アサーション字句をプレディケート名に関連付け ます。 識別子の並びのない #assert 指令は、対応する #unassert 指令を記述しているところまで有効で す。 # 演算式の各識別子 # 演算式の各識別子は、#assert 指令で指定したプレディケート名とアサーション字句にそれぞ れ相当します。アサーション字句がプレディケート名に関連付けられている場合だけ 1 となり、 その他の場合、0 となります。例えば、#system(unix) は 1 です。 以下のアサーションは、処理系によってあらかじめ定義されています ( 既定義アサーション )。 # assert system(unix) # assert machine(sparc) # assert cpu(sparc) ■記述例 # assert langlevel(ansi) # assert langlevel(sysv) 上記の指令は、プレディケート名 langlevel を定義し、アサーション字句 ansi と sysv をプレ ディケート名に関連付けます。 # assert float 上記の指令は、プレディケート名 float を定義します。アサーション字句は持ちません。 6.5 unassert 指令 unassert 指令は、プレディケート名とアサーション字句の関連付けを取り消すことを指示しま す。 ■意味 # unassert 識別子 アサーション指定子 opt 改行 アサーション字句の関連付けを取り消します。識別子の並び ( アサーション指定子 ) がない #unassert 指令は、プレディケート名のアサーション字句の関連付けをすべて取り消します。 指定した識別子がプレディケート名でない場合、#unassert 指令は無視されます。また、関連付 けていないアサーション字句を指定した場合も、#unassert 指令は無視されます。 6.6 あらかじめ定義されたマクロ名 あらかじめ定義されたマクロ名については、「2.2.2.4 言語仕様関連オプション」をお読みくだ さい。 71 72 付録 A 処理系定義の動作 付録 A 処理系定義の動作 ここでは、正しいプログラム構成要素および正しいデータに関する動作のうち、本処理系の特徴 に依存した項目について説明します。 以下に、処理系定義の項目と、その項目に引き続いて本処理系の動作を説明しています。 A.1 翻訳 ■どのような方法で診断メッセージを識別するか。 診断メッセージは、標準エラー出力ファイルに出力されます。 診断メッセージの形式は、以下のとおりです。 "filename" line nn: メッセージ本体 "filename": エラーが起こったファイル名 nn: エラーが起こった行番号 A.2 環境 ■ main 関数への実引数の意味。 以下に、ホスト環境が与える値を示します。 int main(int argc, char *argv[]) {/*...*/} argc : argv : 実引数の個数 実引数となる文字列へのポインタ配列 (argv[0] はプログラム名または空文字列 ) ■対話型装置がどのようなもので構成されるか。 コンソールおよび端末などの表示装置で構成されます。 A.3 識別子 ■外部結合でない識別子において(31 以上の)意味がある先頭の文字数。 4096 文字までです。 ■外部結合である識別子において(6 以上の)意味がある先頭の文字数。 4096 文字までです。 ■外部結合である識別子において英小文字と英大文字の区別に意味があるか否か。 英小文字と英大文字を区別します。 A.4 文字 ■ソースおよび実行文字集合の要素で、この規格で明示的に規定しているもの以外 の要素。 ソース文字集合および実行文字集合の要素の値は、EUC コードの値です。 ただし、環境変数 LANG がシフト JIS の場合、ソース文字集合および実行文字集合の要素の値は、 シフト JIS コードの値となります。 ■多バイト文字のコード化のために使用されるシフト状態。 シフトコードに依存した表現形式ではありません。 73 C 言語使用手引書 ■実行文字集合の文字におけるビット数。 1バイト中のビット数は、8 です。 ■(文字定数内および文字列リテラル内の)ソース文字集合の要素と実行文字集合 の要素との対応付け。 ソース文字集合の要素と実行文字集合の要素との対応付けは同じです。 ■基本実行文字集合で表現できない文字もしくは拡張表記を含む単純文字定数の 値、またはワイド文字定数に対しては拡張文字集合で表現できない文字もしく は拡張表記を含むワイド文字定数の値。 規定されていない拡張表記が文字定数または文字列リテラルの中に現れている場合、¥だけが無 視されて単なる文字として扱われます。 ■ 2 文字以上の文字を含む単純文字定数または 2 文字以上の多バイト文字を含むワ イド文字定数の値。 単純文字定数として、二つ以上の文字を記述した場合、その値は、左から 4 文字取り出されて、 その文字が 'C1C2...Cn'(2 ≦ n ≦ 5) の場合、以下の値を取ります。 n-1 Σ256k-1 × ('Ck'&255) + 256n-1 × 'Cn',2 ≦ n ≦ 4 k=1 5 文字以上の場合は、5 文字以降が無視されます。 ワイド文字定数として二つ以上の多バイト文字を記述した場合、左から 1 文字取り出されて、そ の値は対応するコードの値になります。2 文字以上の場合には、2 文字以降が無視されます。 記述例 表現 '\x123' の値 : '\x23' 表現 '\0223' の値 : '\022' + '3' × 256 表現 L'\1234' の値 : L'\123' ■ワイド文字定数に対して、多バイト文字を対応するワイド文字(コード)に変換 するために使用されるロケール。 環境変数 LANG で定義されます。 ■ " 単なる " char が signed char と同じ値の範囲を持つか、 unsigned char と同 じ値の範囲を持つか。 signed char と同じ値の範囲を持ちます。 A.5 整数 ■整数のさまざまな型の表現方法および値の集合。 「付図 A.1 汎整数型の表現および値」に、汎整数型の表現および値を示します。 0 1 n-1 I S S: I: 符号 (0 のとき正、1 のとき負 ) 整数部 n–1 x = –s× 2n – 1 + Σ ik × 2 n–k–1 k = 1 74 付録 A 処理系定義の動作 付図 A.1 汎整数型の表現および値 文字集合で列挙した要求されるソース文字集合の任意の要素以外の量を、char 型オブジェクト に格納した場合、その動作は、量数の下位バイトが格納され、その値は符号付き整数として扱わ れます。 ■整数をより短い符号付き整数に変換した結果、または符号なし整数を長さの等し い符号付き整数に変換した結果で、値が表現できない場合の変換結果。 その値は、変換される型のビット数のビットパターンを 2 の補数表現として解釈した値となり ます。 ■符号付き整数に対してビット単位の演算を行った結果。 ビットパターンを 2 の補数表現で解釈した値となります。 ■整数除算における剰余の符号。 整数同士の演算で結果が割り切れない場合、両オペランドが正の値であれば、/ 演算子の結果 は、商の真の値より小さい最大の整数となり、% 演算子の結果は正となります。 いずれか一方のオペランドが負の値の場合、/ 演算子の結果は、商の真の値より大きい最小の整 数となります。また、% 演算子の結果の符号は、被除数の符号と同じになります。 両オペランドが負の値の場合、/ 演算子の結果は、商の真の値より小さい最大の整数となり、 % 演算子の結果の符号は、被除数の符号と同じになります。 ■負の値をもつ符号付き汎整数型の右シフトの結果。 E1>>E2 の結果は、E1 を E2 ビット右にシフトしたものです。 E1 が符号付きで負の値を持つ場合、結果は以下に示す式を計算した値となります。 E1/2E2 - 1 + (E1%2E2 == 0) A.6 浮動小数点数 ■浮動小数点数のさまざまな型の表現方法および値の集合。 「付図 A.2 浮動小数点型の表現および値」に、浮動小数点型の表現および値を示します。 IEEE754 準拠形式 ( 指数部表現の基底が 2 の場合 ) float 型 0 1 S 8 9 E 31 M S: 符号 (0 のとき正、1 のとき負 ) E: 指数部 M: 仮数部 s x = ( – 1 ) × ( 1 + m ⁄ 2 23 ) × 2 e – 127 75 C 言語使用手引書 double 型 0 1 S 11 12 E 63 M S: 符号 (0 のとき正、1 のとき負 ) E: 指数部 M: 仮数部 x = ( – 1 ) s × ( 1 + m ⁄ 2 52 ) × 2 e – 1023 long double 型 0 1 S 15 16 127 M E S: 符号 (0 のとき正、1 のとき負 ) E: 指数部 M: 仮数部 x = ( – 1 ) s × ( 1 + m ⁄ 2 112 ) × 2 e – 16383 付図 A.2 浮動小数点型の表現および値 ■汎整数の値を元の値に正確に表現することができない浮動小数点数に変換する 場合の切り捨ての方向。 そのときのFLT_ROUNDSに従って、丸めが行われます。FLT_ROUNDSの初期値は1(最も近傍へ)です。 ■浮動小数点数をより狭い浮動小数点数に変換する場合の切り捨てまたは丸めの 方向。 そのときのFLT_ROUNDSに従って、丸めが行われます。FLT_ROUNDSの初期値は1(最も近傍へ)です。 A.7 配列とポインタ ■配列の大きさの最大値を保持するために必要な整数の型。すなわち、sizeof 演 算子の型 size_t。 size_t の型は、unsigned int 型として扱います。 ■ポインタを整数へキャストした結果およびその逆の場合の結果。 ポインタは、整数型に変換できます。要求されるサイズは、unsigned int 型です。結果の値は、 unsigned int 型 (-KV9 が有効な場合、unsigned long 型)の内部表現がポインタの内部表現と一 致する場合の値です ( 変換において、ビットパターンは変換しません )。 76 付録 A 処理系定義の動作 任意の整数は、ポインタに変換できます。結果の値は、unsigned int 型に変換した後の内部表 現と一致する内部表現を持つ変換後の型の値となります ( 変換において、ビットパターンは変換 しません )。 ■同じ配列内の、二つの要素へのポインタ間の差を保持するために必要な整数の 型、すなわち ptrdiff_t の型。 ptrdiff_t の型は、int 型 (-KV9 が有効な場合、long 型)です。 A.8 レジスタ ■ register 記憶域クラス指定子を使用することによって、実際にオブジェクトを レジスタに置くことができる範囲。 この指定が効果的である範囲は、レジスタに格納されるオブジェクトの型が算術型(long double 型は含まれない ) とポインタで、レジスタには、register の指定に関係なく使用状況に応じて、 効果の高いオブジェクトから順に割り当てられる場合です。 A.9 構造体、共用体、列挙型およびビットフィールド ■共用体オブジェクトのメンバを異なる型のメンバを用いてアクセスする場合。 その値は、参照したメンバの型で評価された値となります。 ■構造体のメンバの詰め物および境界調整。 ある処理系によって書かれたバイナリデータを他の処理系で読まない限り、問題とはなりませ ん。 「付表 A.1 算術型の大きさと境界整列値」で示すように、型に適した境界に整列している最 も小さなオフセットに割り付けられます。単位はバイトです。 付表 A.1 算術型の大きさと境界整列値 型 大きさ 境界整列値 char 1 1 signed char 1 1 unsigned char 1 1 signed short int 2 2 unsigned short int 2 2 signed int 4 4 unsigned int 4 4 signed long int 4注 4注 unsigned long int 4注 4注 signed long long int 8 8 unsigned long long int 8 8 float 4 4 double 8 8 long double 16 8 注 . -KV9 が有効な場合、unsigned long int および signed long int の大きさ、境界整列値は 8 になります。 77 C 言語使用手引書 ■ " 単なる " int 型のビットフィールドが、signed int のビットフィールドとし て扱われるか、unsigned int のビットフィールドとして扱われるか。 unsigned int として扱われます。 ■単位内のビットフィールドの割り付け順序。 単位内のビットは、指定した型の下位ビットから順に割り当てられます。 ■ビットフィールドを記憶域単位の境界にまたがって割り付けるか否か。 ビットフィールドは、それを保持するのに十分な大きさの最も小さいアドレスの記憶単位に割り 当てられます。十分な領域が残っている場合、構造体内のビットフィールドの直後にある別の ビットフィールドは、同じ単位の隣接したビットに詰め込まれます。十分な領域がない場合、合 わないビットフィールドは、隣接した単位の境界をまたがって割り当てられないで、次の単位に 詰め込まれます。 ■列挙型の値を表現するために選択される整数型。 列挙型の値を表現する型は、int 型です。 A.10 修飾子 ■ volatile 修飾型のオブジェクトにアクセスする構成要素。 volatile 宣言は、メモリに割り付けられた入出力ポートに対応するオブジェクト、または非同 期割り込み機能により、アクセスされるオブジェクトを記述するために使用できます。このよう に宣言したオブジェクトの動作は、処理系による " 最適化 "、または式の評価規則により許され ている範囲外の評価順序の変更を受けることはありません。 A.11 宣言子 ■算術型、構造体型または共用体型を修飾する宣言子の最大数。 特に制限ありません(記憶域の大きさによる)。 A.12 文 ■ switch 文における case 値の最大数。 特に制限ありません(記憶域の大きさによる)。 A.13 前処理指令 ■条件付き取り込みを制御する定数式中の単一文字からなる文字定数の値が実行 文字集合中の同じ文字定数の値に一致するか否か。このような文字定数が負の 値をもつことがあるか否か。 一致します。また、単一の文字からなる文字定数は、基本文字集合は負の値を持ちません。その 他の値は負の値となることがあります。 ■取込み可能なソースファイルを探すための方法。 「2.2.2 翻訳時オプションの意味」の -I オプションの説明をお読みください。 ■取込み可能なソースファイルに対する " で囲まれた名前の探索。 「2.2.2 翻訳時オプションの意味」の -I オプションの説明をお読みください。 ■ソースファイル名と文字列との対応付け。 アルファベットの大文字と小文字は区別されます。 ■認識される #pragma 指令の動作。 「6.2 pragma 指令」の説明をお読みください。 78 付録 A 処理系定義の動作 ■翻訳日付および翻訳時刻がそれぞれ有効でない場合における _ _ DATE_ _ および _ _ TIME_ _ の定義。 asctime 関数で生成されるものと同じです。 A.14 ライブラリ関数 ライブラリ関数の処理系定義の動作については、システム付属のリファレンスマニュアル、また は man コマンドの説明をお読みください。 A.15 OpenMP 仕様 OpenMP 仕様の処理系定義の動作については、「4.3.2 処理系依存の仕様」をお読みください。 79 C 言語使用手引書 80 付録 B 翻訳限界 「付表 B.1 翻訳限界」に、本処理系における翻訳限界を示します。 付表 B.1 翻訳限界 項目 複合文、繰返し文および選択文の入れ子のレベル数 C 言語規格 (各値以上) 本処理系の値 127 制限なし (記憶域の大きさによる) 条件組込みにおける入れ子のレベル数 63 制限なし (記憶域の大きさによる) 宣言内の一つの算術型、構造体型、共用体型または不完 全型を修飾する(任意の組合せの ) ポインタ、配列およ び関数宣言子の数 12 制限なし (記憶域の大きさによる) 一つの完全宣言子の中の括弧で囲んだ入れ子の宣言子数 63 制限なし (記憶域の大きさによる) 一つの完全式の中の括弧で囲んだ入れ子の式数 63 制限なし (記憶域の大きさによる) 内部結合として宣言した識別子、またはマクロ名の有効 先頭文字数 63 4096 外部結合として宣言した識別子の有効先頭文字数 31 4096 一つの翻訳単位の中の外部結合として宣言した識別子の 数 4095 制限なし (記憶域の大きさによる) 一つのブロックの中で宣言されるブロック範囲を持つ識 別子の数 511 制限なし (記憶域の大きさによる) 一つの翻訳単位の中で同時に定義されるマクロ識別子の 数 4095 制限なし (記憶域の大きさによる) 一つの関数定義の中の仮引数の数 127 制限なし (記憶域の大きさによる) 一つの関数呼出しの中の実引数の数 127 制限なし (記憶域の大きさによる) 一つのマクロ定義の中の仮引数の数 127 制限なし (記憶域の大きさによる) 一つのマクロ呼出しの中の仮引数の数 127 制限なし (記憶域の大きさによる) 一つの論理ソース行の中の文字数 4095 制限なし (記憶域の大きさによる) ( 連結後の )1 バイトの文字列リテラルまたはワイド文字 列リテラルの中の文字数 4095 制限なし (記憶域の大きさによる) 65535 制限なし (記憶域の大きさによる) ホスト環境における一つのオブジェクトのバイト数 #include ファイルに対する入れ子のレベル数 15 511 81 C 言語使用手引書 付表 B.1 翻訳限界 項目 C 言語規格 (各値以上) 本処理系の値 (任意の入れ子になったswitch文を除いた)一つのswitch 文中での case 名札の数 1023 制限なし (記憶域の大きさによる) 一つの構造体または共用体のメンバ数 1023 制限なし (記憶域の大きさによる) 一つの列挙の中の列挙定数の数 1023 制限なし (記憶域の大きさによる) 63 制限なし (記憶域の大きさによる) 一つの構造体宣言の並びの中の入れ子の構造体または共 用体定義のレベル数 82 付録 C 高速数学関数 「付表 C.1 高速数学関数一覧」に、本処理系で提供する高速数学関数の一覧を示します。 付表 C.1 高速数学関数一覧 関数 機能 sin(x) 正弦を求めます。 cos(x) 余弦を求めます。 tan(x) 正接を求めます。 asin(x) 逆正弦を求めます。 acos(x) 逆余弦を求めます。 atan(x) 逆正接を求めます。 atan2(x,y) x/y の逆正接を求めます。 sinh(x) 双曲線正弦を求めます。 cosh(x) 双曲線余弦を求めます。 exp(x) 指数を求めます。 log10(x) 常用対数(底 10)を求めます。 pow(x,y) べき乗を求めます。 gamma(x) 対数ガンマ関数値を求めます。 lgamma(x) hypot(x,y) ユークリッド距離を求めます。 scalb(x,y) x*pow(r,y) を求めます。(r=2) log(x) 自然対数(底 e)を求めます。 log1p(x) 引数に 1.0 を加えた値の自然対数(底 e)を求めます。 83 C 言語使用手引書 84 付録 D 制限事項および注意事項 D.1 制限事項 ありません。 D.2 注意事項 D.2.1 可変個の引数を持つ関数の呼出し 本処理系は、可変個の引数を持つ関数を呼び出す場合、引数として複素数 (complex)、構造体 (struct) および共用体 (union) を直接受け渡すことはできません。 引数として受け渡したい場合、直接ではなくポインタで受け渡すようにしてください。 D.3 移行上の注意事項 D.3.1 -O4 本処理系の -O4 は、V4 系 C コンパイラの -O4 とは最適化項目が異なります。 V4 系 C コンパイラと同等の最適化を行いたい場合、-O3 -Klib -Keopt を指定してください。 D.3.2 -Kgs および -Kpreload 本処理系は、-Kgs および -Kpreload をサポートしていません。 従来の C コンパイラの -Kgs および -Kpreload と同等の最適化を行いたい場合、-O5 を指定して ください。 D.3.3 -Kmerge および -Kxi=N 本処理系は、-Kmerge および -Kxi=N をサポートしていません。 従来の C コンパイラの -Kmerge および -Kxi=N と同等の最適化を行いたい場合、-Kcrossfile を 指定してください。 D.3.4 -p 本処理系は、-p をサポートしていません。 プログラムをチューニングしたい場合、プログラミング支援ツール (Parallelnavi 環境 )、ある いは並列アナライザ ( 非 Parallelnavi 環境 ) をお使いください。 D.4 環境変数の設定 D.4.1 コマンドの起動 C コンパイラの起動コマンドである fcc を利用するためには、以下の設定が必要です。 - 環境変数 PATH に ${INSTALL}/FSUNf90/bin を追加してください。 - 環境変数 LD_LIBRARY_PATH に ${INSTALL}/FSUNf90/lib を追加してください。 - 環境変数 LD_LIBRARY_PATH_64 に ${INSTALL}/FSUNf90/lib/sparcv9 を追加してください。 ${INSTALL} は、インストール先のディレクトリです。 D.4.2 オンラインマニュアル オンラインマニュアル fcc(1) を利用するためには,以下の設定が必要です。 - 環境変数 MANPATH に ${INSTALL}/FSUNf90/man を追加してください。 ${INSTALL} は、インストール先のディレクトリです。 85 C 言語使用手引書 D.5 整合性 D.5.1 アプリケーションプログラムとの整合性について fcc コマンドが生成するオブジェクトプログラムは、サン・マイクロシステムズ社製 C コンパイ ラが生成するオブジェクトプログラムと互換がありますので、C コンパイラを必要とするアプリ ケーションと富士通 C コンパイラを組み合わせて使用することが可能です。 対応方法としては、以下のいずれかがあります。 1. makefile やシェルスクリプト内で cc というコマンド名で C コンパイラを呼び出している 場合には、cc を fcc に変更する。 2.cc というコマンド名で fcc コマンドが呼び出せるようにシンボリックリンクを設定する。 シンボリックリンクを設定するためには、以下のコマンドを使用します。 ln -s /opt/FSUNf90/bin/fcc /usr/ccs/bin/cc 例えば、INFORMIX V5 では 1) の方法による対処として、シェルスクリプト esql の "CC=cc" およ び "CC=cc -g" となっている行をそれぞれ "CC=fcc" および "CC=fcc -g" に変更することにより使 用できます。また、2) の方法によっても問題なく使用できます。 上記の対処により通常は使用可能となりますが、一部のアプリケーションではリンク時に __cg92_used という外部名が未定義になる場合があります。 この場合には、__fstd.o というオブジェクトファイルがアプリケーションと共に提供されてい れば、リンク時にこのオブジェクトを結合することにより使用できます。例えば ORACLE では、 ランタイムライブラリがインストールされるディレクトリにこのファイルが提供されています。 __fstd.o ファイルが提供されていない場合には、 int __cg92_used ; という外部変数宣言のあるファイルを作成し、同時に結合することにより対処できます。 86 付録 E ISO/IEC 9899:1999 サポートについて 当製品は、ISO/IEC 9899:1999( 以下 C99 規格 ) をサポートするコマンドとして c99 コマンドを 含んでいます。ここでは、c99 コマンドにおける C99 規格のサポート状況について説明します。 E.1 サポート状況 E.1.1 言語 C99 規格の言語部分については、以下の項目がサポートされていません。 ■配列宣言子内の型修飾子リスト・static の記述 配列宣言子内の型修飾子リスト (restrict を除く ) および static の記述は、文法エラーになり ます。 ■ #pragma STDC プラグマ #pragma STDC プラグマはサポートしていません。 ■単純文字列と広角文字列の文字列結合 隣り合った単純文字列と広角文字列の文字列結合はサポートしていません。 C99 規格では単純文字列と広角文字列の文字列結合が翻訳段階 6 で行われ、その後、翻訳段階 7 で mbstowcs によってマルチバイト並びから広角文字列へ変換が行われるとされていますが、こ れは既存のソースプログラムのポータビリティを損なうものです。将来この仕様は変更されるで しょう。C89 規格ではこの使い方はエラーでした。 ■浮動小数点環境 浮動小数点環境を扱う機能 (fenv.h) はサポートしていません。 E.1.2 ライブラリ C99規格のライブラリ部分についてのサポート状況は、オンラインマニュアルをお読みください。 E.2 オブジェクト互換 fcc コマンドで作成したオブジェクトと c99 コマンドで作成したオブジェクトには、オブジェク ト互換があります。ただし、リンクは c99 コマンドで行ってください。 E.3 アプリケーションバイナリインタフェース c99 コマンドは、複素数型 (float _Complex, double _Complex, long double _Complex) および _Bool 型のサポートについて、当社独自のアプリケーションバイナリインタフェース (ABI) を使 用しています。そのため、他社コンパイラで作成したオブジェクトとは、この点ではオブジェク ト互換がありません。また、この ABI については将来変更の可能性があります。 「付表 E.1 複素数型および _Bool 型の大きさと境界整列値」に、複素数型および _Bool 型の大き さと境界整列値を示します。 付表 E.1 複素数型および _Bool 型の大きさと境界整列値 型 大きさ 境界整列値 float _Complex 8 バイト 4 バイト double _Complex 16 バイト 8 バイト long double _Complex 32 バイト 8 バイト 1 バイト 1 バイト _Bool 87 C 言語使用手引書 複素数型は、構造体と同様に取り扱われます。_Bool 型は、整数として取り扱われます。 E.4 処理系定義の動作 fcc コマンドの処理系定義の動作 (「付録 A 処理系定義の動作」) も合わせてお読みください。 ■識別子にマルチバイトキャラクタが記述されたとき、それが国際文字名にどう対 応するか。 マルチバイトキャラクタを識別子に記述できません。 ■実行時キャラクタセットのメンバの値 実行時キャラクタセットは、翻訳時キャラクタセットと一致しなければなりません。 ■ソースキャラクタセットと実行時キャラクタセットのメンバの値のマッピング 同一です。 ■実行時キャラクタセットでは表現できないマルチバイトキャラクタあるいは拡 張表記を含む文字列の値 翻訳時に解釈された値がそのまま文字列内に含まれます。 ■処理系によって拡張された整数型 拡張された整数型はありません。 ■符号付き整数のビット演算の結果 詰め物ビットは存在しないため、符号を考慮した結果が演算の結果になります。 ■ _Bool, signed int, unsigned int 以外にビットフィールドに使用できる整数型 すべての整数型が使用できます。 ■定数式の単純文字の文字定数の値が負の値を持つことができるか。 符号付きと解釈されます。 ■ # 演算子が文字列内の国際文字名の最初の \ に対して \ を付加するか。 付加します。 88 付録 F Parallelnavi ここでは、Parallelnavi 環境における C プログラムの翻訳および実行について説明します。 F.1 ラージページ機能 Parallelnavi 環境では、ラージページ機能を利用することができます。 ラージページ機能とは、ハードウェアがメモリを管理する単位である ' ページ ' を大きくし、実 行性能を向上させる機能です。 ラージページ機能の詳細は、「Parallelnavi 使用手引書」をお読みください。 F.1.1 翻訳 ラージページ機能を利用するプログラムを作成するためには、翻訳時オプション -Klargepage を 結合編集時に指定する必要があります。 単にオブジェクトファイルを作成する場合にはこのオプションは必要ありません。したがって、 一般のライブラリ等も通常どおり利用することができます。 なお、-Klargepage が指定されない場合は、ラージページ機能に対応したプログラムは作成され ません。 -Klargepage には、ラージページ化レベルを指定することができます。 -Klargepage[={1|2}] -Klargepage=1 が指定された場合には、データ域およびヒープ域に対してラージページ機能を適 用します。 -Klargepage=2 が指定された場合には、データ域およびヒープ域に加えて、スタック域に対して もラージページ機能を適用します。-Kparallel または -KOMP と同時に指定した場合には、スレッ ド毎のスタック領域に対してもラージページ機能を適用します。ラージページ化されたスタック 域は、通常のスタック域と異なり、ラージページ化されたヒープ域から、実行開始時に一括して 獲得されます。 なお、実行時のプロセスのスタック領域の制限値が、使用可能なラージページメモリと仮想メモ リの大きさの小さい方より大きい場合、本システムがプロセスのスタック領域の大きさを次のよ うに仮定して確保します。仮想メモリの大きさとは、ulimit(1) コマンドの vmemory で表示され る値です。 S = M / 8 S: プロセスのスタック領域の大きさ(byte) M: ラージページメモリと仮想メモリの小さい方の大きさ(byte) スレッド毎のスタック領域は、プロセスのスタック領域と同じ大きさで確保されます。ただし、 プロセスのスタック領域の制限値が、使用可能なラージページメモリと仮想メモリの大きさの小 さい方をスレッド数で割った値より大きい場合、本システムがスレッド毎のスタック領域の大き さを次のように仮定して確保します。 S = ( M / T ) / 5 S: スレッド毎のスタック領域の大きさ(byte) M: ラージページメモリと仮想メモリの小さい方の大きさ(byte) T: スレッド数 ス レ ッ ド 毎 の ス タ ッ ク 領 域 の 大 き さ を 特 定 の 大 き さ で 確 保 し た い 場 合 に は、環 境 変 数 THREAD_STACK_SIZE を使用してください。 -Klargepage が指定された場合は、-Klargepage=1 が指定されたものと見なします。 例: $ fcc -c fmain.c $ fcc -c fsubs.c $ fcc -Klargepage fmain.o fsubs.o ラージページ機能がインストールされていないシステムで -Klargepage が指定された場合は、次 のようなメッセージを出力し、エラーとなります。 fjlpld: fatal: Large page resources not found. No output written to a.out 89 C 言語使用手引書 F.1.2 実行 ラージページ機能を利用するプログラムは、Parallelnavi 環境下でのみ実行することができま す。実行の方式は、ラージページ機能を利用しない従来のプログラムと変わりません。 例: $ ./a.out Parallelnavi 環境以外でラージページ機能を利用するプログラムを実行した場合は、次のよう なメッセージを出力し、実行時エラーとなります。 例 1: 32 ビットモードで -Klargepage=1 を指定した場合 $ ./a.out_32_lp1 a.out_32_lp1: Cannot find /usr/lib/lpgld.so.1 Killed 例 2: 32 ビットモードで -Klargepage=2 を指定した場合 $ ./a.out_32_lp2 a.out_32_lp2: Cannot find /usr/lib/lpgld2.so.1 Killed 例 3: 64 ビットモードで -Klargepage=1 を指定した場合 $ ./a.out_64_lp1 a.out_64_lp1: Cannot find /usr/lib/sparcv9/lpgld.so.1 Killed 例 4: 64 ビットモードで -Klargepage=2 を指定した場合 $ ./a.out_64_lp2 a.out_64_lp2: Cannot find /usr/lib/sparcv9/lpgld2.so.1 Killed 翻訳時オプション -Klargepage=2 を指定した場合、実行開始時にスタック域が確保できないと、 以下のエラーメッセージが出力されます。 $ ./a.out largepage run-time: stack segment allocation failed. Can't continue to run. このメッセージが出力された場合、ヒープ域を拡大するか、またはスタック域の大きさを縮小し てください。 F.1.3 ラージページ機能を利用するプログラムの判定 ラージページ機能を利用するプログラムかどうかを判定するには、elfdump(1) コマンドを使い ます。elfdump(1) コマンドの出力に、lpgld という文字が含まれている場合は、ラージページ機 能を利用するプログラムです。 例 1: 32 ビットモードで -Klargepage=1 を指定した場合 $ elfdump -i ./a.out_32_lp1 Interpreter Section: .interp /usr/lib/lpgld.so.1 例 2: 32 ビットモードで -Klargepage=2 を指定した場合 $ elfdump -i ./a.out_32_lp2 Interpreter Section: .interp /usr/lib/lpgld2.so.1 例 3: 64 ビットモードで -Klargepage=1 を指定した場合 $ elfdump -i ./a.out_64_lp1 Interpreter Section: .interp /usr/lib/sparcv9/lpgld.so.1 例 4: 64 ビットモードで -Klargepage=2 を指定した場合 $ elfdump -i ./a.out_64_lp2 Interpreter Section: .interp /usr/lib/sparcv9/lpgld2.so.1 F.1.4 制約事項 ラージページ機能を利用するプログラムでは、以下の機能が制約されます。 スタティックリンクオプション 90 付録 F Parallelnavi スタティックリンクオプション -dn は利用できません。 F.2 CPU 数の管理 Parallelnavi 環境では、プロセスが利用できる CPU 数が厳密に管理されます。下記の方法によっ て、CPU 数の上限値を指定することができますが、プログラム実行時のスレッド数の決定におい て、これらの設定が考慮されます。 NQS を利用する場合 バッチキューの資源制限値(プロセスに割り当てる CPU の設定:per_process_processor_limit) や、qsub の -lp オプションの指定が考慮されます。これを NQS のプロセスに割り当てる CPU 数 と呼びます。 なお、バッチリクエストの実行開始時には、環境変数 PARALLEL および OMP_NUM_THREADS に対し て、NQS のプロセスに割り当てる CPU 数が設定されます。 具体的には、自動並列化や OpenMP によって並列化されたプログラムのスレッド数は、次のよう に決定されます。 なお、NQS の詳細は、「SystemWalker/ParallelWORKS 使用手引書ネットワークキューイングシス テム編」をお読みください。 F.2.1 自動並列化向けスレッド数の決定 CPU 数の上限値 以下の値を CPU 数の上限値とします。 ・ NQS のプロセスに割り当てる CPU 数 スレッド数 並列に動作するスレッドの数は、まず以下の優先順位で決定されます。 1.環境変数 PARALLEL の指定値注 2.環境変数 OMP_NUM_THREADS の指定値 3.NQS のプロセスに割り当てる CPU 数 上記の優先順位で決まったスレッド数と、CPU 数の上限値を比較して、小さい方を最終的なス レッド数として採用します。 F.2.2 OpenMP 向けスレッド数の決定 CPU 数の上限値 以下の値を、CPU 数の上限値とします。 ・ NQS のプロセスに割り当てる CPU 数 スレッド数 並列実行のスレッド数は、高速実行時ライブラリを使用するとき OpenMP と自動並列化で共通と なり、そうでないときそれぞれ独立に決定されます。高速実行時ライブラリの使用は、環境変数 FLIB_FASTOMP の設定によって制御することができます。 詳細は、「4.3 OpenMP 仕様による並列化」をお読みください。 高速実行時ライブラリを使用するとき(FLIB_FASTOMP が TRUE のとき) スレッド数は以下の優先順位で決定されます。 1.環境変数 OMP_NUM_THREADS の指定値注注 2.環境変数 PARALLEL の指定値 注 . 結合編集時に -KOMP が指定され、かつ、環境変数 FLIB_FASTOMP に TRUE が設定されてい るとき、環境変数 OMP_NUM_THREADS の指定値があれば、その値と一致していなければな りません。一致していない場合には小さい方の値が採用されます。この時に、環境変数 FLIB_C_MESSAGE が存在する場合には、mpc1042i-w のメッセージが出力されます。 注注 .結合編集時に -Kparallel が指定されているとき、環境変数 PARALLEL の指定値があれ ば、その値と一致していなければなりません。一致していない場合には小さい方の値が 採用されます。この時に、環境変数 FLIB_C_MESSAGE が存在する場合には mpc1042i-w の メッセージが出力されます。 91 C 言語使用手引書 3.NQS のプロセスに割り当てる CPU 数 この優先順位で決まるスレッド数が CPU 数の上限値を超えるとき、スレッド数は CPU 数の上限 値となります。 num_threads 節および omp_set_num_threads 関数によって指定する値は、ここで決まるスレッ ド数と一致していなければなりません。異なる値を指定した場合には、プログラムの実行が終 了されます。この時に、環境変数 FLIB_C_MESSAGE が存在する場合には mpc1041i-s のメッセー ジが出力されます。 高速実行時ライブラリを使用しないとき(FLIB_FASTOMP が TRUE でないとき) OpenMP のスレッド数は、以下の優先順位で決定されます。自動並列化のスレッド数は、 「F.2.1 自動並列化向けスレッド数の決定」の記述に従います。 1.parallel 指示子の num_threads 節の指定値 2.omp_set_num_threads 関数の指定値 3.環境変数 OMP_NUM_THREADS の指定値 4.環境変数 PARALLEL の指定値 5.NQS のプロセスに割り当てる CPU 数 動的スレッド調整機構が有効な場合には、この優先順位で決まるスレッド数が CPU 数の上限値 を超えるとき、スレッド数は CPU 数の上限値になります。 動的スレッド調整機構が無効な場合、1CPU 当たりのスレッド数が 1 を超える場合には、並列 に実行されることを意図したスレッドが時分割で実行されることになります。このような場 合、スレッド間の同期処理のオーバヘッドが大きくなり、実行性能が低下することがありま す。システムによる負荷も考慮して、1CPU 当たりのスレッド数が 1 以下になるようにスレッ ド数を設定することをお勧めします。 F.3 スレッド間ハードウェアバリア機能 Parallelnavi 環境では、ハードウェアバリア機構が実装されている場合、スレッド間ハードウェ アバリア機能を利用することができます。スレッド間ハードウェアバリア機能とは、スレッド並 列処理における同期処理を高速にし、実行性能を向上させる機能です。 スレッド間ハードウェアバリア機能の詳細は、「Parallelnavi 使用手引書」をお読みください。 F.3.1 翻訳 スレッド間ハードウェアバリア機能を利用するプログラムを作成するためには、-Khardbarrier を結合編集時に指定する必要があります。 オブジェクトファイルだけを作成する場合には、-Khardbarrier を指定する必要はありません。 なお、何も指定されない場合や、-Khardbarrier が指定されていても -Kparallel または -KOMP が同時に指定されていない場合には、スレッド間ハードウェアバリア機能に対応したプログラム は作成されません。 例 :-Khardbarrier の指定 $ fcc -Kparallel -c fmain.c $ fcc -Kparallel -c fsubs.c $ fcc -Kparallel -Khardbarrier fmain.o fsubs.o Parallelnavi がインストールされていないシステムで、-Khardbarrier が指定された場合は、次 のようなメッセージを出力し、エラーとなります。 ld: fatal: library -lpnbar: not found F.3.2 実行 スレッド間ハードウェアバリア機能を利用するプログラムは、Parallelnavi 2.0 以上の環境下 でのみ実行することができます。実行の方式は、スレッド間ハードウェアバリア機能を利用しな い従来のプログラムと変わりません。ただし、スレッド間ハードウェアバリア機能を活用するた めには、NQS の Node 内バリア資源が割り当てられている必要があります。 例 : スレッド間ハードウェアバリア機能を利用するプログラムの実行 $ cat script #!/bin/sh ./a.out $ qsub -qmulti -lb1 script 92 付録 F Parallelnavi Parallelnavi の NQS 環境以外でスレッド間ハードウェアバリア機能を利用するプログラムを実 行した場合や、NQS のハードウェアバリア資源が割り当てられなかった場合には、自動的に同期 処理をソフトウェアバリア方式に切り替え、実行を続けます。 -KOMP を指定して翻訳したプログラムでスレッド間ハードウェアバリアを利用する場合には、環 境変数 FLIB_FASTOMP が TRUE に設定されていなければなりません。環境変数 FLIB_FASTOMP の 意味と使用上の注意については、「4.3 OpenMP 仕様による並列化」をお読みください。 環境変数 FLIB_HARDBARRIER_MESSAGE および FLIB_C_MESSAGE が存在した場合、-Khardbarrier を指定したものの、何らかの理由によりスレッド間ハードウェアバリア機能が利用できない場合 には、以下のメッセージが出力されます。 mpc1043i-i "A thread hardware barrier couldn't be used." 環境変数 FLIB_NOHARDBARRIER が存在した場合、翻訳時オプションに関わらず、スレッド間ハー ドウェアバリア機能を使用しません。 F.3.3 スレッド間ハードウェアバリア機能を利用するプログラムの判定 スレッド間ハードウェアバリア機能を利用するプログラムなのかどうかを判定するには、ldd(1) コマンドを使います。ldd(1) コマンドの出力に、libpnbar.so という文字が含まれている場合 は、スレッド間ハードウェアバリア機能を利用するプログラムです。 F.3.4 制約事項 スレッド間ハードウェアバリア機能を利用するプログラムでは、以下の機能が制約されます。 fork(2) 時の子プロセスでの利用 スレッド間ハードウェアバリア機能を利用しているプログラムが fork システムコールを発行 した場合、生成されたプロセスにおいてはスレッド間ハードウェア機能を利用することができ ません。 93 C 言語使用手引書 94