第6章 コンパイラ

6.1 概要

HA8000クラスタシステムでは日立製作所製最適化C,C++,Fortranコンパイラを標準のコンパイラとしています。このコンパイラは本センターの過去のスーパーコンピュータおよびSR11000のコンパイラと高い互換性を持つため、本センターを利用したことのある利用者はプログラムやコンパイル方法を変更することなくHA8000クラスタシステムを利用できます。また、このコンパイラは高速な逐次コードを生成するだけでなく、高度な自動並列化機能を有することで知られており、本システムで初めてスーパーコンピュータを利用するユーザーにもお勧めできるコンパイラです。

HA8000クラスタシステムには日立製作所のコンパイラの他、Intel Compiler Version 11 と PGI Compiler Version 7.1 もインストールされています(PGIコンパイラはアカデミックライセンスで導入されているため企業ユーザーの方はご利用になれません)。これらのコンパイラは Opteron プロセッサで動作する高速なコードを生成できるコンパイラとして広く使われている製品です。

さらに本システムではRedHat Enterprise Linux に標準で付属する GNU Compiler Collection (gcc)も利用できます。機能、性能とも商用コンパイラには及ばないことが多いですが、広く使われているコンパイラであるため多くのソフトウェアでサポートされているという利点があります。

本章ではHA8000クラスタシステムで使用できるこれらのコンパイラの使い方を、並列プログラムのコンパイル方法および最適化オプションを中心に紹介します。コンパイラの使い方は並列化の手法によって使用するコマンドと必須オプションが異なります。本章では以下の場合についてコマンドと必須オプションを列挙します。

並列化なし

並列化を行わない場合のコンパイル方法です。逐次実行が前提のライブラリや逐次部分のみを含んだプログラムのコンパイル方法です。

自動並列化

コンパイラによって自動的に並列化するときに使用するコンパイル方法です。

OpenMP

並列化のためのOpenMP指示文を含んだプログラムのコンパイル方法です。

MPI

ピュアMPI実行する並列プログラムのコンパイル方法です。

MPI + 自動並列化

MPIによって並列化したプログラムをさらに自動並列化によってノード内を並列化するときに使用するコンパイル方法です。

MPI + OpenMP

MPIによって並列化したプログラムをさらにOpenMPによってノード内を並列化するときに使用するコンパイル方法です。

6.2 日立製作所製 最適化C/C++コンパイラ

本節では日立製作所の最適化C,C++コンパイラについてコンパイルに使用するコマンドおよび重要な最適化オプションについて紹介します。

6.2.1 推奨オプション

難しい説明を飛ばしてとりあえず使ってみたい方は次のようにコンパイルして下さい。典型的な数値計算プログラムでは通常安全なオプションですが場合によっては誤った結果となるやや危険なオプションを含んでいます。

$ cc -Os -noparallel +Op program.c

$ mpicc -Os -noparallel +Op mpi-program.c

6.2.2 コマンド

C言語のコンパイルコマンドは ccC++言語のコンパイルコマンドは sCC となります。以下に使い方を示します。角括弧は省略可能(またはデフォルトで設定されている)ことを意味します。

並列化なし

$ cc [?noparallel] [options] source_file

$ sCC [?noparallel] [options] source_file

自動並列化

$ cc ?parallel [options] source_file

$ sCC ?parallel [options] source_file

OpenMP

$ cc ?parallel ?omp [options] source_file

$ sCC ?parallel ?omp [options] source_file

MPI

$ mpicc [?noparallel] [options] source_file

$ mpicxx [?noparallel] [options] source_file

MPI + 自動並列化

$ mpicc ?parallel [options] source_file

$ mpicxx ?parallel [options] source_file

MPI + OpenMP

$ mpicc ?parallel ?omp [options] source_file

$ mpicxx ?parallel ?omp [options] source_file

6.2.3 最適化オプション

以下に示すレベルに従って最適化することができます。オプション無指定時はレベル3でコンパイルされます。なお、最適化機能には副作用を含むものがあり、プログラムによっては計算結果が異なったり、エラーが生じる場合があります。

-O0

原始プログラムどおりのコンパイル、レジスタの効果的な使用方法を中心に文の実行順序を変更しない一文単位の最適化(べき演算の乗算化、文関数のインライン化、局所的なレジスタの割り当て等)

-O3

デフォルト

プログラム全体での大域的な最適化(分岐命令の最適化、命令の並べ替え,演算子の変更、外部手続きインライン展開等)

-O4

制御構造の変換,演算順序の変更を含むプログラム全体の最適化(演算順序の変更、除算の乗算化、ループ展開・交換・分配・融合等)

-Os

一般的に性能向上が期待できる多くのオプションをまとめて設定(後述)
-parallel が設定されるので注意

これらの最適化オプションの他、性能に大きく影響することが知られているオプションに次のものがあります。

+Op

関数仮引数内のポインタ間に依存関係がないことを仮定する。例えば配列へのポインタ、p および q を取る関数で、pのどの要素を変更しても q の要素に影響がないことを仮定する

6.2.4 自動並列化オプション

自動並列化には並列化のレベルに応じて次のようなオプションがあります。

-noparallel

-parallel=0

並列化をしない

-parallel=1

SECTION型要素並列化,強制ループ並列化

-parallel

-parallel=2

変数・配列のプライベート化,リダクション並列化

-parallel=3

ループ分配,ループ分割,ループの一重化,サイクリック分割

-parallel=4

パイプライン並列化,インダクション並列化

6.2.5 その他のオプション

分割コンパイル、リンクなどに使用するオプションは gcc など一般的なコンパイラと共通です。

-I<dir>

ヘッダファイルを探すディレクトリを指定する

-c

コンパイルのみを行う

-L<dir>

ライブラリを探すディレクトリを指定する

-l<lib>

ライブラリをリンクする

6.3 日立製作所製 最適化FORTRANコンパイラ

本節ではHA8000クラスタシステムの標準FORTRANコンパイラである日立製作所製最適化FORTRANコンパイラの使い方を紹介します。

6.3.1 推奨オプション

難しい説明を飛ばしてとりあえず使ってみたい方は次のようにコンパイルして下さい。典型的な数値計算プログラムでは通常安全なオプションですが場合によっては誤った結果となるやや危険なオプションを含んでいます。

$ f90 -Oss -noparallel program.f90

$ mpif90 -Oss -noparallel mpi-program.f90

6.3.2 コマンド

日立製作所製最適化FORTRANコンパイラは f90 コマンドで起動します。f77コマンドもインストールされていますがこれは昔の日立製作所製の計算機で使われていたコンパイラとの互換性を維持するためのコマンドで、一部の機能が使用できません。特別な理由がない限りFORTRAN77プログラムもf90コマンドでコンパイルして下さい。

並列化なし

$ f90 [?noparallel] [options] source_file

自動並列化

$ f90 ?parallel [options] source_file

OpenMP

$ f90 ?parallel ?omp [options] source_file

MPI

$ mpif90 [?noparallel] [options] source_file

MPI + 自動並列化

$ mpif90 ?parallel [options] source_file

MPI + OpenMP

$ mpif90 ?parallel ?omp [options] source_file

言語仕様と形式はソースファイルの拡張子によって次のように設定されます。

f

固定形式

f77, f90, f95

各言語の自由形式

F

固定形式(コンパイル前にCプリプロセッサを使用)

F77, F90, F95

各言語の自由形式(コンパイル前にCプリプロセッサを使用)

6.3.3 言語オプション

拡張子に関わらず規格や形式を指定するには次のオプションを用います。

-fixed

ファイルの拡張子によらず固定形式を用いる

-free

ファイルの拡張子によらず自由形式を用いる

-hf77

ファイルの拡張子によらずFORTRAN77としてコンパイルする

-hf90

ファイルの拡張子によらずFortran90としてコンパイルする

-hf95

ファイルの拡張子によらずFortran95としてコンパイルする

6.3.4 最適化オプション

以下に示すレベルにしたがって最適化することができます。オプション無指定時はレベル3でコンパイルされます。なお、最適化機能には副作用を含むものがあり、プログラムによっては計算結果が異なったり、エラーが生じる場合があります。

-O0

原始プログラムどおりのコンパイル、レジスタの効果的な使用方法を中心に文の実行順序を変更しない一文単位の最適化(べき演算の乗算化、文関数のインライン化、局所的なレジスタの割り当て等)

-O3

デフォルト

プログラム全体での大域的な最適化(分岐命令の最適化、命令の並べ替え、演算子の変更、外部手続きインライン展開等)

-O4

制御構造の変換、演算順序の変更を含むプログラム全体の最適化(演算順序の変更、除算の乗算化、ループ展開・交換・分配・融合等)

-Os

ソフトウェアパイプライン、要素並列化を含む各種最適化オプションをまとめて設定。-parallel が設定されるので要注意

-Oss

一般的に性能向上が期待できるほとんどの最適化オプションをまとめて設定。-parallel が設定されるので注意

-Oss に含まれませんが、次のオプションも高速化につながる可能性があります。

-autoinline

関数のインライン展開を行う

6.3.5 自動並列化オプション

自動並列化には並列化のレベルに応じて次のようなオプションがあります。

-noparallel

-parallel=0

並列化をしない

-parallel=1

SECTION型要素並列化,強制ループ並列化

-parallel

-parallel=2

変数・配列のプライベート化,リダクション並列化

-parallel=3

ループ分配,ループ分割,ループの一重化,サイクリック分割

-parallel=4

パイプライン並列化,インダクション並列化

6.3.6 その他のオプション

分割コンパイル、リンクなどに使用するオプションは一般的なコンパイラと共通です。

-I<dir>

ヘッダファイルを探すディレクトリを指定する

-c

コンパイルのみを行う

-L<dir>

ライブラリを探すディレクトリを指定する

-l<lib>

ライブラリをリンクする

6.4 日立製作所最適化コンパイラ オプションの詳細

6.4.1 最適化の内容

前節までで日立製作所製最適化コンパイラの基本的なオプションを紹介しましたが、-Os などの最適化オプションは複数の最適化技術を組み合わせて使用することを示しており、アプリケーションによっては計算結果が変わってしまう最適化技術を含んでいます。以下に最適化オプション -Os または -Oss が行う最適化の種類と、それぞれの最適化手法を個別に選択するためのオプションをまとめます。

表6 -Os に含まれるオプション

レベル

含まれるオプション

詳細

-Os

C言語

Fortran

共通

-O4

プログラム全体の最適化

-approx

除算で,逆数による乗数化を許可する

-disbracket

括弧や文の順序によって明示された演算順序を変更する

-divmove

条件式下で除算割り込みが起こる可能性があるループ不変式をループ外に移動する

-expmove

条件式下にあるループ不変式をループ外に移動する

-invariant_if

ループ不変条件展開最適化をする

-ischedule=3

命令の実行順序を変更する。分岐予測を行い投機的に実行順序を変更する。

-loopdistribute

ル-プ分配による最適化をする

-loopexpand

ル-プ展開による最適化をする

-loopfuse

ル-プ融合による最適化をする

-loopinterchange

ル-プ交換による最適化をする

-loopreroll

ループ巻き戻しによる最適化をする

-parallel=2

自動並列化を行う

-prefetch

最内側ループ中の配列に対してプリフェッチ最適化をする

-simd

SIMD命令による最適化を行う

-workarray

作業配列を利用した最適化をする

-Os

Fortran

のみ

-rapidcall

組込み関数に対して呼び出し時の引数チェックを行わない,引数を値渡しとする

-scope

ループの最適化でスコープ分割をする

-swpl

ソフトウェアパイプラインによる最適化をする

-noargchk

サブルーチンおよび関数を引用する際,引数の個数と型,属性,名称の重なりをチェックしない

-noagochk

プログラム実行時に,割当て形GO TO文の文番号並びの有無をチェックしない

-nosubchk

配列参照の添字の値が,宣言の範囲内にあるかどうかをチェックしない

-nolcheck

新Fortran規格から拡張した仕様に対して,エラーメッセージを出力しない

-nodochk

DO文の繰り返し回数0をチェックしない

-Os

Cのみ

-autoinline

自動的に関数をインライン展開する

表7 -Ossに含まれるオプション

レベル

含まれるオプション

内容

-Oss

Fortranのみ

-Os

表6のすべて

-ifswpl

条件分岐を含むループのソフトウェアパイプラインによる最適化をする

-parallel=4

(前述)

6.4.2 最適化の個別設定と打ち消し

特定の最適化技術のみを使用する場合は表6および表7に示したオプションを個別に設定します。また -Oss や -Os が含む最適化技術の一部を無効化したいときは各オプションに no を付けたオプションを -Oss または -Os の後に置くきます。特に、自動並列化を抑止するための -noparallel はピュアMPIプログラムのコンパイル時には必須となります。

$ mpif90 -Oss -noparallel mpi-program.f90

6.4.3 並列化報告

チューニングのヒントのために並列化の報告を出力することができます。次のように -loglist オプションを付けてコンパイルして下さい。並列化ログはソースファイル名の拡張子を .log にしたファイルとして生成され、元のソースファイルにコメントを加える形で並列化状況が書き込まれます。

$ mpif90 -Oss -loglist mpi-program.f90

6.5 日立製作所最適化コンパイラ 実行時オプションと環境変数

本節は実行時に設定する環境変数または実行時オプションについて説明します。

6.5.1 自動並列化およびOpenMPのスレッド数指定

自動並列化またはOpenMPによる並列化を行った場合、実行時のスレッド数は次の表にある環境変数で指定します。環境変数を設定しなかった場合はコア数(HA8000クラスタシステムでは常に16)となります。

環境変数

内容

HF_PRUNST_THREADNUM

自動並列化されたプログラムの実行時スレッド数

OMP_NUM_THREADS

OpenMPで並列化されたプログラムの実行時スレッド数

環境変数の具体的な指定方法は後の「使用例」の章に例を載せます。

6.5.2 FORTRANの実行時オプション

FORTRANプログラムの実行時にはプログラムの動作を変更するいくつかのオプションが指定できます。オプションは次のように -F に続けてオプションを書きます。

$ ./a.out -F’RUNST(UFLOW),RUNST(OFLOW)’

ただし、この方法はシェルの特殊文字との相性が悪く、特にバッチジョブでは正常にプログラムに渡らないことが多いので実行時オプションは上のようにプログラムの引数として指定するのではなく、次の例のように環境変数 HF_90USEROPTS に設定するようにしてください。

export HF_90USEROPTS=’-FRUNST(UFLOW),RUNST(OFLOW)’

主なオプションは次の通りです。詳しくはオンラインマニュアルをご覧下さい。

オプション

内容

RUNST(UFLOW)

浮動小数点演算中にアンダーフローが発生したらエラーとしてプログラムを終了する

RUNST(OFLOW)

浮動小数点演算中にオーバーフローが発生したらエラーとしてプログラムを終了する

PORT(ENDIANINOUT(ALL))

入出力のエンディアンを変換する

6.6 Intel コンパイラ

本節では Intel コンパイラの使い方を紹介します。

6.6.1 基本的な使い方と推奨オプション

とりあえず使ってみたい方のため、解説の前に基本的な使い方の例を示します。

$ source /opt/itc/mpi/mpiswitch.sh mpich-mx-intel11

$ icc -msse3 -O3 -ipo -no-prec-div program.c

$ mpicc -msse3 -O3 -ipo -no-prec-div mpi-program.c

6.6.2 環境設定

次のコマンドでIntel コンパイラに必要なPATH などの環境変数が設定されます。またMPI用のコンパイルコマンド(mpif90など)がIntel コンパイラを使用するように切り替わります。

$ source /opt/itc/mpi/mpiswitch.sh mpich-mx-intel11 (通常の環境)

$ source /opt/itc/mpi/mpiswitch.csh mpich-mx-intel11 (tcshに変更している場合)

IntelコンパイラにはPATHなどの環境変数を設定する環境設定シェルスクリプトが付属していますが、HA8000クラスタシステムではそれらを明示的に呼び出す必要はありません。

6.6.3 コマンド

Intel コンパイラは次のように呼び出して使用します。上から順にC言語、C++言語、FORTRANです。MPIを使う場合のコマンドは前節で説明した方法でIntelコンパイラ用の環境に切り替わっていることを前提とします。MPIプログラムのコンパイラはコンパイラの種類によらず同じコマンド名なので、前節の設定を行っていない場合は日立製作所最適化コンパイラを使うMPIコンパイラが動きます(日立製コンパイラにIntelコンパイラのオプションを渡すことになるので多くの場合はエラーになります)。

並列化なし

$ icc [option] source_file

$ icpc [option] source_file

$ ifort [option] source_file

自動並列化

$ icc [option] -parallel source_file

$ icpc [option] -parallel source_file

$ ifort [option] -parallel source_file

OpenMP

$ icc [option] -openmp source_file

$ icpc [option] -openmp source_file

$ ifort [option] -openmp source_file

MPI

$ mpicc [option] source_file

$ mpicxx [option] source_file

$ mpif90 [option] source_file

MPI + 自動並列化

$ mpicc [option] -parallel source_file

$ mpicxx [option] -parallel source_file

$ mpif90 [option] -parallel source_file

MPI + OpenMP

$ mpicc [option] -openmp source_file

$ mpicxx [option] -openmp source_file

$ mpif90 [option] -openmp source_file

6.6.4 オプション

主なオプションを次の表にまとめます。

オプション

内容

-O

最適化を行います

-O3

強い最適化を行います。通常はこのオプションがお勧めです

-msse3

SSE3ベクトル演算命令を生成します

-ipo

複数の関数にまたがっての最適化を行います

-no-prec-div

除算を逆数の乗算に変換します。計算精度がわずかに落ちます

-fixed

(FORTRAN) 固定フォーマットを仮定します

-free

(FORTRAN) 自由フォーマットを仮定します

-convert big_endian

(FORTRAN) unformatted データをビッグエンディアンと仮定します

6.6.5 実行時オプションおよび環境変数

OpenMP または自動並列化でコンパイルしたプログラムの実行時スレッド数は OMP_NUM_THREADS 環境変数で指定できます。自動並列化の場合もこの環境変数を参照します。省略時はコア数になります。

6.7 PGI コンパイラ

本節では PGI コンパイラの使い方を紹介します。PGIコンパイラはアカデミックライセンスで導入されておりますので企業ユーザーの方はご利用になれません。ご了承下さい。

6.7.1 基本的な使い方と推奨オプション

とりあえず使ってみたい方のため、解説の前に基本的な使い方の例を示します。

$ source /opt/itc/mpi/mpiswitch.sh mpich-mx-pgi

$ pgcc -fast -O3 -tp=barcelona-64 program.c

$ mpicc -fast -O3 -tp=barcelona-64 mpi-program.c

6.7.2 環境設定

次のコマンドでPGI コンパイラに必要なPATH などの環境変数が設定されます。またMPI用のコンパイルコマンド(mpif90など)がPGIコンパイラを使用するように切り替わります。

$ source /opt/itc/mpi/mpiswitch.sh mpich-mx-pgi (通常の環境)

$ source /opt/itc/mpi/mpiswitch.csh mpich-mx-pgi (tcshに変更している場合)

6.7.3 コマンド

PGIコンパイラは次のように呼び出して使用します。上から順にC言語、C++言語、FORTRAN77,

Fortran90です。MPIを使う場合のコマンドは前節で説明した方法でPGIコンパイラ用の環境に切り替わっていることを前提とします。MPIプログラムのコンパイラはコンパイラの種類によらず同じコマンド名なので、前節の設定を行っていない場合は日立製作所最適化コンパイラを使うMPIコンパイラが動きます(日立製コンパイラにPGIコンパイラのオプションを渡すことになるので多くの場合はエラーになります)。

並列化なし

$ pgcc [option] source_file

$ pgCC [option] source_file

$ pgf77 [option] source_file

$ pgf90 [option] source_file

自動並列化

-Mcouncur オプションがありますが性能が良くないのでお勧めしません

OpenMP

$ pgcc [option] -mp source_file

$ pgCC [option] -mp source_file

$ pgf77 [option] -mp source_file

$ pgf90 [option] -mp source_file

MPI

$ mpicc [option] source_file

$ mpicxx [option] source_file

$ mpif77 [option] source_file

$ mpif90 [option] source_file

MPI + OpenMP

$ mpicc [option] -mp source_file

$ mpicxx [option] -mp source_file

$ mpif77 [option] -mp source_file

$ mpif90 [option] -mp source_file

6.7.4 オプション

主なオプションを次の表にまとめます。

オプション

内容

-fast

通常効果のあるすべての最適化オプションを有効にします

-O3

強い最適化を行います。-fast のあとに付けると効果的です

-tp=barcelona-64

HA8000クラスタシステムで使われているプロセッサ向けのコードを生成します

-Mfixed

(FORTRAN) 固定フォーマットを仮定します

-Mfree

(FORTRAN) 自由フォーマットを仮定します

-Mbyteswapio

(FORTRAN) unformatted データをビッグエンディアンと仮定します

6.7.5 実行時オプションおよび環境変数

OpenMP または自動並列化でコンパイルしたプログラムの実行時スレッド数は OMP_NUM_THREADS 環境変数で指定できます。自動並列化の場合もこの環境変数を参照します。省略時はコア数になります。

6.8 GNU Compiler Collection

HA8000クラスタシステムには RedHat Linux 標準の GNU Compiler Collection (GCC) がインストールされています。一般的に数値計算用途には前節までに紹介した商用コンパイラの方が高性能です。しかし性能がそれほど重要でないツール類やフリーソフトウェアのコンパイルには、世界中のユーザーによってテストされているGCCを使うのが最もトラブルが少ないと期待されます。

GCC のコマンドはC言語、C++、Fortran がそれぞれ gcc, g++, gfortran です。詳しい使い方は info gcc コマンドなどでご確認下さい。また、GCCを使用するMPIも準備してあります。

$ source /opt/itc/mpi/mpiswitch.sh mpich-mx-gcc

を実行すると GCC 用の MPI 環境に切り替わります。

6.9 分割コンパイルとリンク

規模の大きなプログラムは複数のソースコードに分割し、分割コンパイルを行うことをお勧めします。分割コンパイルは各ソースコードのコンパイル時に ?c オプションをつけてコンパイルし、生成されたオブジェクトファイルを最後にリンクします。次の例では上2行がコンパイルのみを行っており、最後の行がリンクを行っています。

$ mpicc ?parallel ?omp ?Os ?c a.c

$ mpicc ?parallel ?omp ?Os ?c b.c

$ mpicc ?parallel ?omp a.o b.o ?o program

このようにするとソースの変更があった場合も変更したソースのみをコンパイルするだけで済みます。分割コンパイルをするときは、変更があったファイルのみを自動的にコンパイルできる make と呼ばれるツールを使用するのが一般的です。なお各コンパイラ共、自動並列化、OpenMP 関連のオプションはコンパイル時、リンク時双方に必要です。