Docs: Review f90charm
[charm.git] / doc / f90charm / manual.rst
blob0caa70cb49c038213b9a20be5b85cedd2e661874
1 ==============================
2 Fortran90 Bindings for Charm++
3 ==============================
5 .. contents::
6    :depth: 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
25 #. Run it!
27 Overview
28 ========
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
34 example:
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 ##
41          MODULE HelloMod
43          TYPE Hello
44          ! ## your chare's data goes here, the integer below is an example ##
45          integer data
46          END TYPE
48          TYPE HelloPtr
49          TYPE (Hello), POINTER :: obj
50          integer*8 aid
51          END TYPE
53          END MODULE
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
112 example shown here):
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
119 well:
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
139 translator.
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
154 readonly variables.
156 Third, for the user’s convenience, several Charm++ runtime library functions
157 have their Fortran interface defined in the F90Charm library. These
158 currently include:
162    CkExit()
163    CkMyPe(integer mype)
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++
168 programs:
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 ##
196          mainmodule hello {
197            // declare readonly variables which once set is available to all
198            // Chares across processors.
199            readonly int chunkSize;
201            array [1D] Hello {
202              entry Hello();
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);
210            };
211          };
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
216 messages.
218 Writing the F90 Program
219 =======================
221 To start, you need to create a Fortran Module to represent a chare, e.g.
222 {ChareName}Mod.
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 ##
229          MODULE HelloMod
231          TYPE Hello
232          ! ## your chare's data goes here ##
233          integer data
234          END TYPE
236          TYPE HelloPtr
237          TYPE (Hello), POINTER ::  obj
238          integer*8 aid
239          END TYPE
241          END MODULE
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)
251          USE HelloMod
252          TYPE(HelloPtr) objPtr
253          integer*8 aid
254          integer index
256          allocate(objPtr%obj)
257          objPtr%aid = aid;
258          ! ## you can initialize the Chare user data here
259          objPtr%obj%data = index
260          END SUBROUTINE
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)
271          USE HelloMod
272          IMPLICIT NONE
274          TYPE(HelloPtr) objPtr
275          integer myIndex
276          integer data
277          double precision data2
278          integer len
279          integer s(len)
281          objPtr%obj%data = 20
282          if (myIndex < 4) then
283              call Hello_Invoke_SayHi(objPtr%aid, myIndex+1, 1, data2, len, s);
284          else
285              call CkExit()
286          endif
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()
306          USE HelloMod
307          integer i
308          double precision d
309          integer*8 aid
310          integer  s(8)
312          call Hello_CkNew(5, aid)
314          call set_ChunkSize(10);
316          do i=1,8
317              s(i) = i;
318          enddo
319          d = 2.50
320          call Hello_Invoke_SayHi(aid, 0, 1, d, 4, s(3:6));
322          END
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
326 element of index 0.
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
333 ``hello.C``.)
335 .. code-block:: bash
337      > charmc hello.ci -language f90charm
339 will create ``hello.decl.h`` and ``hello.def.h``.
341 .. code-block:: bash
343      > charmc -c hello.C
345 will compile ``hello.C`` with ``hello.decl.h`` and ``hello.def.h``.
347 .. code-block:: bash
349      > charmc -c hellof.f90
351 charmc will invoke the Fortran compiler:
353 .. code-block:: bash
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``.
362 Running the Program
363 ===================
365 To run the program, type:
367 .. code-block:: bash
369     > ./charmrun +p2 hello
371 which will run ``hello`` on two PEs.