1 /***********************************************************************
5 The following is a notice of limited availability of the code and
6 Government license and disclaimer which must be included in the
7 prologue of the code and in all source listings of the code.
10 (c) 1977 University of Chicago
12 Permission is hereby granted to use, reproduce, prepare
13 derivative works, and to redistribute to others at no charge. If
14 you distribute a copy or copies of the Software, or you modify a
15 copy or copies of the Software or any portion of it, thus forming
16 a work based on the Software and make and/or distribute copies of
17 such work, you must meet the following conditions:
19 a) If you make a copy of the Software (modified or verbatim)
20 it must include the copyright notice and Government
21 license and disclaimer.
23 b) You must cause the modified Software to carry prominent
24 notices stating that you changed specified portions of
27 This software was authored by:
29 Argonne National Laboratory
30 J. Michalakes: (630) 252-6646; email: michalak@mcs.anl.gov
31 Mathematics and Computer Science Division
32 Argonne National Laboratory, Argonne, IL 60439
34 ARGONNE NATIONAL LABORATORY (ANL), WITH FACILITIES IN THE STATES
35 OF ILLINOIS AND IDAHO, IS OWNED BY THE UNITED STATES GOVERNMENT,
36 AND OPERATED BY THE UNIVERSITY OF CHICAGO UNDER PROVISION OF A
37 CONTRACT WITH THE DEPARTMENT OF ENERGY.
39 GOVERNMENT LICENSE AND DISCLAIMER
41 This computer code material was prepared, in part, as an account
42 of work sponsored by an agency of the United States Government.
43 The Government is granted for itself and others acting on its
44 behalf a paid-up, nonexclusive, irrevocable worldwide license in
45 this data to reproduce, prepare derivative works, distribute
46 copies to the public, perform publicly and display publicly, and
47 to permit others to do so. NEITHER THE UNITED STATES GOVERNMENT
48 NOR ANY AGENCY THEREOF, NOR THE UNIVERSITY OF CHICAGO, NOR ANY OF
49 THEIR EMPLOYEES, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
50 ASSUMES ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY,
51 COMPLETENESS, OR USEFULNESS OF ANY INFORMATION, APPARATUS,
52 PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD
53 NOT INFRINGE PRIVATELY OWNED RIGHTS.
55 ***************************************************************************/
62 RSL_CREATE_MESSAGE - create a descriptor for an RSL message.
65 RSL_CREATE_MESSAGE ( m )
69 . m - message descriptor
72 Create a descriptor for an RSL message. On return, the
73 integer Arg1 will contain a handle to a new RSL message.
74 Messages exist only temporarily by themselves -- once a message
75 has been asssociated with a stencil or a state vector, the handle
79 RSL_BUILD_MESSAGE, RSL_DESCRIBE_STENCIL, RSL_DESCRIBE_STATE
84 RSL_CREATE_MESSAGE ( mh_p
)
91 /* NOTE: never return the 0th message descriptor */
92 for ( i
= 1 ; i
< RSL_MAXDESCRIPTORS
; i
++ )
93 if ( mh_descriptors
[i
] == NULL
) break ; /* got one */
95 RSL_TEST_ERR( i
== RSL_MAXDESCRIPTORS
,
96 "rsl_create_message: out of descriptors.\nAre you creating messages and then not associating them with\na stencil, bcast/merge, or state vector?" ) ;
99 msg
= RSL_MALLOC(message_desc_t
,1) ;
100 msg
->tag
= MESSAGE_DESC
;
102 mh_descriptors
[*mh_p
] = msg
;
105 /* Only ever called internally to RSL. This routine is for use
106 by routines that associate messages with other RSL constructs. Once
107 the association is made, those constructs point to the messages. We
108 do *not* free the message description structures here, only free up
109 the descriptors so they can be used again. */
111 release_mh_descriptor (mh_p
)
118 if ( mh
== RSL_INVALID
) return ;
120 RSL_TEST_ERR( mh
<= 0 || mh
>= RSL_MAXDESCRIPTORS
,
121 "internal error. Invalid message descriptor.") ;
122 if ( mh_descriptors
[mh
] != NULL
)
124 mh_descriptors
[mh
] = NULL
;
126 /* it can happen that this will be called for a descriptor that
127 has already been nulled out. Let it happen. */
132 RSL_BLANK_MESSAGE - (obsolete) describe a message for broadcast/merges.
135 RSL_BLANK_MESSAGE ( m, len )
140 . m - message descriptor
141 . len - length, in bytes, of message
144 Messages to be used in a broadcast or a merge operation
145 for inter-domain communication do not have fields associated
146 with them ahead of time, unlike messages that are used
147 in stencil exchanges (see RSL_BUILD_MESSAGE). Rather, the
148 packing and unpacking routines are provided by the user,
149 and the message is simply a stream of bytes. RSL_BLANK_MESSAGE
150 designates a message as a blank message and associates with
151 the message its length in bytes.
154 RSL_BUILD_MESSAGE, RSL_COMP_BCAST, RSL_COMP_MERGE
158 RSL_BLANK_MESSAGE ( mh_p
, len_p
)
159 int_p mh_p
; /* message handle */
160 int_p len_p
; /* length in bytes */
163 message_desc_t
*msg
;
165 mh
= *mh_p
; len
= *len_p
;
167 RSL_TEST_ERR((mh
<= 0)|| (mh
>= RSL_MAXDESCRIPTORS
),
168 "rsl_blank_message: bad message handle" ) ;
169 RSL_TEST_ERR((msg
= (message_desc_t
*)mh_descriptors
[mh
])==NULL
,
170 "descriptor for null message");
171 RSL_TEST_ERR( msg
->tag
!= MESSAGE_DESC
,
172 "rsl_blank_message: handle given is not for an rsl message def" ) ;
174 msg
->tag
= BLANK_MESSAGE_DESC
; /* change tag */
180 RSL_BUILD_MESSAGE - Add a 2- or 3-dimensional field to a message.
183 An RSL message is a set of fields that are to be communicated
184 for a point in the model grid. Describing messages in this way
185 allows RSL to assume control of packing and unpacking of model data
186 from and to local processor memory for efficient and transparent
187 communication of stencil exchanges and state remappings.
189 A field (Arg3), a multi-dimensional
190 array of a given type (Arg2),
193 to a message (Arg1) by repeated calls to RSL_BUILD_MESSAGE.
194 Once constructed, messages may then be combined into stencils
195 (RSL_DESCRIBE_STENCIL) for stencil exchanges (RSL_EXCH_STENCIL).
196 A message may also be used to describe a state-vector (RSL_DESCRIBE_STATE)
197 used in remapping for load balancing.
199 The Arg4 argument gives the number of dimensions in the field
200 being added to the message. It is permissable to mix 2 and 3
201 dimensional fields. Regardless, however, 2 and only dimensions
204 The three arguments Arg4, Arg5, and Arg6, are integer arrays
205 of size Arg4. The indicies of these arrays correspond to the
206 dimensions of the field being added; index 1 is the most minor,
207 and index ndim is the most major dimension.
209 The values stored in the Arg4 array may be
212 $ RSL_NORTHSOUTH -- decomposed over M
213 $ RSL_EASTWEST -- decomposed over N
214 $ RSL_NOTDECOMPOSED. -- not decomposed.
217 This tells RSL whether the
218 dimension in question is decomposed over a north/south column of
219 processors in the mesh, an east-west row in the mesh, or -- as is the
220 case with the vertical dimension in 3-d arrays -- not decomposed at
221 all. RSL_NORTHSOUTH, RSL_EASTWEST, and RSL_NOTDECOMPOSED are
222 defined in the RSL include file "rsl.inc".
224 The values stored in the Arg5 array are the global, or
225 undecomposed, sizes of each dimension of the field. The values
226 stored in the Arg6 array are the local, or actual,
227 sizes of the dimensions of the field as it exists in the processor's
228 memory. If the field is statically declared (say, in common) the
229 sizes would be the sizes that were used to declare the array itself.
230 If the array is dynamically allocated using a Fortran90
231 ALLOCATE() statement, the values of llen would be sizes that
232 were specified to the ALLOCATE() statement. In the latter case,
233 if these sizes ever change during the course of a run, it would
234 be necessary to destroy this message and reconstruct a new one
235 for RSL, since it must always be able to determine the true size
236 in memory of the data structures involved in messaging operations.
239 $ integer m ! message descriptor
240 $ integer decomp(3), llen(3), glen(3) ! dimension descriptions
241 $ real ua(ix,jx,kx), va(ix,jx,kx) ! locally dimensioned 3-d arrays
242 $ real psa(ix,jx,kx) ! locally dimensioned 2-d array
244 $ decomp(1) = RSL_NORTHSOUTH ! how most minor dim decomposed
245 $ decomp(2) = RSL_EASTWEST ! how next dim decomposed
246 $ decomp(3) = RSL_NOTDECOMPOSED ! major dim (vertical) not decomposed
248 $ glen(1) = g_ix ! global size in n/s
249 $ glen(2) = g_jx ! global size in e/w
250 $ glen(3) = kx ! size in vertical
251 $ llen(1) = ix ! local size in n/s
252 $ llen(2) = jx ! local size in e/w
253 $ llen(3) = kx ! local size of vertical (same as global)
255 $ call rsl_create_message( m )
256 $ call rsl_build_message( m, RSL_REAL, ua, 3, decomp, glen, llen )
257 $ call rsl_build_message( m, RSL_REAL, va, 3, decomp, glen, llen )
258 $ call rsl_build_message( m, RSL_REAL, psa, 2, decomp, glen, llen )
263 In the above example, a message is created and then built by
264 adding two three-dimensional fields and one two-dimensional field.
265 The order of the construction is not important. Subsequent
266 to these statements, the completed message could be used to define
267 one or more points of a stencil exchange to communicate ua,
268 psa, and va between processors.
272 RSL_CREATE_MESSAGE, RSL_BLANK_MESSAGE, RSL_DESCRIBE_STENCIL,
277 static struct f90_base_table_entry
{
278 char * base
, * virt_base
;
280 } f90_base_table
[ MAX_BASE_TABLE_ENTRIES
] ;
281 static int base_table_cursor
= 1;
282 static int base_table_size
= 1;
284 RSL_BUILD_MESSAGE ( mh_p
, t_p
, base
, ndim_p
, decomp
, glen
, llen
)
286 mh_p
/* (I) Message handle created by RSL_CREATE_MESSAGE. */
287 ,t_p
/* (I) RSL type description. */
288 ,ndim_p
; /* (I) Number of dimensions of field being added to message.*/
290 base
; /* (I) Base address field in local memory. */
292 decomp
[] ; /* (I) How decomposed. */
294 glen
[] ; /* (I) Global (undecomposed) dimensions of field. */
296 llen
[] ; /* (I) Local (decomposed) dimensions of field. */
299 message_desc_t
*msg
;
302 int f90_table_index
;
305 mh
= *mh_p
; t
= *t_p
; ndim
= *ndim_p
;
307 RSL_TEST_ERR( ndim
< 0, "rsl_build_message: bad ndim argument" ) ;
308 RSL_TEST_ERR( ndim
> RSL_MAXDIM
,
309 "rsl_build_message: ndim too large. Change RSL_MAXDIM; recompile librsl.a." ) ;
310 RSL_TEST_ERR((mh
<= 0)||(mh
>= RSL_MAXDESCRIPTORS
),
311 "rsl_build_message: bad message handle" ) ;
312 if ( (msg
= (message_desc_t
*)mh_descriptors
[mh
])==NULL
)
314 RSL_TEST_ERR(1, "descriptor for null message");
316 RSL_TEST_ERR( msg
->tag
!= MESSAGE_DESC
,
317 "rsl_build_message: handle given is not for an rsl message def" ) ;
319 fld
= RSL_MALLOC( rsl_fldspec_t
, 1 ) ;
322 fld
->elemsz
= elemsize( t
) ;
323 for ( fld
->memsize
= fld
->elemsz
, i
= 0 ; i
< ndim
; i
++ )
325 fld
->memsize
= fld
->memsize
* llen
[i
] ;
330 if ( ! (fld
->f90_table_index
= get_index_for_base( base
)) )
331 { RSL_TEST_ERR(1,"Use of unregistered f90 typed variable") ; }
333 fld
->base
= (void *)((fld
->f90_table_index
-1) * F90_MAX_FLD_SIZE_IN_BYTES
+ 1) ; /* don't allow base of 0 */
335 fld
->base
= f90_base_table
[ fld
->f90_table_index
].virt_base
;
343 for ( dim
= 0 ; dim
< ndim
; dim
++ )
345 fld
->decomp
[dim
] = decomp
[dim
] ;
346 fld
->gdex
[dim
] = RSL_INVALID
; /* this gets filled in dynamically */
347 if ( decomp
[dim
] == RSL_NOTDECOMPOSED
&& glen
[dim
] != llen
[dim
] )
350 "rsl_build_message: mesg %d: dim %d is RSL_NOTDECOMPOSED so glen(%d)=%d must eq llen(%d)=%d",
351 mh
, dim
+1, dim
+1, glen
[dim
], dim
+1, llen
[dim
] ) ;
352 RSL_TEST_WRN( 1, errmess
) ;
354 fld
->glen
[dim
] = glen
[dim
] ;
355 fld
->llen
[dim
] = llen
[dim
] ;
356 if ( decomp
[dim
] > 10 )
362 /* work out pack/unpack strategy for this field */
366 if ( decomp
[0]%10 == RSL_M
&&
367 decomp
[1]%10 == RSL_N
)
368 fld
->strategy
= MINNS_MAJEW_2D
;
369 else if ( decomp
[1]%10 == RSL_M
&&
370 decomp
[0]%10 == RSL_N
)
371 fld
->strategy
= MINEW_MAJNS_2D
;
373 RSL_TEST_ERR(1,"rsl_build_message: unsupported decomposition strategy for 2d message") ;
376 if ( decomp
[0]%10 == RSL_M
&&
377 decomp
[1]%10 == RSL_N
&&
378 decomp
[2]%10 == RSL_NOTDECOMPOSED
)
379 fld
->strategy
= MINNS_MAJEW_K_3D
;
380 else if ( decomp
[0]%10 == RSL_N
&&
381 decomp
[1]%10 == RSL_M
&&
382 decomp
[2]%10 == RSL_NOTDECOMPOSED
)
383 fld
->strategy
= MINEW_MAJNS_K_3D
;
384 else if ( decomp
[0]%10 == RSL_NOTDECOMPOSED
&&
385 decomp
[1]%10 == RSL_M
&&
386 decomp
[2]%10 == RSL_N
)
387 fld
->strategy
= K_MIDNS_MAJEW_3D
;
388 else if ( decomp
[0]%10 == RSL_M
&&
389 decomp
[1]%10 == RSL_NOTDECOMPOSED
&&
390 decomp
[2]%10 == RSL_N
)
391 fld
->strategy
= MINNS_K_MAJEW_3D
;
393 RSL_TEST_ERR(1,"rsl_build_message: unsupported decomposition strategy for 3d message") ;
396 sprintf(mess
,"rsl_build_message: %d dimension flds not supported yet\n",
398 RSL_TEST_ERR(1,mess
) ;
402 /* insert fldspec at beginning of list (note: we're not concerning
403 ourselves with order of the fields -- this will reverse them from
404 the order they were specified in.) */
406 fld
->next
= msg
->fldspecs
;
407 msg
->fldspecs
= fld
;
412 RSL_REGISTER_F90 ( base
)
415 if ( base_table_cursor
< MAX_BASE_TABLE_ENTRIES
)
417 f90_base_table
[ base_table_cursor
].base
= base
;
418 base_table_cursor
++ ;
422 RSL_TEST_ERR(1,"Exceeded MAX_BASE_TABLE_ENTRIES number of f90 fields") ;
426 #define BASE_TABLE_PADDING sizeof(double) ;
427 RSL_REGISTER_F90_BASE_AND_SIZE ( base
, size
)
431 if ( base_table_cursor
< MAX_BASE_TABLE_ENTRIES
)
433 f90_base_table
[ base_table_cursor
].base
= base
;
434 f90_base_table
[ base_table_cursor
].size_in_bytes
= * size
;
435 f90_base_table
[ base_table_cursor
].virt_base
=
436 f90_base_table
[ base_table_cursor
-1 ].virt_base
+
437 f90_base_table
[ base_table_cursor
-1 ].size_in_bytes
+ BASE_TABLE_PADDING
;
438 base_table_cursor
++ ;
442 RSL_TEST_ERR(1,"Exceeded MAX_BASE_TABLE_ENTRIES number of f90 fields") ;
446 RSL_END_REGISTER_F90 ()
448 base_table_size
= base_table_cursor
;
451 RSL_START_REGISTER_F90 ()
453 base_table_cursor
= 1 ;
454 f90_base_table
[ 0 ].virt_base
= (char *) BASE_TABLE_PADDING
;
455 f90_base_table
[ 0 ].size_in_bytes
= 0 ;
459 get_base_for_index ( dex
)
462 if ( dex
< 1 || dex
>= base_table_size
)
464 sprintf(mess
, "bad index %d into f90_base_table. base_table_size %d\n", dex
, base_table_size
) ;
465 RSL_TEST_ERR( 1, mess
) ;
467 return( (void *) f90_base_table
[dex
].base
) ;
470 get_index_for_base ( base
)
474 for ( i
= 1 ; i
< base_table_size
; i
++ )
476 if ( base
== f90_base_table
[ i
].base
)
484 /* return the number of bytes this message will require
485 (only the data requirements -- descriptors not figured here */
488 message_desc_t
*msg
;
492 rsl_fldspec_t
* fld
;
494 if ( msg
== NULL
) return(0) ;
495 if ( msg
->tag
!= MESSAGE_DESC
) return(-1) ;
497 for ( fld
= msg
->fldspecs
; fld
!= NULL
; fld
= fld
->next
)
499 accum
+= fldsize( fld
) ;
506 rsl_fldspec_t
* fld
;
509 int accum
, fldaccum
;
511 for ( dim
= 0 ; dim
< fld
->ndim
; dim
++ )
513 fldaccum
*= (fld
->decomp
[dim
] == RSL_NOTDECOMPOSED
)?fld
->llen
[dim
]:1;
515 return (fldaccum
* fld
->elemsz
) ;
518 /* only used internally within the RSL package... called by routines
519 that destroy larger RSL constructs such as stencils, bcast/merges,
520 state vectors (note: this routine was written using emacs, so
522 destroy_message( msg
)
523 message_desc_t
* msg
;
525 rsl_fldspec_t
*fld
, *doomed
;
526 if ( msg
== NULL
) return ;
527 RSL_TEST_ERR( msg
->tag
!= MESSAGE_DESC
, "destroy_message: arg not a msg.") ;
529 for ( fld
= msg
->fldspecs
; fld
!= NULL
; )
543 if ( t
>= 100 ) t
= t
% 100 ; /* remove extra info */
547 case RSL_REAL
: return(sizeof(double)) ;
549 case RSL_REAL
: return(sizeof(float)) ;
551 case RSL_DOUBLE
: return(sizeof(double)) ;
553 case RSL_COMPLEX
: return(2*sizeof(double)) ;
555 case RSL_COMPLEX
: return(2*sizeof(float)) ;
557 case RSL_INTEGER
: return(sizeof(int)) ;
558 case RSL_CHARACTER
: return(sizeof(char)) ;