doc: clean up syntax highlighting
[charm.git] / doc / armci / manual.rst
1 =============================
2 ARMCI Interface under Charm++
3 =============================
4
5 .. contents::
6    :depth: 3
7
8 Introduction
9 ============
10
11 This manual describes the basic features and API of the Aggregate Remote
12 Memory Copy Interface (ARMCI) library implemented under Charm++. It is
13 meant for developers using ARMCI who desire the performance features of
14 the Charm++ run-time system (e.g. dynamic load balancing, fault
15 tolerance and scalability) applied transparently to their libraries
16 written using the ARMCI API.
17
18 ARMCI is a library that supports remote memory copy functionality. It
19 focuses on non-contiguous data transfers and is meant to be used by
20 other libraries as opposed to application development. Libraries that
21 the original ARMCI developers have targeted include Global Arrays,
22 P++/Overture and the Adlib PCRC run-time system.
23
24 ARMCI remote copy operations are one-sided and complete, regardless of
25 the actions taken by the remote process. For performance reasons,
26 polling can be helpful but should not be necessary to ensure progress.
27 The operations are ordered when referencing the same remote process.
28 Operations issued to different processes can complete in an arbitrary
29 order. Both blocking and non-blocking APIs are supported.
30
31 ARMCI supports three classes of operations: data transfer using *put*,
32 *get* and *accumulate* operations; synchronization with local and global
33 *fence* operations and atomic read-modify-write; and utility functions
34 for memory management and error handling. *Accumulate* and atomic
35 read-modify-write operations are currently not implemented for the
36 charmpp port.
37
38 A *get* operation transfers data from the remote process memory (source)
39 to the calling processing local memory (destination). A *put* operation
40 transfers data from the local memory of the calling process (source) to
41 the memory of the remote process (destination).
42
43 This manual will include several useful Charm++-specific extensions to
44 the ARMCI API. It will also list the functions that have not yet been
45 implemented but exists in the original ARMCI implementation. Readers of
46 this manual are advised to refer to the original ARMCI documentation
47 (See Section :numref:`sec::related doc`) for more complete information
48 and motivation for the development of this library.
49
50 .. _sec::charm build:
51
52 Building ARMCI Support under The Charm++ Runtime System
53 -------------------------------------------------------
54
55 Build charm target ARMCI (instead of charm or AMPI):
56
57 .. code-block:: bash
58
59    $ cd charm
60    $ ./build ARMCI netlrts-linux -O3
61
62 .. _sec::simple program:
63
64 Writing a Simple ARMCI Program
65 ------------------------------
66
67 The following simple example has two processes place their own string
68 into the global array and then acquire the appropriate string from the
69 other’s global address space in order to print “hello world”.
70
71 The main function has to be compliant to ANSI C:
72
73 .. code-block:: c++
74
75    #include <stdio.h>
76    #include <stdlib.h>
77    #include <string.h>
78
79    #include <armci.h>
80
81    #define MAX_PROCESSORS 2
82
83    int main(int argc, char * argv[]) {
84      void *baseAddress[MAX_PROCESSORS];
85      char *myBuffer;
86      int thisImage;
87
88      // initialize
89      ARMCI_Init();
90      ARMCI_Myid(&thisImage);
91
92      // allocate data (collective operation)
93      ARMCI_Malloc(baseAddress, strlen("hello")+1);
94
95      if (thisImage == 0) {
96        sprintf((char *)baseAddress[0], "%s", "hello");
97      } else if (thisImage == 1) {
98        sprintf((char *)baseAddress[1], "%s", "world");
99      }
100
101      // allocate space for local buffer
102      myBuffer = (char *)AMRCI_Malloc_local(strlen("hello")+1);
103
104      ARMCI_Barrier();
105
106      if (thisImage == 0) {
107        ARMCI_Get(baseAddress[1], myBuffer, strlen("hello")+1, 1);
108        printf("[%d] %s %s\n",thisImage, baseAddress[0], myBuffer);
109      } else if (thisImage == 1) {
110        ARMCI_Get(baseAddress[0], myBuffer, strlen("hello")+1, 0);
111        printf("[%d] %s %s\n",thisImage, myBuffer, baseAddress[1]);
112      }
113
114      // finalize
115      ARMCI_Finalize();
116      return 0;
117    }
118
119 .. _sec::armci build:
120
121 Building an ARMCI Binary and Execution
122 --------------------------------------
123
124 Compiling the code with:
125
126 .. code-block:: bash
127
128    $ charm/bin/charmc -c hello.c /$(OPTS)
129
130 Linking the program with:
131
132 .. code-block:: bash
133
134    $ charm/bin/charmc hello.o -o hello -swapglobals -memory isomalloc -language armci $(OPTS)
135
136 Run the program:
137
138 .. code-block:: bash
139
140    $ ./charmrun ./hello +p2 +vp8
141
142 .. _sec::data structures:
143
144 ARMCI Data Structures
145 =====================
146
147 ARMCI provides two formats to describe non-contiguous layouts of data in
148 memory.
149
150 The *generalized I/O vector* is the most general format intended for
151 multiple sets of equally sized data segments to be moved between
152 arbitrary local and remote memory locations. It uses two arrays of
153 pointers: one for source and one for destination addresses. The length
154 of each array is equal to the number of segments.
155
156 .. code-block:: c++
157
158    typedef struct {
159      void *src_ptr_ar;
160      void *dst_ptr_ar;
161      int bytes;
162      int ptr_ar_len;
163    } armci_giov_t;
164
165 Currently, there is no support for *generalized I/O vector* operations
166 in the charmpp implementation.
167
168 The *strided* format is an optimization of the generalized I/O vector
169 format. It is intended to minimize storage required to describe sections
170 of dense multi-dimensional arrays. Instead of including addresses for
171 all the segments, it specifies only an address of the first segment in
172 the set for source and destination. The addresses of the other segments
173 can be computed using the stride information.
174
175
176 Application Programmer’s Interface
177 ==================================
178
179 The following is a list of functions supported on the Charm++ port of
180 ARMCI. The integer value returned by most ARMCI operations represents
181 the error code. The zero value is successful, other values represent
182 failure (See Section :numref:`sec::error codes` for details).
183
184 Startup, Cleanup and Status Functions
185 -------------------------------------
186
187 .. code-block:: c++
188
189    int ARMCI_Init(void);
190
191 Initializes the ARMCI library. This function must be called before any
192 ARMCI functions may be used.
193
194 .. code-block:: c++
195
196    int ARMCI_Finalize(void);
197
198 Shuts down the ARMCI library. No ARMCI functions may be called after
199 this call is made. It must be used before terminating the program
200 normally.
201
202 .. code-block:: c++
203
204    void ARMCI_Cleanup(void);
205
206 Releases system resources that the ARMCI library might be holding. This
207 is intended to be used before terminating the program in case of error.
208
209 .. code-block:: c++
210
211    void ARMCI_Error(char *msg, int code);
212
213 Combines the functionality of ARMCI_Cleanup and Charm++’s CkAbort call.
214 Prints to *stdout* and *stderr* ``msg`` followed by an integer ``code``.
215
216 .. code-block:: c++
217
218    int ARMCI_Procs(int *procs);
219
220 The number of processes is stored in the address ``procs``.
221
222 .. code-block:: c++
223
224    int ARMCI_Myid(int *myid);
225
226 The id of the process making this call is stored in the address
227 ``myid``.
228
229 ARMCI Memory Allocation
230 -----------------------
231
232 .. code-block:: c++
233
234    int ARMCI_Malloc(void* ptr_arr[], int bytes);
235
236 Collective operation to allocate memory that can be used in the context
237 of ARMCI copy operations. Memory of size ``bytes`` is allocated on each
238 process. The pointer address of each process’ allocated memory is stored
239 at ``ptr_arr[]`` indexed by the process’ id (see ``ARMCI_Myid``). Each
240 process gets a copy of ``ptr_arr``.
241
242 .. code-block:: c++
243
244    int ARMCI_Free(void *ptr);
245
246 Collective operation to free memory which was allocated by
247 ``ARMCI_Malloc``.
248
249 .. code-block:: c++
250
251    void *ARMCI_Malloc_local(int bytes);
252
253 Local memory of size ``bytes`` allocated. Essentially a wrapper for
254 ``malloc``.
255
256 .. code-block:: c++
257
258    int ARMCI_Free_local(void *ptr);
259
260 Local memory address pointed to by ``ptr`` is freed. Essentially a
261 wrapper for ``free``.
262
263 Put and Get Communication
264 -------------------------
265
266 .. code-block:: c++
267
268    int ARMCI_Put(void *src, void *dst, int bytes, int proc);
269
270 Transfer contiguous data of size ``bytes`` from the local process memory
271 (source) pointed to by ``src`` into the remote memory of process id
272 ``proc`` pointed to by ``dst`` (remote memory pointer at destination).
273
274 .. code-block:: c++
275
276    int ARMCI_NbPut(void *src, void* dst, int bytes, int proc,
277                    armci_hdl_t *handle);
278
279 The non-blocking version of ``ARMCI_Put``. Passing a ``NULL`` value to
280 ``handle`` makes this function perform an implicit handle non-blocking
281 transfer.
282
283 .. code-block:: c++
284
285    int ARMCI_PutS(void *src_ptr, int src_stride_ar[],
286                   void *dst_ptr, int dst_stride_ar[],
287                   int count[], int stride_levels, int proc);
288
289 Transfer strided data from the local process memory (source) into remote
290 memory of process id ``proc``. ``src_ptr`` points to the first memory
291 segment in local process memory. ``dst_ptr`` is a remote memory address
292 that points to the first memory segment in the memory of process
293 ``proc``. ``stride_levels`` represents the number of additional
294 dimensions of striding beyond 1. ``src_stride_ar`` is an array of size
295 ``stride_levels`` whose values indicate the number of bytes to skip on
296 the local process memory layout. ``dst_stride_ar`` is an array of size
297 ``stride_levels`` whose values indicate the number of bytes to skip on
298 process ``proc``\ ’s memory layout. ``count`` is an array of size
299 ``stride_levels + 1`` whose values indicate the number of bytes to copy.
300
301 As an example, assume two 2-dimensional C arrays residing on different
302 processes.
303
304 .. code-block:: c++
305
306              double A[10][20]; /* local process */
307              double B[20][30]; /* remote process */
308
309 To put a block of data of 3x6 doubles starting at location (1,2) in
310 ``A`` into location (3,4) in ``B``, the arguments to ``ARMCI_PutS`` will
311 be as follows (assuming C/C++ memory layout):
312
313 .. code-block:: c++
314
315              src_ptr = &A[0][0] + (1 * 20 + 2); /* location (1,2) */
316              src_stride_ar[0] = 20 * sizeof(double);
317              dst_ptr = &B[0][0] + (3 * 30 + 4); /* location (3,4) */
318              dst_stride_ar[0] = 30 * sizeof(double);
319              count[0] = 6 * sizeof(double); /* contiguous data */
320              count[1] = 3; /* number of rows of contiguous data */
321              stride_levels = 1;
322              proc = /*<B's id> */;
323
324 .. code-block:: c++
325
326    int ARMCI_NbPutS(void *src_ptr, int src_stride_ar[],
327                     void *dst_ptr, int dst_stride_ar[],
328                     int count[], int stride_levels, int proc
329                     armci_hdl_t *handle);
330
331 The non-blocking version of ``ARMCI_PutS``. Passing a ``NULL`` value to
332 ``handle`` makes this function perform an implicit handle non-blocking
333 transfer.
334
335 .. code-block:: c++
336
337    int ARMCI_Get(void *src, void *dst, int bytes, int proc);
338
339 Transfer contiguous data of size ``bytes`` from the remote process
340 memory at process ``proc`` (source) pointed to by ``src`` into the local
341 memory of the calling process pointed to by ``dst``.
342
343 .. code-block:: c++
344
345    int ARMCI_NbGet(void *src, void *dst, int bytes, int proc,
346                    armci_hdl_t *handle);
347
348 The non-blocking version of ``ARMCI_Get``. Passing a ``NULL`` value to
349 ``handle`` makes this function perform an implicit handle non-blocking
350 transfer.
351
352 .. code-block:: c++
353
354    int ARMCI_GetS(void *src_ptr, int src_stride_ar[],
355                   void* dst_ptr, int dst_stride_ar[],
356                   int count[], int stride_levels, int proc);
357
358 Transfer strided data segments from remote process memory on process
359 ``proc`` to the local memory of the calling process. The semantics of
360 the parameters to this function are the same as that for ``ARMCI_PutS``.
361
362 .. code-block:: c++
363
364    int ARMCI_NbGetS(void *src_ptr, int src_stride_ar[],
365                     void* dst_ptr, int dst_stride_ar[],
366                     int count[], int stride_levels, int proc,
367                     armci_hdl_t *handle);
368
369 The non-blocking version of ``ARMCI_GetS``. Passing a ``NULL`` value to
370 ``handle`` makes this function perform an implicit handle non-blocking
371 transfer.
372
373 Explicit Synchronization
374 ------------------------
375
376 .. code-block:: c++
377
378    int ARMCI_Wait(armci_hdl_t *handle);
379    int ARMCI_WaitProc(int proc);
380    int ARMCI_WaitAll();
381    int ARMCI_Test(armci_hdl_t *handle);
382    int ARMCI_Barrier();
383
384 .. code-block:: c++
385
386    int ARMCI_Fence(int proc);
387
388 Blocks the calling process until all *put* or *accumulate* operations
389 the process issued to the remote process ``proc`` are completed at the
390 destination.
391
392 .. code-block:: c++
393
394    int ARMCI_AllFence(void);
395
396 Blocks the calling process until all outstanding *put* or *accumulate*
397 operations it issued are completed on all remote destinations.
398
399 .. _sec::extensions:
400
401 Extensions to the Standard API
402 ------------------------------
403
404 .. code-block:: c++
405
406    void ARMCI_Migrate(void);
407    void ARMCI_Async_Migrate(void);
408    void ARMCI_Checkpoint(char* dirname);
409    void ARMCI_MemCheckpoint(void);
410
411    int armci_notify(int proc);
412    int armci_notify_wait(int proc, int *pval);
413
414 List of Unimplemented Functions
415 ===============================
416
417 The following functions are supported on the standard ARMCI
418 implementation but not yet supported in the Charm++ port.
419
420 .. code-block:: c++
421
422    int ARMCI_GetV(...);
423    int ARMCI_NbGetV(...);
424    int ARMCI_PutV(...);
425    int ARMCI_NbPutV(...);
426    int ARMCI_AccV(...);
427    int ARMCI_NbAccV(...);
428
429    int ARMCI_Acc(...);
430    int ARMCI_NbAcc(...);
431    int ARMCI_AccS(...);
432    int ARMCI_NbAccS(...);
433
434    int ARMCI_PutValueLong(long src, void* dst, int proc);
435    int ARMCI_PutValueInt(int src, void* dst, int proc);
436    int ARMCI_PutValueFloat(float src, void* dst, int proc);
437    int ARMCI_PutValueDouble(double src, void* dst, int proc);
438    int ARMCI_NbPutValueLong(long src, void* dst, int proc, armci_hdl_t* handle);
439    int ARMCI_NbPutValueInt(int src, void* dst, int proc, armci_hdl_t* handle);
440    int ARMCI_NbPutValueFloat(float src, void* dst, int proc, armci_hdl_t* handle);
441    int ARMCI_NbPutValueDouble(double src, void* dst, int proc, armci_hdl_t* handle);
442    long ARMCI_GetValueLong(void *src, int proc);
443    int ARMCI_GetValueInt(void *src, int proc);
444    float ARMCI_GetValueFloat(void *src, int proc);
445    double ARMCI_GetValueDouble(void *src, int proc);
446
447    void ARMCI_SET_AGGREGATE_HANDLE (armci_hdl_t* handle);
448    void ARMCI_UNSET_AGGREGATE_HANDLE (armci_hdl_t* handle);
449
450    int ARMCI_Rmw(int op, int *ploc, int *prem, int extra, int proc);
451    int ARMCI_Create_mutexes(int num);
452    int ARMCI_Destroy_mutexes(void);
453    void ARMCI_Lock(int mutex, int proc);
454    void ARMCI_Unlock(int mutex, int proc);
455
456 .. _sec::error codes:
457
458 Error Codes
459 ===========
460
461 As of this writing, attempts to locate the documented error codes have
462 failed because the release notes have not been found. Attempts are being
463 made to derive these from the ARMCI source directly. Currently Charm++
464 implementation does not implement any error codes.
465
466 .. _sec::related doc:
467
468 Related Manuals and Documents
469 =============================
470
471 ARMCI website: http://www.emsl.pnl.gov/docs/parsoft/armci/index.html