Windows 10 Pro の WSL2 の Ubuntu18.04LTSで,Intel Fortran (ifort) version 19.1.2.275,gfortran 7.5.0 (gfortran),および NAG Fortran 7.0 (nagfor) を使用し,沿岸海洋環境数値モデルコードのコンパイルで出会った Warning や Error と対応方針の備忘録です.Libraryは用いず,Fortranソースコードのみからなるプログラムを想定しています.NetCDFを用いて検証したかったのですが,コンパイラ毎に Library を用意するのは大変なので,NetCDFへのリンクの有無をプリプロセッサで制御できるようにし,本記事では外して検証しています.なお,本記事はあくまで個人で開発しているシリアル(並列化されていない)のプログラムを用いた実験結果で,一般性はあまりありません.
bashの環境変数の PATH 設定は full path とします(make で見つけられないため).
結論として,NAG Fortran のコンパイラは未定義(初期化忘れ等)の発見が秀逸で,デバッグに最も威力を発揮しました.
Makefileは以下の様なものを準備しました.
.SUFFIXES : .o .f90
#FLAG_1 = -DNETCDF_OUT
FC = ifort
#FC = gfortran
#FC = nagfor
CPP = icc -E
CPPFLAGS = -P -traditional
CPPARGS = $(CPPFLAGS) $(FLAG_1)
### Intel Fortran
FFLAGS = -auto -heap-arrays -ftrapuv -check all -warn -stand -fpe0 -traceback -g
#FFLAGS = -O2 -fp-model precise
### gfortran
#FFLAGS = -fbounds-check -O -Wuninitialized -fbacktrace
### NAG Fortran
#FFLAGS = -C=undefined -w=unused
TARGET = teem.exe
.f90.o :
$(FC) $(FFLAGS) -c $<
OBJS = mod_util.o mod_globals.o mod_interface.o mod_grid.o mod_grid_bed.o mod_output.o mod_temperature.o mod_salinity.o mod_velocity.o mod_eco_water_param.o mod_eco_bed_param.o mod_eco_flux_param.o teem_flux.o teem_water.o teem_bed.o teem_wavehindcast.o teem_main.o matrix_solver.o matrix_solver_bed.o bcond_surface_stress.o bcond_discharge.o bcond_bed_stress.o bcond_tide.o scalar_common.o teem_flow.o heat_flux.o coriolis.o etc.o bcond_met.o vdiffusion.o hdiffusion.o turbulence_model.o
#LDFLAGS = "${HOME}/local/netcdf4-intel-fortran/4.5.3/lib"
#INCLUDES = "${HOME}/local/netcdf4-intel-fortran/4.5.3/include"
#LIBS = -lnetcdff
LDFLAGS =
INCLUDES =
LIBS =
.F.o :
$(CPP) $(CPPARGS) $*.F > $*.f90
# $(FC) $(FFLAGS) -I$(INCLUDES) -c $*.f90
$(FC) $(FFLAGS) -c $*.f90
# rm -f *.f90
$(TARGET) : $(OBJS)
# $(FC) -o $@ $(OBJS) -L$(LDFLAGS) $(LIBS)
$(FC) -o $@ $(OBJS) $(LIBS)
run :
./$(TARGET) <./input/in2000m1999_1.dat
clean :
rm -f $(OBJS) $(TARGET) *.mod *.f90
Intel Fortran (ifort)
オプション選択と計算結果への影響
標準的なオプションとして以下を採用しています.テストに用いたコードでは -O2
と -O3
の差はないようでした.
FFLAGS = -O2 -fp-model precise # 標準
FFLAGS = -O2 -fp-model precise -traceback # 実行時エラー情報取得
FFLAGS = -auto -ftrapuv -check all -warn -stand -traceback # デバッグ時
FFLAGS = -auto -ftrapuv -check all -warn -stand -traceback -g # デバッグ時 debugger利用
コンパイルオプションの異なる2つの実行形式を用意し,計算結果の実数配列値の差の絶対値の和をとり,チェックしたところ,以下の様になりました.
-O2 VS -O3 # No difference
-O2 VS -O2 -fp-model precise # Significant difference
-O2 -fp-model precise VS -O2 -fp-model precise -fpe0 # No difference
-O2 -fp-model precise VS -O2 -fp-model precise -fpe0 -traceback # No difference
-O2 -fp-model precise VS -O2 -fp-model precise -fpe0 -traceback -xHost # Significant difference
結論として,-fp-model precise
の有無と -xHost
の有無が結果に大きく影響しました.テストケースは1年分の境界条件を用意し,沿岸海洋環境の変動を時々刻々再現するもので,同一の境界条件を用いて複数年の計算を実施し,平衡解(に近いもの)を得ようとするものです.1年程度の計算ではオプションによる差は軽微ですがが,10年分計算すると結構変わります.
Warning への対応
forrtl: warning (406): fort: (1): In call to MYFUNC, an array temporary was created for argument #1 参考
実引数 Array(1,1:10) を仮引数 Dummy(1:10) で受け取る場合はtemporary arrayが作成され,性能が劣化するようです.実引数の配列のメモリアクセスが不連続なためです.
Warning #5268: Extension to standard: The text exceeds right hand column allowed on the line.
1行132桁以内とする
Warning #8889: Explicit declaration of the external attribute is required
外部プロシージャのインターフェースを用意することで対応します.
デバッガー gdb
コンパイルオプション -g
を追加してコンパイルを実行し,実行形式が teem.exe
,標準入力に与えるファイルが ./input/in.dat
とします.デバッガを実行すると詳細なエラー情報が表示されるはずです.
$ gdb teem.exe # gdb 実行形式
(gdb) run <./input/in.dat # run [< 標準入力用のファイル]
抜けるには quit
と入力します.
Tips
NAG Fortran のおかげで変数の値が未定義のエラーがなくなった後で,ifort で -auto
を追加してコンパイル・実行すると(-auto以外のオプションでは問題なく実行できていました),forrtl: severe (174): SIGSEGV, segmentation fault occurred
となりました.デバッガで調べたところ,以下のようなエラーでした.
Program received signal SIGSEGV, Segmentation fault.
0x00000000004ebe27 in teem_ecosystem_water::teem_eco_water_run (
lout3d=<error reading variable: Cannot access memory at address 0xcccccccccccccccc>,
tempt=<error reading variable: value requires 166320 bytes, which is more than max-value-size>,
スタック領域の不足を疑い,$ ulimit -s unlimited
としたところ,問題なく実行できました.一方,コンパイルオプションの -heap-arrays
を加えてコンパイルしても,このエラーは解消されませんでした.
NAG Fortran (nagfor)
トライアルではじめて利用させていただきました.強力なプログラムチェック機能 が売りとのことでしたが,それを実感し,感動しました.
オプション選択と計算結果への影響
NAG Fortran は未定義(初期値設定忘れ)の変数を発見する性能が秀逸です.デバッガーなしで実行時に問題箇所を指摘してくれました.配列の一部の値の指定漏れを指摘したのは NAG Fortran だけでした.
FFLAGS = -C=undefined -w=unused # デバッグ時
Warning への対応
Questionable: ###.f90, line ###: DO index variable ### is not a local variable (it is from module ###)
module procedure内のDOループ変数を(行数節約のため)module変数として定義した場合に現れます.素直に各procedure内で局所変数として定義するのがよいでしょう.
その他
Fortran Builder をWindowsにインストール後,WSL2-Ubuntu の bashターミナルを立ち上げるとsyntaxエラーが発生しました.原因はWindowsのPATHが自動的に取り込まれる際,(x86)のように括弧を含むPATHを解釈できないためでした.Fortran Builderのデフォルトのインストール先は(x86)を含むフォルダ名で,これを適切に変更すれば回避できます.また,Fortran Builder の nagfor.exe を WSL2 の Ubuntuで使えないか試しましたがうまくいきませんでした.本記事はLinux版を使用しました.
The GNU Fortran (gfortran)
NAG Fortran を使用する前にgfortranを使ってみました.Intel Fortranよりも未定義変数を見つける性能が優れていると感じました.
FFLAGS = -fbounds-check -O -Wuninitialized -fbacktrace
参考資料
- Metcalf, M., Reid, J. and Cohen, M. Modern Fortran explained, Oxford University Press, 2018.
- Markus, A. Modern Fortran in Practice, Cambridge University Press, 2012.
- Brainerd, W. S. Guide to Fortran 2008 Programming, 2nd edition, Springer, 2015.
- Curcic M. Modern Fortran - Building efficient parallel applications -, Manning, 2020.
- Chirila, D. B. and Lohmann, G. Introduction to Modern Fortran for the Earth System Sciences, Springer, 2015.
- 牛島省.数値計算のためのFortran90/95プログラミング入門(第2版),森北出版,2020.
- 暗黙の型宣言編著.Fortranによる実践オブジェクト指向プログラミング,2018.
- NAG Fortran コンパイラ 7.0 マニュアル
- Damian Rouson This is not Your Parents' Fortran: A scalable, Parallel, Functional, OO PDE Solver
- Wikipedia: Partitioned global address space (PGAS) ([和訳](https://www.deepl.com/translator#en/ja/In%20computer%20science%2C%20a%20partitioned%20global%20address%20space%20(PGAS)%20is%20a%20parallel%20programming%20model.%20It%20assumes%20a%20global%20memory%20address%20space%20that%20is%20logically%20partitioned%20and%20a%20portion%20of%20it%20is%20local%20to%20each%20process%2C%20thread%2C%20or%20processing%20element.%5B1%5D%20The%20novelty%20of%20PGAS%20is%20that%20the%20portions%20of%20the%20shared%20memory%20space%20may%20have%20an%20affinity%20for%20a%20particular%20process%2C%20thereby%20exploiting%20locality%20of%20reference.%20The%20PGAS%20model%20is%20the%20basis%20of%20Coarray%20Fortran%2C%20Unified%20Parallel%20C%2C%20Split-C%2C%20Fortress%2C%20Chapel%2C%20X10%2C%20UPC%2B%2B%2C%20Coarray%20C%2B%2B%2C%20Global%20Arrays%2C%20DASH%20and%20SHMEM.%20In%20standard%20Fortran%2C%20this%20model%20is%20now%20an%20integrated%20part%20of%20the%20language%20(as%20of%20Fortran%202008).%20PGAS%20attempts%20to%20combine%20the%20advantages%20of%20a%20SPMD%20programming%20style%20for%20distributed%20memory%20systems%20(as%20employed%20by%20MPI)%20with%20the%20data%20referencing%20semantics%20of%20shared%20memory%20systems.%20This%20is%20more%20realistic%20than%20the%20traditional%20shared%20memory%20approach%20of%20one%20flat%20address%20space%2C%20because%20hardware-specific%20data%20locality%20can%20be%20modeled%20in%20the%20partitioning%20of%20the%20address%20space.%0A%0AA%20variant%20of%20the%20PGAS%20model%2C%20asynchronous%20partitioned%20global%20address%20space%20(APGAS)%20permits%20both%20local%20and%20remote%20asynchronous%20task%20creation.%5B2%5D%20Two%20programming%20languages%20that%20use%20this%20model%20are%20Chapel%20and%20X10. www.DeepL.com/Translator(無料版)で翻訳しました。))