1 ==============================
2 Fortran90 Bindings for Charm++
3 ==============================
8 Charm++ is a parallel object language based on C++. The f90charm module
9 is to provide Fortran90 programs a f90 interface to Charm++. Using the
10 F90Charm interface, users can write Fortran90 programs in a fashion
11 similar to Charm++, which allows creation of parallel object arrays
12 (Chare Arrays) and sending messages between them.
14 To interface Fortran90 to Charm++ and thus obtain a parallel version of
15 your program you need to do the following things:
17 #. Write a Charm Interface file (extension .ci)
19 #. Write your F90 program with f90charmmain() as main program;
21 #. Write implementations of Chare entry methods in the F90 program;
23 #. Compile and Link with Charm’s Fortran library
30 Here we suppose you already know most concepts in Charm++ and have
31 done some Charm++ programming.
32 Unlike in C++, we don’t have classes in Fortran90. Thus, a Chare in
33 F90Charm is represented as a Fortran type structure. Here is an
36 .. code-block:: fortran
38 ! ## Just replace Hello throughout with your chare's name. ##
39 ! ## and add your chare's personal data below where indicated ##
40 ! ## Everything else remains the same ##
44 ! ## your chare's data goes here, the integer below is an example ##
49 TYPE (Hello), POINTER :: obj
55 You can think of this module as a Chare declaration. Type [Hello]
56 defines arbitrary user program data and HelloPtr defines the Chare
57 pointer which the Fortran program will use later to communicate with the
58 F90Charm runtime library. The [aid] is the handle of the array returned
59 by the F90Charm library, and the user shouldn’t change it.
61 In F90Charm as in Charm++, you need to write a .ci interface file so
62 that the Charm translator will generate helper functions. The syntax of
63 .ci files is the same as in Charm++, however, for F90Charm, there are
64 certain constraints. First, you don’t need to declare the main chare as
65 in Charm++. Second, F90Charm currently only supports up to 3D Chare
66 arrays, and you cannot define Chare, Group, and NodeGroup types. Third,
67 there are no message declarations in .ci files, all the entry functions
68 must be declared in the parameter marshalling fashion of Charm++.
69 Essentially, users can declare in .ci files readonly variables and 1-3D
70 chare arrays with parameter marshalled entry methods.
72 It is the programmer’s responsibility to write the implementation of
73 Chare entry methods. The decl and def files generated by Charm++’s
74 translator define the interface functions programmer need to write.
76 For each Chare defined in the .ci file, the user must write these
77 functions for F90Charm’s runtime:
79 ``SUBROUTINE <ChareName>_allocate(objPtr, aid, index)``
81 You can think of this function as a constructor for each array element
82 with array index [index]. For a 3D array, for example, you can replace
83 index in the example by a 3D array index [index1, index2, index3]. In
84 this function the user must allocate memory for the Chare’s user data
85 and perform any initialization.
87 For each Chare entry method you have declared, you should write the
88 corresponding Fortran90 subroutine for it:
90 ``SUBROUTINE <ChareName>_Entry_<EntryName>(charePtr, myIndex, data1, data2 ... )``
92 Note that the first argument is the Chare pointer as declared
93 previously, and the second argument is the array index which will be passed
94 from the Charm runtime. The rest of the parameters should be the same as
95 declared in the .ci file. For higher dimensional
96 arrays, replace ``myIndex`` by ``myIndex1, myIndex2`` for example.
98 On the caller side, the decl/def files generated by Charm++’s translator
99 also provide the following functions for Chare creation and remote method
100 invocation. For each Chare declared in .ci files, these subroutines are
101 generated for use in Fortran90 code:
103 ``<ChareName>_CkNew(integer n, integer*8 aid)``
105 This subroutine creates a chare array of size ``n``. For higher
106 dimensional array creation, specify one integer for each dimension. For
107 example, to create a 3D array:
109 ``<ChareName>_CkNew(integer dim1, integer dim2, integer dim3, integer*8 aid)``
111 For each entry method, a corresponding ``Invoke`` method is provided (1D
114 ``<ChareName>_Invoke_<EntryName>(charePtr, myIndex, data1, data2 ... )``
116 This subroutine will send a message to the array element with index
117 ``myIndex``. Similarly, for arrays with higher dimensions, replace ``myIndex``
118 by a corresponding number of array indices. Broadcasts are supported as
121 ``<ChareName>_Broadcast_<EntryName>(charePtr, data1, data2 ... )``
123 There are several others things you need to know.
125 First, as in Charm++, each .ci file will generate two header files:
126 .decl.h and .def.h. However, in Fortran90 charm, you are not able to
127 include these C++ files in Fortran90 code. Thus, currently, it is the user’s
128 task to write a short C++ file including these two headers files. You
129 should also provide definitions for readonly variables in this C++ file.
130 It can be as simple as this:
134 #include "hello.decl.h"
135 int chunkSize; // define readonly variables here
136 #include "hello.def.h"
138 In the future, this file could be generated automatically by the
141 Second, you can still use readonly variables as in Charm++. However,
142 since there are no global variables as in C++ in Fortran90, you have to
143 access them explicitly via function call. Here are the two helper
144 functions that the translator generates:
146 Take the readonly variable chunkSize as an example:
150 Set_Chunksize(chunkSize);
151 Get_Chunksize(chunkSize);
153 These two functions can be used in user’s Fortran program to set and get
156 Third, for the user’s convenience, several Charm++ runtime library functions
157 have their Fortran interface defined in the F90Charm library. These
164 CkNumPes(integer pes)
165 CkPrintf(...) // note, the format string must terminated with '$$'
167 Here is a summary of current constraints to write F90 binding Charm++
170 #. Only one- to three-dimensional chare arrays are supported.
172 #. readonly variables must be basic types, i.e. they have to be integers,
173 floats, etc. scalar types or array types of these basic scalar types.
175 #. Instead of ``program main``, your f90 main program starts from
176 ``subroutine f90charmmain``.
178 These details are best illustrated with an example: a hello world program.
179 When executed, an array of several parallel chares is created, forming a ring.
180 Each chare prints a string when it receives a message, and then sends a
181 message to the next chare in the ring. The Fortran ``f90charmmain`` subroutine
182 begins execution, and the ``SayHi`` subroutine performs each chare's task.
184 Writing the Charm++ Interface File
185 ==================================
187 In this step, you need to write a Charm++ interface file (.ci).
188 In the file you can declare parallel chare arrays and their
189 entry methods. The syntax is the same as in Charm++.
193 // ## Just replace Hello throughout with your chare's name. ##
194 // ## and add your chare's entry points below where indicated ##
195 // ## Everything else remains the same ##
197 // declare readonly variables which once set is available to all
198 // Chares across processors.
199 readonly int chunkSize;
204 // Note how your Fortran function takes the above defined
205 // message instead of a list of parameters.
206 entry void SayHi(int a, double b, int n, int arr[n]);
208 // Other entry points go here
209 entry [reductiontarget] void MyReduction(int result);
213 Note, you cannot declare a main chare in the interface file, and you
214 also are not supposed to declare messages. Furthermore, the entry
215 functions must be declared with explicit parameters instead of using
218 Writing the F90 Program
219 =======================
221 To start, you need to create a Fortran Module to represent a chare, e.g.
224 .. code-block:: fortran
226 ! ## Just replace Hello throughout with your chare's name. ##
227 ! ## and add your chare's personal data below where indicated ##
228 ! ## Everything else remains the same ##
232 ! ## your chare's data goes here ##
237 TYPE (Hello), POINTER :: obj
243 In the Fortran file you must write an allocate function for this chare
244 with the name: Hello_allocate.
246 .. code-block:: fortran
248 ! ## Just replace Hello throughout with your chare's name. ##
249 ! ## Everything else remains the same ##
250 SUBROUTINE Hello_allocate(objPtr, aid, index)
252 TYPE(HelloPtr) objPtr
258 ! ## you can initialize the Chare user data here
259 objPtr%obj%data = index
262 Now that you have the chare and the chare constructor function, you can
263 start to write entry functions as declared in the .ci files.
265 .. code-block:: fortran
267 ! ## p1, p2, etc represent user parameters
268 ! ## the "objPtr, myIndex" stuff is required in every Entry Point.
269 ! ## CkExit() must be called by the chare to terminate.
270 SUBROUTINE Hello_Entry_SayHi(objPtr, myIndex, data, data2, len, s)
274 TYPE(HelloPtr) objPtr
277 double precision data2
282 if (myIndex < 4) then
283 call Hello_Invoke_SayHi(objPtr%aid, myIndex+1, 1, data2, len, s);
288 Preliminary support for reductions is available as well. Support is
289 limited to reducing from a chare array to the first member of the same
290 array. Only basic built-in reducers are available. For an entry method
291 named MyReduction, tagged as a reduction target in the interface file, a
292 contribution can be made as follows:
294 .. code-block:: fortran
296 external Hello_ReductionTarget_MyReduction
298 call Hello_contribute(objPtr%aid, myIndex, sizeof(myIndex), myValue, CHARM_SUM_INT, Hello_ReductionTarget_MyReduction)
300 Now, you can write the main program to create the chare array and start
301 the program by sending the first message.
303 .. code-block:: fortran
305 SUBROUTINE f90charmmain()
312 call Hello_CkNew(5, aid)
314 call set_ChunkSize(10);
320 call Hello_Invoke_SayHi(aid, 0, 1, d, 4, s(3:6));
324 This main program creates an chare array Hello of size 5 and send a
325 message with an integer, an double and array of integers to the array
328 Compilation and Linking
329 =======================
331 Lastly, you need to compile and link the Fortran program with the Charm
332 runtime system as follows: (Let’s say you have written ``hellof.f90``, ``hello.ci`` and
337 > charmc hello.ci -language f90charm
339 will create ``hello.decl.h`` and ``hello.def.h``.
345 will compile ``hello.C`` with ``hello.decl.h`` and ``hello.def.h``.
349 > charmc -c hellof.f90
351 charmc will invoke the Fortran compiler:
355 > charmc -o hello hello.o hellof.o -language f90charm
357 will link ``hellof.o`` and ``hello.o`` against Charm’s Fortran90 library to create
358 a new executable program, ``hello``.
360 A 2D array example can be found in ``charm/examples/charm++/f90charm/hello2D``.
365 To run the program, type:
369 > ./charmrun +p2 hello
371 which will run ``hello`` on two PEs.