Tutorials:ALPS Fortran Application Development/ja

From ALPS
Revision as of 07:58, 1 May 2013 by Wistaria (talk | contribs)

Jump to: navigation, search

ALPS FortranはALPSのFortranインターフェースモジュールです。ALPS Fortranを使用し、いくつかの必要なサブルーチンを実装することで、容易にALPS上でFortranコードを実行することができます。 本章ではALPS上で動作するFortranコードを書くための手順を説明します。また、既存のFortranコードをALPS Fortranに移植する手順やビルド設定ファイル(CMakeList.txt)の書き方についても本章で説明します。

以下の説明で使用するコードは、ALPSのチュートリアル[tutorials/alpsize-11-fortran-ising]に含まれています。

ALPS Fortranの概要

ALPS本体、ALPS Fortran及びFortranで記述されたユーザーアプリケーションの関係を以下に示します。


ALPS 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ソースコードに含まれるチュートリアル[tutorials/alpsize-11-fortran-ising]のファイルを使用します。移植作業の準備として、[tutorials/alpsize-11-fortran-ising]フォルダ内の以下のファイルを作業ディレクトリにコピーしてください。

  • ising_original.f:移植元のソースコード
  • template.f90:ALPS Fortranアプリケーションのソースコードテンプレート
  • ising_impl.f90:移植後のコード
  • ising.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の各ブロックで行われている処理を、サブルーチンに割り当てていきます。本節では、移植後のサンプルとして[ising_impl.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:

ising.Cについて 

ising.Cはアプリケーションのエントリポイントになるため、必須のファイルです。ただし、main関数については内容を変更する必要はありません。アプリケーション設定に関しては#サブルーチン呼び出しの流れを参照の上、必要に応じて変更してください。

CMakeLists.txtについて 

CMakeLists.txtを#Fortran コードの書き方を参照の上、変更してください。以下はCMakeLits.txtの例です。


    1: 	cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
    2: 	project(alpsize NONE)
    3: 	
    4: 	# find ALPS Library
    5: 	find_package(ALPS REQUIRED PATHS ${ALPS_ROOT_DIR} $ENV{ALPS_HOME} NO_SYSTEM_ENVIRONMENT_PATH)
    6: 	message(STATUS "Found ALPS: ${ALPS_ROOT_DIR} (revision: ${ALPS_VERSION})")
    7: 	include(${ALPS_USE_FILE})
    8: 	
    9: 	# enable C, C++, and Fortran compilers
   10	: enable_language(C CXX Fortran)
   11	: set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_C_FLAGS}")
   12: 	
   13	: # rule for generating ising program
   14	: add_executable(ising ising.C ising_impl.f90)
   15	: target_link_libraries(ising ${ALPS_LIBRARIES} ${ALPS_FORTRAN_LIBRARIES})