Fortran 勉強会 第 5 回 辻野智紀
今回のお品書き サブルーチンの分割コンパイル ライブラリ 静的ライブラリ 動的ライブラリ モジュール
その前に 以下の URL から STPK ライブラリをインストールしておいて下さい. http://www.gfd-dennou.org/library/davis/stpk 前回参加された方はインストール済みのはず.
サブルーチンの分割コンパイル
サブルーチンの独立化 サブルーチンはメインプログラムとは別のファ イルに記述可能. メインプログラムとは独立に開発が可能. サブルーチンが独立でない場合 ( プログラム A, B はサブルーチン A を call しているとする.) プログラム + サブルーチン A A サブルーチンの修正が生じると プログラム + サブルーチン A A プログラム + サブルーチン B A 両方修正しないとダメ!! プログラム + サブルーチン B A
サブルーチンの独立化 サブルーチンはメインプログラムとは別のファ イルに記述可能. メインプログラムとは独立に開発が可能. サブルーチンが独立である場合 ( プログラム A, B はサブルーチン A を call しているとする.) プログラム A サブルーチンの修正が生じると プログラム A プログラム B プログラム B サブルーチン A サブルーチンファイルを修正するだけ!! サブルーチン A
ソースファイルから実行ファイルを コンパイル 作るには... 人間が作成したプログラムの設計図を計算機がわかる形に変換する作業. この作業で作成されるファイルをオブジェクトファイル ( 拡張子.o ), コンパイルを行うソフトウェアをコンパイラと呼ぶ. リンク この段階ではプログラムは実行できない. オブジェクトファイルにライブラリ ( 後述 ) 等のプログラムを実行するために必 要なその他ファイルをつなげる作業. この作業で作成されるファイルはオブジェクトファイルか実行形式のファイル. リンクを行うソフトウェアをリンカと呼ぶ. よく使われる コンパイルする というのは, コンパイル + リンク = 実行ファイルの作成 を指している.
分割コンパイルの方法 メインプログラムのソースファイル main.f90 ifort -c main.f90 メインプログラムのオブジェクトファイル main.o サブルーチン A のソースファイル sub.f90 ifort -c sub.f90 コンパイル サブルーチン A のオブジェクトファイル sub.o ライブラリファイル libm.a ( コンパイラ標準提供も含む ) リンク ifort main.o sub.o -lm -o main オプション -l = ライブラリファイルの陽的な指定. 直後に来る文字はライブラリファイル名の先頭 3 文字と拡張子を除いた文字. メインプログラム main
実習 1 前回作成したガウスの消去法のサブルーチンを別ファイルに記述し, 分割コンパイルを行って実行ファイルを作成してみましょう.
ライブラリ モジュール
ライブラリファイルとは サブルーチン 関数を 1 つにまとめたもの. サブルーチンを独立化させて, 分割コンパイルはできたが, サブルーチンファイルの数が多くなるとコンパイルが面倒. 利点 コンパイル時間の短縮. 先にサブルーチンファイルだけコンパイルしておけば, メインファイルを書き換えたときにサブルーチンファイルも再コンパイルする必要はない. 汎用性が高ければ パッケージ として関数群を提供可能. lapack, linpack など. 2 つの形 静的ライブラリ 動的ライブラリ
静的ライブラリ オブジェクトファイルを 1 つにまとめたもの. リンク時にオブジェクトファイルそのものを実行ファイルにリンクする ( 実行ファイルを生成するときにオブジェクトファイルも組み込む ). 慣習的な命名規則 先頭 3 文字 lib, 拡張子.a 利点? バージョンを固定できる. 欠点? 一度作成したライブラリファイルはそのオブジェクトファイルをコンパイルした時点のもので固定される ( オブジェクトファイルが変化しても変わらない ). 実行ファイルの容量が大きくなる.
静的ライブラリ ライブラリのソースファイル (Ver.1.0) libtest.a (Ver.1.0) このバージョンでのオブジェクトファイルの情報をすべて所持. ソースが変更される libtest.a を利用しているプログラム ライブラリのソースファイル (Ver.2.0) 静的ライブラリはオブジェクトファイルごとまとめられているので, それを利用しているプログラムはソースの変更があっても影響されない. libtest.a (Ver.1.0) 再コンパイルしなければ Ver.1.0 のまま libtest.a を利用しているプログラム (Ver.1.0 で実行される )
動的ライブラリ オブジェクトファイルの名前を1つにまとめたもの. リンク時にはオブジェクトファイルの場所と名前を実行ファイルにリンクする. 実行ファイルが起動してから各オブジェクトファイルを参照. 慣習的な命名規則 先頭 3 文字 lib, 拡張子.so 利点? 実行ファイルの容量が ( 静的ライブラリに比べて ) 小さくなる. バージョン変化への対応が容易 ( 名前を変えるだけ ). 欠点? 一度作成したライブラリファイルはそのオブジェクトファイルの内容が変化すれば自動的に変化する. バージョン変化によってそれを参照しているプログラムに影響. シンボリックリンク等で対応可能.
動的ライブラリ ライブラリのソースファイル (Ver.1.0) オブジェクトファイル (Ver.1.0) ソースが変更される libtest.so (Ver.1.0) オブジェクトファイルの名前をまとめているだけ libtest.so を利用しているプログラム オブジェクトファイル (Ver.2.0) ライブラリのソースファイル (Ver.2.0) 動的ライブラリはオブジェクトファイルの名前だけリンクしているので, それを利用しているプログラムはソースの変更によって自動的に置き換わる. libtest.so (Ver.2.0) libtest.so を利用しているプログラム (Ver.2.0 で実行される )
モジュール Fortran 90 から追加された機能. 各要素 ( 変数, 定数, 型, 手続き等 ) をまとめることが可 能. 各モジュールに含まれる要素はプログラム内で陽に指定 (use) されないと使用できない. 非常に有用な機能. あるサブルーチンを使いたければ, そのサブルーチンがまとめられているモジュール名を指定しないと使えない. 関数群としてだけではなく, 定数集としても使える.
モジュールの書き方 module モジュール名 use 別モジュール! 別モジュールを組み込むことも可能. implicit none ( もしあれば ) 変数の定義 contains subroutine サブルーチン名 end subroutine サブルーチン名 end module モジュール名
モジュールの使い方 program メインプログラム名 use モジュール名 implicit none 変数の定義処理! モジュール内に含まれている手続き等を call end program
ライブラリ モジュールの コンパイル リンク方法 メインプログラム : main.f90 モジュールプログラム : module.f90 ライブラリファイル : libtest.a $ ifort -c main.f90 オブジェクトファイル main.o 生成. ifort -c module.f90 オブジェクトファイル module.o, モジュールファイル module.mod 生成. ifort -I./ main.f90 module.o -o main -ltest 実行ファイル main 生成.
コンパイルオプションまとめ コンパイル時に用いるオプション -c : コンパイルのみ行う. -o : 実行ファイルの名前. 省略した場合, a.out が生成. -l( エル ) : ライブラリファイルのリンク. 命名規則 : ライブラリファイル名の先頭 3 文字と拡張子を省略した文字 (libtest.a なら -ltest ). ファイルの位置指定. -I( アイ ) : モジュールファイル. -L : ライブラリファイル.
例題 以下をコンパイル, リンクして実行形式ファイルを作成する. メインプログラム : カレントディレクトリの main.f90 ライブラリファイル : /usr/local/lib/libtest.a モジュールプログラム : カレントディレクトリの mo.f90 作成までの流れ コンパイル ifort -c main.f90 ifort -c mo.f90 リンク 注意 ifort -I./ main.o mo.o -L/usr/local/lib -ltest -o main ライブラリファイルをリンクする時は, 必ず参照しているファイルの後にオプション記述すること.
実習 2 STPK ライブラリのディレクトリに demo/unit があるので, fft_test.f90 ファイルをコンパイルして実行ファイル fft_test を作成し, プログラムを実行してみましょう. コンパイル時に, STPK ライブラリをリンクします. ライブラリやモジュールファイルの位置を間違えないよ うに... 詳細は配布資料参照.
実習 3 ~ より実用的な使用 ~ サンプルデータは CReSS の計算結果の隣接 3 時刻 の 3 次元風速データである. サンプルプログラム sample.f90 はこのデータをもとに, 任意の点から流跡線を計算するプログラムである. このプログラムをコンパイルし, 実行ファイルを作成し ましょう. 実行して任意の点での流跡線を計算し, 結果をプロット してみましょう. 流跡線の計算結果はテキスト形式で出力されます. 詳細は配布資料参照.
ctl ファイルと流跡線の計算開始位置を指定. Grads の ctl ファイルから x, y, z の座標軸データを取得. Grads の ctl ファイルから 3 次元速度データ u, v, w のデータを取得. 速度場データを元に流跡線解析を実行. trajx, trajy, trajz に流跡線の x,y,z データが格納される.
実習 4 problem.f90 は実習 3 で用いたサンプルデータの 1 時刻における鉛直第 1 層目の水平収束を計算する書きかけのプログラムである. このプログラムを完成させ, 水平収束を計算し, 結果を図化しましょう. 詳細は配布資料参照.
参考資料 http://docs.oracle.com/cd/e19205-01/820-1203/aeudq/index.html Fortran プログラミングガイド (Oracle) http://www.nag-j.co.jp/fortran/index.html Fortran 入門 (NAG) http://www.atmarkit.co.jp/flinux/rensai/buildlamp/l amp_07/07_1.html ダイナミックリンクとスタティックリンク (@IT) http://www.gfd-dennou.org/library/davis/stpk/ 数値解析ライブラリ (STPK)