Windows 版 PGI コンパイラの使用法特集(2)

PGI Workstation 製品を使う

対象 Windows用コンパイラ、シェル操作、Cygwin

 PGIコンパイラ製品の中で Windows® 版のコンパイラ製品は、二種類あります。前回のコラムでは、PGI Visual Fortran と Micorosoft Visual C++ のコンパイラを使用して、アプリケーションをビルドする方法を説明しました。このコラムでは、もう一つのPGIコンパイラ製品である PGI Workstation 製品を使用して、Linux と同じ Bash シェルコマンド・インタフェースで、前回の課題と同じ SEAWAT v.4 アプリケーションのビルドを行う方法を説明します。
2010年11月18日 Copyright © 株式会社ソフテック 加藤

Windows 版 PGI コンパイラの使用法の特集

 Windows 上で PGI コンパイラ製品の使用法を特集して説明します。

使用する課題は、SEAWAT V.4 (前回の PVF で使用したもの)

 使用する題材は、前回の PVF コンパイラでビルドしたものと同じ、米国地質調査所(USGS)が開発している地下水流動モデルと輸送モデルとして有名な パブリックドメイン・ソフトウェア SEAWAT v.4 です。このプログラムは、FortranとC言語が混在したアプリケーションであるため、Windows 版の PGI Fortran/C/C++ Workstation 製品の Fortran コンパイラとCコンパイラを使用して、実行モジュール作成します。

 展開したソースファイルは、前コラムと同じものを使用しますが、再度、その様子を記しておきます。ダウンロードしたアーカイブは、SEAWAT Version 4.00.03 program (updated September 22, 2009)で、swt_v4_00_03.zip と言うファイルです。これを、Windows上の任意のフォルダ配下に展開します。私の場合は、C ドライブの C:\PGI\SEAEWAT4 と言うフォルダを作成し、その配下に展開しました。展開されたファイルは、この配下に置かれ、その時に swt_v4_00_03 と言うトップのフォルダが作成されます。

実装場所

 C:\PGI\SEAEWAT4\swt_v4_00_03 と言うフォルダ配下に、SWEWAT パッケージの各フォルダが存在します。この中に、ソースプログラムが含まれた sources と言うフォルダも存在します。コンパイル等の作業は、この source フォルダ配下で行います。

PGI Fortran/C/C++ Workstation を使ってみる(Bashシェルによるコマンド・インタフェース)

 ここでは、Windows Vista 64bit 上にインストールされた PGI Workstation コンパイラを使用します。ここでは、64bit のアプリケーションを作成します。デスクトップ上にある「PGI Workstation」にアイコンをダブルクリックすると、64ビット専用のPGIコマンド・プロンプト画面を表示されます。あるいは、Windows の「スタート」-->「全てのプログラム」-->「PGI Workstation」-->「Command shell」-->「PGI bash (64)」を選択して起動します。もし、32ビット用のコンパイル環境を使用したい場合は、「PGI bash」を選択します。PGI Workstation (Windows版)では、32ビット/64ビットのコンパイル環境の切り替えは、このように、専用のコマンド・プロンプト画面を開いて操作します。

Bashコマンドで、ソースがあるフォルダまで移動する

 Linux 上での使用法と全く同じ方法で操作できます。PGIコマンド・プロンプトは、Linux の bash シェル環境となりますので、主な Linux のコマンドがそのまま使用できます。cd で、ソースファイルの存在する directory(フォルダ)に移動します。この例では、C: ドライブの PGI/SEAMAT4/swt__v4_00_03/source まで移動します。なお、フォルダ間の区切り記号は、Linux流で、/(スラッシュ)を使います。Windowsのコマンドプロンプトでは、区切り記号は \ を使用しましますが、bash シェル上では、/ を使います。また、\ 文字は、Linuxの世界では escape 文字として使用されます。

画面例

 sourceフォルダの中には、必要とする Fortran ソース並びに、C ソース、include ファイル、ヘッダファイルが含まれております。Linuxの Make ユーティリティを使用して、これらのソースファイルのコンパイルとリンクを行い、実行モジュールを生成することにします。ここで使用するコンパイラは、PGI の Fortran コンパイラ(pgfortran)とPGI Cコンパイラ(pgcc)とします。Microsoft の VC++ コンパイラで C ルーチンのオブジェクト(ライブラリ)を別に作成しても良いですが、これは前回のコラムを参考にしていただきます。この場合は、VC++で作成した static library (例えば、STW-C.lib と言った名前で)をこのフォルダにコピーしておきます。

Makefileの作成

 ソースファイルの数が多いアプリケーションの実行バイナリの構築では、一般に make ユーティリティを使用します。コンパイル対象となるソースファイルを定義して、さらに、適用するコンパイルオプション等を定義し、また、ファイル間のコンパイル順序の依存関係等を定義するファイル Makefile を作成すれば、make コマンドを実行するだけで、定義に習い自動的にコンパイルできます。SEAWAT v.4 用の Makefile の一例がインターネット上に公開されていますので、それを参照して、PGI用に変更することにします。以下は、PGIコンパイラを使用する場合の変更した例です。なお、Windowsの世界では、オブジェクト・ファイルの名前の慣習は、***.obj のため、Linux 等の ***.o とは異なります。従って、この Makefile では、Windows 流に改め、***.obj として記述します。もし、Linux 上で動作する Makefile があるのであれば、***.o スタイルの Makefile をそのまま使用する方法もあります。これについては、過去のコラム「PGI Workstation 製品の Windows 版の使用」に説明しています。

# Makefile example for SEAWAT (swt_v4_003)
# Makefile for non-USGS distribution
# SofTek / using PGI compiler 

PROGRAM = swt_v4.exe

INCDIR= .

# 
# PGI Fortran コンパイラ (pgfortran)設定
# -r8 :倍精度へ精度拡張
#

FC= pgfortran

# 手続き間の最適化 IPA を行う時は以下の行のコメント#を外す
#
#OPTIPA= -Mipa=fast,inline

# PGI コンパイル・オプション
FFLAGS= -r8 -Minfo=ccff -fastsse $(OPTIPA)

# Microsoft(R) MPI library msmpi の使用(PGIコンパイラオプション)
# MS-MPI 並列ライブラリをリンクする場合、以下の行のコメント#を外す
#MPI= -Mmpi=msmpi

# 32bit Windows のコンパイル環境の付加オプション
# 32bit Windows 下では、以下の行のコメント#を外す
#COMP32= -Miface=unix

# Cコンパイラ
# -D_UF を定義する(シンボル名の変更 C -- Fortran混在の場合の呼び出し規約を合わせる)

CC= pgcc
CDEF= -D_UF
CFLAGS= -fastsse -Minfo $(OPTIPA)

# GMG functions Cルーチンオブジェクト
#
GMG = r_vector.obj\
      SOLVERS.obj\
      CCFD.obj\
      MF2KGMG.obj

# 全てのオブジェクトの指定
MHC = mhc1

OBJECTS = \
    vdf1.obj \
    vdf1vsc1.obj \
    swt_v4.obj \
    ctime.obj \
    daf1.obj \
    de45.obj \
    glo1bas6.obj \
    gmg1.obj \
    gutsdaf.obj \
    gwf1bas6.obj \
    gwf1bcf6.obj \
    gwf1chd6.obj \
    gwf1drn6.obj \
    gwf1drt1.obj \
    gwf1ets1.obj \
    gwf1evt6.obj \
    gwf1fhb1.obj \
    gwf1gag5.obj \
    gwf1ghb6.obj \
    gwf1hfb6.obj \
    gwf1huf2.obj \
    gwf1ibs6.obj \
    gwf1lak3.obj \
    gwf1lpf1.obj \
    gwf1mnw1.obj \
    gwf1rch6.obj \
    gwf1res1.obj \
    gwf1riv6.obj \
    gwf1sfr2.obj \
    gwf1str6.obj \
    gwf1sub1.obj \
    gwf1swt1.obj \
    gwf1wel6.obj \
    hufutl2.obj \
    hydmod.obj \
    imt1adv5.obj \
    imt1btn5.obj \
    imt1dsp5.obj \
    imt1fmi5.obj \
    imt1gcg5.obj \
    imt1rct5.obj \
    imt1ssm5.obj \
    imt1tob5.obj \
    imt1utl5.obj \
    lmg1.obj \
    lmt6.obj \
    memchk.obj \
    obs1adv2.obj \
    obs1bas6.obj \
    obs1bas6vd.obj \
    obs1drn6.obj \
    obs1drn6vd.obj \
    obs1drt1.obj \
    obs1drt1vd.obj \
    obs1ghb6.obj \
    obs1ghb6vd.obj \
    obs1riv6.obj \
    obs1riv6vd.obj \
    obs1str6.obj \
    parutl1.obj \
    pcg2.obj \
    pes1bas6.obj \
    pes1gau1.obj \
    rtedaf.obj \
    sen1bas6.obj \
    sen1chd6.obj \
    sen1drn6.obj \
    sen1drt1.obj \
    sen1ets1.obj \
    sen1evt6.obj \
    sen1ghb6.obj \
    sen1hfb6.obj \
    sen1huf2.obj \
    sen1lpf1.obj \
    sen1rch6.obj \
    sen1riv6.obj \
    sen1str6.obj \
    sen1wel6.obj \
    sip5.obj \
    sor5.obj \
    utl6.obj \
    vdf1bas6.obj \
    vdf1bcf6.obj \
    vdf1chd6.obj \
    vdf1drn6.obj \
    vdf1drt1.obj \
    vdf1ets1.obj \
    vdf1evt6.obj \
    vdf1fhb1.obj \
    vdf1ghb6.obj \
    vdf1huf2.obj \
    vdf1lmt6.obj \
    vdf1lpf1.obj \
    vdf1mnw1.obj \
    vdf1rch6.obj \
    vdf1riv6.obj \
    vdf1wel6.obj \
    para-non.obj 
#   para-mpi.obj 

all: $(PROGRAM)

$(PROGRAM): 	$(MHC).mod $(OBJECTS) $(GMG)
		$(FC) $(FFLAGS) -o $(PROGRAM) $(MHC).obj $(OBJECTS) $(GMG) $(MPI) 

# MPI並列コード作成の場合 (以下2行のコメント#を外す,上記の# para-mpi.objの#コメントを外し、
#                        # para-non.obj としてコメント化し、行を入れ替え)
#para-mpi.obj: parallel/para-mpi.f
#	$(FC) $(FFLAGS) $(COMP32) -I$(INCDIR) -c parallel/para-mpi.f $(MPI)

# シリアルコード作成の場合(MPIコード作成の場合、以下の2行コメント化する)
para-non.obj: serial/para-non.f
	$(FC) $(FFLAGS) $(COMP32) -I$(INCDIR) -c serial/para-non.f

%.obj: 	%.f
	$(FC) $(FFLAGS) $(COMP32) -c $<

$(MHC).mod:
	$(FC) $(FFLAGS) $(COMP32) -c $(MHC).f90

%.obj : %.c
	$(CC) $(CDEF) $(CFLAGS) -c $<

clean:
	/bin/rm *.obj *.mod $(PROGRAM) *.oo 
						

 上記の Makefile の重要なポイントを説明しておきます。以下に表すリストの部分は、pgfortran コンパイラのオプションの設定の部分です。"OPTIPA" の定義は、コメント化していますが、これを enable にした場合、IPA と言う「手続き間の最適化」を行います。この最適化の意味は、個々のソースファイル内の最適化だけに閉じないで、ソースファイル間で関連のある最適化事項も含めて全体プログラムを最適化すると言う意味です。次に、FFLAGS で定義されたオプションは、 -r8 を指定します。これは、単精度実数を倍精度実数に精度拡張すると言う意味です。-fastsse は、SSEベクトル化も含む最大限の最適化を行うと言う意味です。一般的には、どんな場合でもこのオプションを付けることをお勧めします。-Minfo=ccff は、コンパイラが行った最適化等の情報(CCFF)を保持すると言う意味です。この CCFF(Common Compiler Feedback Format) 情報は、pgprof プロファイリングのユーティリティを使用して、プログラムのソースラインと紐付けして表示されます。このオプションは、実行モジュールの作成の用途だけであれば、付けても付けなくても構いません。

# 
# PGI Fortran コンパイラ (pgfortran)設定
# -r8 :倍精度へ精度拡張
#

FC= pgfortran

# 手続き間の最適化 IPA を行う時は以下の行のコメント#を外す
#
#OPTIPA= -Mipa=fast,inline

# PGI コンパイル・オプション
FFLAGS= -r8 -Minfo=ccff -fastsse $(OPTIPA)

 以下に表すリストの部分は、今回の64bit版のシリアル実行バイナリのビルドにおいては、必要ないため enable にしていません。まず、MPI マクロから説明します。"MPI" と言うマクロ名は、MPI並列ライブラリ(マイクロソフト® の MS-MPI ライブラリ)のヘッダーファイルを読み込み、そしてリンクするためのPGI専用のオプション -Mmpi=mpmpi として定義しています。これを enable にすると、SEAWATの MPI 並列実装ルーチン(parallel/para-mpi.f)をコンパイルできます。次に、COMP32マクロは、32ビットWindowsでコンパイルする場合は、必ず有効に下さい。その理由は、こちらへ。

# Microsoft(R) MPI library msmpi の使用(PGIコンパイラオプション)
# MS-MPI 並列ライブラリをリンクする場合、以下の行のコメント#を外す
MPI= -Mmpi=msmpi

Makefule 中の以下の2行を有効にする場合 MPI は enable にする必要あり。
# MPI並列コード作成の場合 (以下2行のコメント#を外す)
para-mpi.obj: parallel/para-mpi.f
	$(FC) $(FFLAGS) -I$(INCDIR) -c parallel/para-mpi.f $(MPI)

# 32bit Windows のコンパイル環境の付加オプション
# 32bit Windows 下では、以下の行のコメント#を外す
COMP32= -Miface=unix

 以下に表すリストの部分は、C ルーチンのコンパイルのためのオプション設定です。このプログラムでは、Fortran オブジェクトとの相互運用のため、プリプロセッサでルーチン名のシンボル名を変更する処理をしています。この定義が、CDEF= -D_UF で行っています。CFLAGSマクロは、Cコンパイラ pgcc へのオプション設定です。Fortranの設定と同じ、最大限の最適化 -fastsse を設定しています。以上でコンパイラのオプション設定は終了します。

# Cコンパイラ
# -D_UF を定義する(シンボル名の変更 C -- Fortran混在の場合の呼び出し規約を合わせる)

CC= pgcc
CDEF= -D_UF
CFLAGS= -fastsse -Minfo $(OPTIPA)

make の実行(アプリケーションのビルド)

 ソースファイルと Makefile があれば、後は、make を実行するだけです。Makefile の記述に従い、Fortran と C ソースのコンパイルされ、実行モジュール swt_v4.exe が生成されます。以下のリストは、make のログの一部です。

PGI Workstation 10.9 (64)
PGI$ cd C:
PGI$ cd PGI
PGI$ cd SEAWAT4/swt_v4_00_03/source/

PGI$ make
pgfortran -r8 -Minfo=ccff -fastsse    -c mhc1.f90
pgfortran -r8 -Minfo=ccff -fastsse    -c vdf1.f
pgfortran -r8 -Minfo=ccff -fastsse    -c vdf1vsc1.f
pgfortran -r8 -Minfo=ccff -fastsse    -c swt_v4.f
pgfortran -r8 -Minfo=ccff -fastsse    -c ctime.f
pgfortran -r8 -Minfo=ccff -fastsse    -c daf1.f
PGF90-W-0093-Type conversion of expression performed (daf1.f: 188)
PGF90-W-0155-The type of FLOAT is now double precision with -r8  (daf1.f: 189)
PGF90-W-0093-Type conversion of expression performed (daf1.f: 209)
  0 inform,   3 warnings,   0 severes, 0 fatal for gwf1daf1ad
PGF90-W-0093-Type conversion of expression performed (daf1.f: 342)
  0 inform,   1 warnings,   0 severes, 0 fatal for gwf1daf1fm
PGF90-W-0093-Type conversion of expression performed (daf1.f: 545)
PGF90-W-0093-Type conversion of expression performed (daf1.f: 572)
  0 inform,   2 warnings,   0 severes, 0 fatal for limseep
pgfortran -r8 -Minfo=ccff -fastsse    -c de45.f
(以下、省略)

SEAWAT v.4 の実行

この SEAWAT のパッケージには、サンプルデータセットがありますので、これを使用してテストランしてみます。

PGI$ pwd
/c/PGI/SEAWAT4/swt_v4_00_03/source
PGI$ cd ../examples/7_swtv4_ex/   (サンプルデータのある場所まで移動)
PGI$ ls
case1  case2  case3  case4  case5  case6  case7   ("case1"を実行)
PGI$ cd case1
PGI$ ls
MT3D.CNF     MT3D002.MAS        coastal_flow.adv  coastal_flow.dis  coastal_flow.lpf
coastal_flow.ssm    pgprof.out    spec_02.mv
MT3D001.MAS  MT3D002.OBS        coastal_flow.bas  coastal_flow.dsp  coastal_flow.lst
coastal_flow.vdf    pgprof.out.1  swt_v4.bat
MT3D001.OBS  MT3D002.UCN        coastal_flow.btn  coastal_flow.gcg  coastal_flow.oc
coastal_flow.wel    seawat.nam    swt_v4.exe
MT3D001.UCN  SEAWAT403func.exe  coastal_flow.cbb  coastal_flow.hds  coastal_flow.pcg 
spec_01.mv

PGI$ ../../../source/swt_v4.exe seawat.nam  (source配下の作成した実行モジュールを実行)
(以下、省略)