Tutorials:ALPS Fortran Application Development
Languages: |
English • 日本語 (ja) • 繁體中文 (zh-tw) • 简体中文 (zh) |
ALPS FortranはALPSのFortranインターフェースモジュールです。ALPS Fortranを使用し、いくつかの必要なサブルーチンを実装することで、容易にALPS上でFortranコードを実行することができます。 本章ではALPS上で動作するFortranコードを書くための手順を説明します。また、既存のFortranコードをALPS Fortranに移植する手順やビルド設定ファイル(CMakeList.txt)の書き方についても本章で説明します。
ALPS Fortranの概要
ALPS本体、ALPS Fortran及びFortranで記述されたユーザーアプリケーションの関係を以下に示します。
ALPS FortranはALPS本体からの呼び出しを受け、必要に応じてユーザーアプリケーションのサブルーチンをコールします。これにより、ALPSはC++で実装されたアプリケーションと同様にFortranで実装されたアプリケーションを制御できます。
一方で、ALPS FortranはALPS本体の機能を呼び出すサブルーチンを提供しており、ユーザーアプリケーションは通常のFortranサブルーチンを呼び出すのと同様にALPSの機能を利用することができます。
サブルーチン呼び出しの流れ
ALPS Fortranを使用した時のALPS / ユーザーアプリケーションの呼び出しの流れは以下のようになります。下図中の各サブルーチンについては[2.3.3]をご参照ください。
Fortran コードの書き方
ALPS Fortranを利用したアプリケーションを実装するには、最低限、下記2つのソースコードを準備する必要があります。
- アプリケーションのエントリポイント(main関数)が実装されたC++ソースコード
- ALPS Fortranのルールに従って実装されたFortranソースコード
エントリポイント
ここではmain関数(アプリケーションのエントリポイント)、ワーカー名等のアプリケーション設定を記述します。main関数は決まった内容を記述するだけであり、通常は変更の必要はありません。
アプリケーションの設定ついては以下の設定用コードを記述します。
- アプリケーションのバージョン番号
- アプリケーションのコピーライト
- ワーカー名
- エバリュエータ名
以下に、C++ソースコードの例を示します。
1: #include <alps/parapack/parapack.h> 2: #include "fortran_wrapper.h" 3: 4: // バージョンの設定 5: PARAPACK_SET_VERSION("my version"); 6: 7: // コピーライト表示の設定 8: PARAPACK_SET_COPYRIGHT("my copyright"); 9: 10: // ワーカー名の設定 11: PARAPACK_REGISTER_WORKER(alps::fortran_wrapper, "worker name</span>"); 12: 13: // エバリュエータの設定 14: PARAPACK_REGISTER_EVALUATOR(alps::parapack::simple_evaluator, 15: "evaluator name"); 16: 17: /** 18: * アプリケーションのエントリポイント 19: */ 20: int main(int argc, char** argv) 21: { 22: return alps::parapack::start(argc, argv); 23: }
上記例の内、変更が必要なのは赤字の部分になります。
Fortranソースコード
Fortranソースコードの内容は計算ロジックが主になります。ただし、ALPS Fortranを使用するためにいくつかのサブルーチンを必ず実装する必要があります。 また、計算結果の保存やパラメータの読み込み等を行う際はALPS Fortranが提供するサブルーチンを経由してALPS本体の機能を呼び出します。
必須サブルーチン
ユーザーアプリケーションがALPSからの制御を受けるためには、Fortranソースコード内にいくつかのサブルーチンが必要になります。後述する各サブルーチンの説明をご一読の上、適切な実装を行ってください。これらを省略するとリンクエラーとなり、ビルドできません。 これらのサブルーチンを実装する際は、以下の点に留意して実装してください。
- 全てのサブルーチンは引数として「integer(2) :: caller」が渡されます。callerはALPS本体の機能を利用するために内部で利用される変数です。したがって、callerの値を書き換えないでください。callerの値が変更された場合の動作は未保証になります。
- 各サブルーチンでは「alps/fortran/alps_fortran.h」をインクルードしてください。このファイルはFortranコードからALPS本体の機能を呼び出す際に必須になります。
したがって、必須サブルーチンにつきましては、サブルーチンのシグネチャ直下に以下の3行が必要になります。
1: subroutine alps_init(caller) 2: implicit none 3: include "alps/fortran/alps_fortran.h" 4: integer :: caller(2) 5: 6: ! --- 以下、略 --- !
alps_init(caller)
- 引数
型 | 名前 | I/O | 説明 |
integer | caller(2) | in | 内部変数 |
- 説明
本サブルーチンは計算が行われる前に一度だけコールされます。ここでは、配列の確保等、アプリケーションの初期化処理を行います。 本サブルーチンは入力パラメータ1セットにつき、1回のみコールされます。
alps_init_observables(caller)
- 引数
型 | 名前 | I/O | 説明 |
integer | caller(2) | in | 内部変数 |
- 説明
本サブルーチンはalps_initがコールされた後に1度だけコールされます。ここでは、alps::ObservableSetの初期化を行います。本サブルーチンは入力パラメータ1セットにつき、1回のみ呼び出されます。 なお、alps::ObservableSetの詳細につきましては、ALPSのHPをご参照ください。
alps_run(caller)
- 引数
型 | 名前 | I/O | 説明 |
integer | caller(2) | in | 内部変数 |
- 説明
計算ロジックを実装します。本サブルーチンは後述するalps_progressが1.0以上を返すまで、ALPSから繰り返し呼び出されます。したがって、本サブルーチン内ではループを記述する必要はありません。 なお、スレッド並列実行時には、本サブルーチンはマルチスレッド下で動作します。そのため、スレッド並列で利用する際にはスレッドセーフな実装を行う必要があります。
alps_progress(prgrs, caller)
- 引数
型 | 名前 | I/O | 説明 |
real*8 | prgrs | out | アプリケーションの進捗状態(0.0 ≦ prgrs) |
integer | caller(2) | in | 内部変数 |
- 説明
本サブルーチンはalps_runが実行された後にALPSからコールされ、アプリケーションの進捗状態をALPSに返します。prgrsが1.0未満の間、ALPSは繰り返しalps_runをコールします。prgrsに1.0以上の値を代入すると、ALPSは計算が完了したとみなし、アプリケーションを終了します。 なお、スレッド並列実行時には、本サブルーチンはマルチスレッド下で動作します。そのため、スレッド並列で利用する際にはスレッドセーフな実装を行う必要があります。
alps_is_thermalized(thrmlz, caller)
- 引数
型 | 名前 | I/O | 説明 |
real*8 | thrmlz | out | サーマライズ終了フラグ(0:未 / 1:完) |
integer | caller(2) | in | 内部変数 |
- 説明
本サブルーチンはalps_runが実行された後にALPSからコールされ、サーマライズの完了/未完了を返します。thrmlzの値が0の場合、アプリケーションがサーマライズ中であるとみなし、計算結果を保存しません。thrmlzが1になるとサーマライズが完了したとみなし、計算結果の保存が開始されます。 なお、スレッド並列実行時には、本サブルーチンはマルチスレッド下で動作します。そのため、スレッド並列で利用する際にはスレッドセーフな実装を行う必要があります。
alps_finalize(caller)
- 引数
型 | 名前 | I/O | 説明 |
integer | caller(2) | in | 内部変数 |
- 説明
本サブルーチンは計算が完了した後(alps_progressが1.0以上を返した後)に1度だけコールされます。ここでは、alps_initで確保したメモリの解放等の終了処理を行います。
alps_save(caller)
- 引数
型 | 名前 | I/O | 説明 |
integer | caller(2) | in | 内部変数 |
- 説明
alps_runが実行された後にALPSからコールされます。ここではALPS本体の機能を利用してリスタートファイルの保存を行います。スレッド並列実行時には、本サブルーチンはマルチスレッド下で動作するため、スレッド並列で利用する際にはスレッドセーフな実装を行う必要があります。
alps_load(caller)
- 引数
型 | 名前 | I/O | 説明 |
integer | caller(2) | in | 内部変数 |
- 説明
本サブルーチンはアプリケーションがリスタートされたときに1度だけコールされます。ここでは、ALPS本体の機能を利用して、保存されたリスタートファイルをロードします。
ALPS Fortran提供サブルーチン
ユーザーアプリケーションからALPSの機能を呼び出す際は、ALPS Fortranが提供するサブルーチンをコールします。 これらのサブルーチンは引数として「integer(2) :: caller」が必要になります。callerはALPS Fortranから渡される内部変数であり、必須サブルーチン(2.2.3.1)に引数で渡された変数をそのまま提供サブルーチンに渡す必要があります。
alps_get_parameter(data, name, type, caller)
- 引数
型 | 名前 | I/O | 説明 |
- | data | out | 取り出した値の格納先 |
character | name(*) | in | 取り出したいパラメータの名前 |
integer | type | in | dataの型 |
integer | caller(2) | in | 内部変数 |
- 説明
名前を指定して、ALPSからパラメータを受け取ります。パラメータの名前、型、要素数はそれぞれname、type、countで指定します。 本サブルーチンは主にalps_init内で配列や変数の初期化に利用されます。なお、typeが取りうる値はalps_fortran.hに定義されています。
alps_parameter_defined(res, name, caller)
- 引数
型 | 名前 | I/O | 説明 |
integer | res | out | パラメータ定義の有無(1:有 / 0:無) |
character | name(*) | in | パラメータの名前 |
integer | caller(2) | in | 内部変数 |
- 説明
nameで指定したパラメータがパラメータファイルに定義されているかどうかを返します。パラメータが定義されていればresに1が代入されます。定義されていなければ0が代入されます。 本サブルーチンは主にalps_init内で配列や変数の初期化に利用されます。
alps_init_observable(count, type, name, caller)
- 引数
型 | 名前 | I/O | 説明 |
integer | count | in | 保存される計算結果の要素数 |
integer | type | in | dataの型 |
character | name(*) | in | 保存したい計算結果(Observable)の名前 |
integer | caller(2) | in | 内部変数 |
- 説明
本サブルーチンは、alps_init_observable内でalps::ObservableSetにnameで指定されたObservableを登録するために使用します。 Observableの種類はcount及びtypeによって以下のように決定されます。
type | count | 対応するObservable |
ALPS_INT | 1 | IntObservable |
ALPS_INT | 1< | in |
ALPS_REAL | 1 | RealObservable |
ALPS_REAL | 1< | RealVectorObservable |
ALPS_DOUBLE_PRECISION | 1 | RealObservable |
ALPS_DOUBLE_PRECISION | 1< | RealVectorObservable |
alps_accumulate_observable(data, count, type, name, caller)
- 引数
型 | 名前 | I/O | 説明 |
- | data | in | 保存される計算結果 |
integer | count | in | 保存される計算結果の要素数 |
integer | type | in | dataの型 |
character | name(*) | in | 保存したい計算結果の名前 |
integer | caller(2) | in | 内部変数 |
- 説明
指定された名前のObservableにdata(= 計算結果)を保存します。本サブルーチンはalps_run内で計算結果を保存するために使用します。 count / name / type はinit_observableで指定したものと一致している必要があります。
alps_dump(data, count, type, caller)
- 引数
型 | 名前 | I/O | 説明 |
- | data | in | 保存する値 |
integer | count | in | 保存する値の要素数 |
integer | type | in | dataの型 |
integer | call(2) | in | 内部変数 |
- 説明
本サブルーチンは、alps_save内でリスタートファイルを保存するために使用します。alps_dumpを使用して保存した中断データはリスタート時に使用されます。
alps_restore(data, count, type, caller)
- 引数
型 | 名前 | I/O | 説明 |
- | data | out | ロードした値の格納先 |
integer | count | in | ロードする値の要素数 |
integer | type | in | dataの型 |
integer | caller(2) | in | 内部変数 |
- 説明
本サブルーチンは、alps_load内でリスタートファイルをロードするために使用します。リスタートファイル内にはalps_dumpで保存した順にデータが保存されます。したがって、alps_restoreでロードする際は保存時と同じ順番でデータを取り出してください。
ビルド設定ファイルの書き方
ユーザーアプリケーションはALPS同様、CMakeを使ってビルドします。以下はユーザーアプリケーションをCMakeでビルドするための設定ファイル(CMakeLists.txt)のサンプルです。
1: # CMakeList.txt 2: # CMakeを実行するための設定ファイル 3: 4: cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR) 5: 6: #プロジェクト名の設定 7: project(hello_sample) 8: 9: # find ALPS Fortran の設定 10: find_package(ALPS REQUIRED NO_SYSTEM_ENVIRONMENT_PATH) 11: message(STATUS "ALPS version: ${ALPS_VERSION}") 12: include(${ALPS_USE_FILE}) 13: 14: # 作成する実行ファイル名と必要なソースコード 15: add_executable(hello main.C hello_impl.f) 16: # 実行ファイル生成に必要な外部ライブラリ 17: target_link_libraries(hello ${ALPS_LIBRARIES} ${ALPS_FORTRAN_LIBRARIES})
上記例のうち、変更が必要なのは赤字の部分になります。
既存コードの移植
本節では、以下に示すisingプログラムを例に、既存のFortranアプリケーションをALPS上で動作させるための手順について説明します。
移植の準備
本節ではalps_fortran.tar.gzを解凍して生成されるtutorialフォルダ内のファイルを使用します。移植作業の準備として、tutorialフォルダ内の以下のファイルを作業ディレクトリにコピーしてください。
- ising_original.f:移植元のソースコード
- template.f90:ALPS Fortranアプリケーションのソースコードテンプレート
- main.C:アプリケーションのエントリポイント
- CMakeList.txt:CMakeList.txtのテンプレート
template.f90にはFortranでALPSアプリケーションを実装する際に必要となる全てのサブルーチンが定義されています。そのため、新規アプリケーションを開発する際はtemplate.f90を元に開発進めることができます。
なお、移植元コードの大まかな構造は以下の通りです。
処理内容 | |
4-7 | 変数の宣言、初期化 |
8-23 | 配列要素の初期化 |
24-47 | メインループ |
25-34 | 計算 |
36 | サーマライズチェック |
37-46 | 計算結果の保存 |
48-58 | 結果の出力 |
Fortranコードの移植
Fortranコードの移植では、ising_original.fの各ブロックで行われている処理を、サブルーチンに割り当てていきます。本節では、移植後のサンプルとしてtutorial/alps_ising.f90を例に説明します。
変数の宣言
ising_original.f内で宣言されている各変数はALPS移植時にはmodule化します。ALPSに移植するためには処理単位ごとにサブルーチン化する必要があるため、各サブルーチンから変数にアクセスできるようにするためです。
- 移植元
4: DIMENSION IS(20,20),IP(20),IM(20),P(-4:4),A(4) 5: C PARAMETERS 6: DATA TEMP/2.5/, L/10/, MCS/1000/, INT/1000/ 7: DATA IX/1234567/, V0/.465661288D-9/
- 移植後
1: module ising_mod 2: implicit none 3: real, parameter :: V0 = .465661288D-9 4: 5: integer, allocatable, dimension(:) :: IP, IM 6: integer, allocatable, dimension(:,:) :: IS 7: real*8, allocatable, dimension(:) :: P 8: integer :: K, MCS, INT, L, IX 9: real :: TEMP 10: end module ising_mod 11:
配列IP、IM、IS、Pはalps_init内で初期化するため、ここでは移植後はサイズ指定しません。また、移植元コードの配列Aは結果保存用の配列ですが、移植後はALPSの仕組みを利用します。したがって移植後のコードに配列Aは必要ありません。また、移植後の各変数の値は、パラメータファイルから取得します。
なお、移植後の変数Kは繰り返し回数をカウントするための変数です。移植後はdoループを使わずにKの値で繰り返し制御やサーマライズチェックを行います。
※本節ではMPI並列での実行を想定しているので、スレッドセーフについては考慮していません。
初期化処理
移植元コードの初期化処理は配列の各要素を初期化していますが、移植後コードでは初期化処理をalps_initサブルーチンで実行します。 最初にalps_get_parameterを使用して変数・配列の初期化を行い、その後配列要素の初期化を行います。また、移植後は結果保存用の配列を用意せず、alps_init_observableサブルーチン内で結果保存用のObservableを用意します。 なお、alps_init及びalps_init_observableはALPSから自動的にコールされるので移植後コード内でコールする必要はありません。
- 移植元
8: C TABLES 9: DO 10 I=-4,4 10: W=EXP(FLOAT(I)/TEMP) 11: 10 P(I)=W/(W+1/W) 12: DO 11 I=1,L 13: IP(I)=I+1 14: 11 IM(I)=I-1 15: IP(L)=1 16: IM(1)=L 17: C INITIAL CONFIGURATION 18: DO 20 I=1,L 19: DO 20 J=1,L 20: 20 IS(I,J)=1 21: C ACCUMULATION DATA RESET 22: DO 21 I=1,4 23: 21 A(I)=0.0
- 移植後(alps_init)
13: subroutine alps_init(caller) 14: use ising_mod 15: implicit none 16: include "alps/fortran/alps_fortran.h" 17: integer :: caller(2) 18: integer :: i, j 19: real*8 :: W 20: 21: call alps_get_parameter(TEMP, "TEMPERATURE", ALPS_REAL, caller) 22: call alps_get_parameter(L, "L", ALPS_INT, caller) 23: call alps_get_parameter(MCS, "MCS", ALPS_INT, caller) 24: call alps_get_parameter(INT, "INT", ALPS_INT, caller) 25: 26: allocate( IP(L) ) 27: allocate( IM(L) ) 28: allocate( P(-4:4) ) 29: allocate( IS(L, L) ) 30: 31: K = 0 32: IX = 1234567 33: 34: do i = -4, 4 35: W = exp(float(i)/TEMP) 36: P(i) = W / (W + 1/W) 37: end do 38: 39: do i = 1, L 40: IP(i) = i + 1 41: IM(i) = i - 1 42: end do 43: 44: do i = 1, L 45: do j = 1, L 46: IS(i, j) = 1 47: end do 48: end do 49: 50: IP(L) = 1 51: IM(1) = L 52: 53: return 54: end subroutine alps_init
移植後は21~24行目でalps_get_parameterをコールしており、ALPSを通してパラメータファイルの内容を取得しています。なお、34~51行目の処理は移植元と同じです。
- 移植後(alps_init_observables)
92: subroutine alps_init_observables(caller) 93: implicit none 94: include "alps/fortran/alps_fortran.h" 95: integer :: caller(2) 96: 97: call alps_init_observable(1, ALPS_REAL, "Energy", caller) 98: call alps_init_observable(1, ALPS_REAL, "Magnetization", caller) 99: 100: return 101: end subroutine alps_init_observables
移植後は計算結果の保存用バッファとして"Energy"及び"Magnetization"という名前でObservableを用意しています。移植元ではEnergy及びMagnetizationそれぞれについて総和と二乗和を計算していますが、これらの計算はObservableが自動的に行います。
計算及び結果保存
移植元コードではdoループ内(移植前25行目)で繰り返し計算を行っていますが、移植後はdoループを使わずにalps_run及びalps_progressサブルーチンを使用します。
- 移植前
24: C SIMULATION 25: DO 30 K=1,MCS+INT 26: KIJ=0 27: DO 31 I=1,L 28: DO 31 J=1,L 29: M=IS(IP(I),J)+IS(I,IP(J))+IS(IM(I),J)+IS(I,IM(J)) 30: KIJ=KIJ+1 31: IS(I,J)=-1 32: IX=IAND(IX*5*11,2147483647) 33: IF(P(M).GT.V0*IX) IS(I,J)=1 34: 31 CONTINUE 35: C DATA 36: IF(K.LE.INT) GOTO 30 37: EN=0 38: MG=0 39: DO 40 I=1,L 40: DO 40 J=1,L 41: EN=EN+IS(I,J)*(IS(IP(I),J)+IS(I,IP(J))) 42: 40 MG=MG+IS(I,J) 43: A(1)=A(1)+EN 44: A(2)=A(2)+EN**2 45: A(3)=A(3)+MG 46: A(4)=A(4)+MG**2 47: 30 CONTINUE
- 移植後(alps_run)
56: ! subroutine alps_run 57: subroutine alps_run(caller) 58: use ising_mod 59: implicit none 60: include "alps/fortran/alps_fortran.h" 61: integer :: caller(2) 62: integer :: i, j, M 63: real*8 :: EN, MG 64: 65: do i = 1, L 66: do j = 1, L 67: M = IS(IP(i), j) + IS(i, IP(j)) + IS(IM(i), j) + IS(i, IM(j)) 68: IS(i, j) = -1 69: 70: IX = IAND(IX * 5 * 11, 2147483647) 71: if(P(M).gt.V0*IX) IS(i, j) = 1 72: end do 73: end do 74: 75: EN = 0.0D0 76: MG = 0.0D0 77: do i = 1, L 78: do j = 1, L 79: EN = EN + IS(i, j) * (IS(IP(i), j) + IS(i, IP(j))) 80: MG = MG + IS(i, j) 81: end do 82: end do 83: 84: call alps_accumulate_observable(EN, 1, & ALPS_DOUBLE_PRECISION, "Energy", caller) 85: call alps_accumulate_observable(MG, 1, & ALPS_DOUBLE_PRECISION, "Magnetization", caller) 86: K = K + 1 87: 88: return 89: end subroutine alps_run
計算処理自体(65~82行目)は移植元と同じですが、移植後はalps_runが自動的に繰り返しコールされるので、移植前の25行目にあたるループは記述しません。その変わり、86行目で繰り返し回数をカウントします。 また、計算結果の保存はALPSの機能を使用します(84、85行目)。移植元では積算、二乗計算等を行っています(移植元43~46行目)が、これらはalps_accumulate_observableで自動的に行われます。
- 移植後(alps_progress)
103: ! alps_progerss 104: subroutine alps_progress(prgrs, caller) 105: use ising_mod 106: implicit none 107: include "alps/fortran/alps_fortran.h" 108: integer :: caller(2) 109: real*8 :: prgrs 110: 111: prgrs = K / (INT + MCS) 112: 113: end subroutine alps_progress
移植後は繰り返し計算の制御をalps_progressで行います。prgrsが1以上になるとalps_runがコールされなくなるので、カウンタ(K)の値を監視し、規定回数分実行されたらprgrsが1以上になるよう実装します。
サーマライズチェック
移植前のサーマライズチェックはメインループ内(36行目)で行われていますが、移植後はalps_is_thermalizedサブルーチンで行います。
- 移植前
36: IF(K.LE.INT) GOTO 30
- 移植後(alps_is_thermalized):
115: ! alps_is_thermalized 116: subroutine alps_is_thermalized(thrmlz, caller) 117: use ising_mod 118: implicit none 119: include "alps/fortran/alps_fortran.h" 120: integer :: caller(2) 121: integer :: thrmlz 122: 123: if(K >= INT) then 124: thrmlz = 1 125: else 126: thrmlz = 0 127: end if 128: 129: return 130: end subroutine alps_is_thermalized
移植後はalps_progress同様、カウンタ(K)の値からサーマライズのチェックを行います。thrmlzが1になるとサーマライズが完了したとみなされます。
結果の出力
ALPSを使用すると結果の後処理や出力は自動的に行われます。したがって、移植後は計算結果の後処理・出力用のコードは必要ありません。
- 移植前
48: C STATISTICS 49: DO 50 I=1,4 50: 50 A(I)=A(I)/MCS 51: C=(A(2)-A(1)**2)/L**2/TEMP**2 52: X=(A(4)-A(3)**2)/L**2/TEMP 53: ENG=A(1)/L**2 54: AMG=A(3)/L**2 55: WRITE(6,100) TEMP,L,ENG,C,AMG,X 56: 100 FORMAT(' TEMP=',F10.5,' SIZE=',I5, 57: * /' ENG =',F10.5,' C =',F10.5, 58: * /' MAG =',F10.5,' X =',F10.5)
- 移植後:該当コードなし
終了処理
移植前のコードではallocateを行っていないため終了処理がありません。しかし、移植後はalps_init内でallocateした領域を終了時に開放する必要があります。
- 移植前:該当コードなし
- 移植後(alps_finalize)
160: ! alps_finalize 161: subroutine alps_finalize(caller) 162: use ising_mod 163: implicit none 164: include "alps/fortran/alps_fortran.h" 165: integer :: caller(2) 166: 167: deallocate(IP) 168: deallocate(IM) 169: deallocate(P) 170: deallocate(IS) 171: 172: return 173: end subroutine alps_finalize
リスタート機能
ALPSを使用するとリスタートファイルの入出力機能(alps_save / alps_load)を実装するだけで、アプリケーションにリスタート機能を追加できます。移植元にはリスタート機能がありませんが、以下にALPSによるリスタートファイルの入出力機能の実装例を説明します。
- 移植前:該当コードなし
- 移植後(alps_save)
132: ! alps_save 133: subroutine alps_save(caller) 134: use ising_mod 135: implicit none 136: include "alps/fortran/alps_fortran.h" 137: integer caller(2) 138: 139: call alps_dump(K, 1, ALPS_INT, caller) 140: call alps_dump(IX, 1, ALPS_INT, caller) 141: call alps_dump(IS, L * L, ALPS_INT, caller) 142: 143: return 144: end subroutine alps_save
alps_saveではリスタートに必要なる変数のみをalps_dumpで書き出します。ここでは、カウンタ(K)及び計算途中のデータ(IX、IS)を書き出しています。
- 移植後(alps_load)
146: ! alps_load 147: subroutine alps_load(caller) 148: use ising_mod 149: implicit none 150: include "alps/fortran/alps_fortran.h" 151: integer :: caller(2) 152: 153: call alps_restore(K, 1, ALPS_INT, caller) 154: call alps_restore(IX, 1, ALPS_INT, caller) 155: call alps_restore(IS, L * L, ALPS_INT, caller) 156: 157: return 158: end subroutine alps_load
alps_loadではalps_saveで書き出した(alps_dump)順番で読み込む(alps_restore)する必要があります。 なお、ALPSアプリケーションをリスタートした場合、alps_loadが呼ばれる前にalps_initが呼ばれます。つまり、K、IX、ISのメモリ確保や他の変数の初期化はalps_init内で行われるので、alps_load内で初期化等を行う必要はありません。
マルチスレッド対応につて
ALPSアプリケーションをマルチスレッドで動作させる場合、Fortranコードをスレッドセーフな実装にする必要があります。本節で説明したtutorial.f90の場合、2.4.2で準備した変数をスレッドローカルにすることでマルチスレッドに対応することができます。
- 移植後(マルチスレッド版)
1: module ising_mod
2: implicit none
3: real, parameter :: V0 = .465661288D-9
4:
5: integer, allocatable, dimension(:) :: IP, IM
6: integer, allocatable, dimension(:,:) :: IS
7: real*8, allocatable, dimension(:) :: P
8: integer :: K, MCS, INT, L, IX
9: real :: TEMP
10: !$omp threadprivate (K, MCS, INT, TEMP, IP, IM, P, IS, IX, L)
11: end module ising_mod
12:
main.Cについて
main.Cはアプリケーションのエントリポイントになるため、必須のファイルです。ただし、main関数については内容を変更する必要はありません。アプリケーション設定に関しては#サブルーチン呼び出しの流れを参照の上、必要に応じて変更してください。
CMakeLists.txtについて
CMakeLists.txtを#Fortran コードの書き方を参照の上、変更してください。以下はCMakeLits.txtの例です。
1: cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR) 2: 3: project(tutorial) 4: 5: find_package(ALPS REQUIRED NO_SYSTEM_ENVIRONMENT_PATH) 6: message(STATUS "ALPS version: ${ALPS_VERSION}") 7: include(${ALPS_USE_FILE}) 8: 9: # 作成する実行ファイル名と必要なソースコード 10: add_executable(tutorial main.C tutorial.f90) 11: target_link_libraries(tutorial ${ALPS_LIBRARIES} ${ALPS_FORTRAN_LIBRARIES})