3 #define exit exit /*Supress definition of exit in ampi.h*/
6 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
7 #include "ampiEvents.h" /*** for trace generation for projector *****/
8 #include "ampiProjections.h"
12 #include "bigsim_logs.h"
15 /* change this to MPI_ERRORS_RETURN to not abort on errors */
16 #define AMPI_ERRHANDLER MPI_ERRORS_ARE_FATAL
18 #define AMPI_PRINT_IDLE 0
20 /* change this define to "x" to trace all send/recv's */
21 #define MSG_ORDER_DEBUG(x) //x /* empty */
22 /* change this define to "x" to trace user calls */
23 #define USER_CALL_DEBUG(x) // ckout<<"vp "<<TCHARM_Element()<<": "<<x<<endl;
24 #define STARTUP_DEBUG(x) //ckout<<"ampi[pe "<<CkMyPe()<<"] "<< x <<endl;
25 #define FUNCCALL_DEBUG(x) //x /* empty */
27 /* For MPI_Get_library_version */
28 extern "C" const char * const CmiCommitID;
30 static CkDDT *getDDT(void) {
31 return getAmpiParent()->myDDT;
34 /* if error checking is disabled, ampiErrhandler is defined as a macro in ampiimpl.h */
35 #if AMPI_ERROR_CHECKING
36 inline int ampiErrhandler(const char* func, int errcode) {
37 if (AMPI_ERRHANDLER == MPI_ERRORS_ARE_FATAL && errcode != MPI_SUCCESS) {
38 // Abort with a nice message of the form: 'func' failed with error code 'errstr'.
39 // where 'func' is the name of the failed AMPI_ function and 'errstr'
40 // is the string returned by AMPI_Error_string for errcode.
41 int funclen = strlen(func);
42 const char* filler = " failed with error code ";
43 int fillerlen = strlen(filler);
45 char errstr[MPI_MAX_ERROR_STRING];
46 AMPI_Error_string(errcode, errstr, &errstrlen);
47 vector<char> str(funclen + fillerlen + errstrlen);
48 strcpy(&str[0], func);
49 strcat(&str[0], filler);
50 strcat(&str[0], errstr);
57 inline int checkCommunicator(const char* func, MPI_Comm comm) {
58 if (comm == MPI_COMM_NULL)
59 return ampiErrhandler(func, MPI_ERR_COMM);
63 inline int checkCount(const char* func, int count) {
65 return ampiErrhandler(func, MPI_ERR_COUNT);
69 inline int checkData(const char* func, MPI_Datatype data) {
70 if (data == MPI_DATATYPE_NULL)
71 return ampiErrhandler(func, MPI_ERR_TYPE);
75 inline int checkTag(const char* func, int tag) {
76 if (tag != MPI_ANY_TAG && (tag < 0 || tag > MPI_TAG_UB_VALUE))
77 return ampiErrhandler(func, MPI_ERR_TAG);
81 inline int checkRank(const char* func, int rank, MPI_Comm comm) {
83 AMPI_Comm_size(comm, &size);
84 if (((rank >= 0) && (rank < size)) ||
85 (rank == MPI_ANY_SOURCE) ||
86 (rank == MPI_PROC_NULL))
88 return ampiErrhandler(func, MPI_ERR_RANK);
91 inline int checkBuf(const char* func, void *buf, int count) {
92 if ((count != 0 && buf == NULL) || buf == MPI_IN_PLACE)
93 return ampiErrhandler(func, MPI_ERR_BUFFER);
97 inline int errorCheck(const char* func, MPI_Comm comm, int ifComm, int count,
98 int ifCount, MPI_Datatype data, int ifData, int tag,
99 int ifTag, int rank, int ifRank, void *buf1, int ifBuf1,
100 void *buf2=0, int ifBuf2=0) {
103 ret = checkCommunicator(func, comm);
104 if (ret != MPI_SUCCESS)
105 return ampiErrhandler(func, ret);
108 ret = checkCount(func, count);
109 if (ret != MPI_SUCCESS)
110 return ampiErrhandler(func, ret);
113 ret = checkData(func, data);
114 if (ret != MPI_SUCCESS)
115 return ampiErrhandler(func, ret);
118 ret = checkTag(func, tag);
119 if (ret != MPI_SUCCESS)
120 return ampiErrhandler(func, ret);
123 ret = checkRank(func, rank, comm);
124 if (ret != MPI_SUCCESS)
125 return ampiErrhandler(func, ret);
128 ret = checkBuf(func, buf1, count);
129 if (ret != MPI_SUCCESS)
130 return ampiErrhandler(func, ret);
133 ret = checkBuf(func, buf2, count);
134 if (ret != MPI_SUCCESS)
135 return ampiErrhandler(func, ret);
140 //------------- startup -------------
141 static mpi_comm_worlds mpi_worlds;
143 int _mpi_nworlds; /*Accessed by ampif*/
144 int MPI_COMM_UNIVERSE[MPI_MAX_COMM_WORLDS]; /*Accessed by user code*/
149 void operator+=(const AmpiComplex &a) {
153 void operator*=(const AmpiComplex &a) {
154 float nu_re=re*a.re-im*a.im;
158 int operator>(const AmpiComplex &a) {
159 CkAbort("AMPI> Cannot compare complex numbers with MPI_MAX\n");
162 int operator<(const AmpiComplex &a) {
163 CkAbort("AMPI> Cannot compare complex numbers with MPI_MIN\n");
168 class AmpiDoubleComplex {
171 void operator+=(const AmpiDoubleComplex &a) {
175 void operator*=(const AmpiDoubleComplex &a) {
176 double nu_re=re*a.re-im*a.im;
180 int operator>(const AmpiDoubleComplex &a) {
181 CkAbort("AMPI> Cannot compare double complex numbers with MPI_MAX\n");
184 int operator<(const AmpiDoubleComplex &a) {
185 CkAbort("AMPI> Cannot compare double complex numbers with MPI_MIN\n");
190 class AmpiLongDoubleComplex {
193 void operator+=(const AmpiLongDoubleComplex &a) {
197 void operator*=(const AmpiLongDoubleComplex &a) {
198 long double nu_re=re*a.re-im*a.im;
202 int operator>(const AmpiLongDoubleComplex &a) {
203 CkAbort("AMPI> Cannot compare long double complex numbers with MPI_MAX\n");
206 int operator<(const AmpiLongDoubleComplex &a) {
207 CkAbort("AMPI> Cannot compare long double complex numbers with MPI_MIN\n");
212 typedef struct { float val; int idx; } FloatInt;
213 typedef struct { double val; int idx; } DoubleInt;
214 typedef struct { long val; int idx; } LongInt;
215 typedef struct { int val; int idx; } IntInt;
216 typedef struct { short val; int idx; } ShortInt;
217 typedef struct { long double val; int idx; } LongdoubleInt;
218 typedef struct { float val; float idx; } FloatFloat;
219 typedef struct { double val; double idx; } DoubleDouble;
221 /* For MPI_MAX, MPI_MIN, MPI_SUM, and MPI_PROD: */
222 #define MPI_OP_SWITCH(OPNAME) \
224 switch (*datatype) { \
225 case MPI_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(char); } break; \
226 case MPI_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed short int); } break; \
227 case MPI_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed int); } break; \
228 case MPI_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long); } break; \
229 case MPI_UNSIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned char); } break; \
230 case MPI_UNSIGNED_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned short); } break; \
231 case MPI_UNSIGNED: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned int); } break; \
232 case MPI_UNSIGNED_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long); } break; \
233 case MPI_FLOAT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(float); } break; \
234 case MPI_DOUBLE: for(i=0;i<(*len);i++) { MPI_OP_IMPL(double); } break; \
235 case MPI_COMPLEX: for(i=0;i<(*len);i++) { MPI_OP_IMPL(AmpiComplex); } break; \
236 case MPI_DOUBLE_COMPLEX: for(i=0;i<(*len);i++) { MPI_OP_IMPL(AmpiDoubleComplex); } break; \
237 case MPI_LONG_LONG_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long long); } break; \
238 case MPI_SIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed char); } break; \
239 case MPI_UNSIGNED_LONG_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long long); } break; \
240 case MPI_WCHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(wchar_t); } break; \
241 case MPI_INT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int8_t); } break; \
242 case MPI_INT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int16_t); } break; \
243 case MPI_INT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int32_t); } break; \
244 case MPI_INT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int64_t); } break; \
245 case MPI_UINT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint8_t); } break; \
246 case MPI_UINT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint16_t); } break; \
247 case MPI_UINT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint32_t); } break; \
248 case MPI_UINT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint64_t); } break; \
249 case MPI_FLOAT_COMPLEX: for(i=0;i<(*len);i++) { MPI_OP_IMPL(AmpiComplex); } break; \
250 case MPI_LONG_DOUBLE_COMPLEX: for(i=0;i<(*len);i++) { MPI_OP_IMPL(AmpiLongDoubleComplex); } break; \
251 case MPI_AINT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(MPI_Aint); } break; \
253 ckerr << "Type " << *datatype << " with Op "#OPNAME" not supported." << endl; \
254 CkAbort("Unsupported MPI datatype for MPI Op"); \
257 /* For MPI_LAND, MPI_LOR, and MPI_LXOR: */
258 #define MPI_LOGICAL_OP_SWITCH(OPNAME) \
260 switch (*datatype) { \
261 case MPI_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed short int); } break; \
262 case MPI_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed int); } break; \
263 case MPI_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long); } break; \
264 case MPI_UNSIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned char); } break; \
265 case MPI_UNSIGNED_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned short); } break; \
266 case MPI_UNSIGNED: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned int); } break; \
267 case MPI_UNSIGNED_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long); } break; \
268 case MPI_LONG_LONG_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long long); } break; \
269 case MPI_SIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed char); } break; \
270 case MPI_UNSIGNED_LONG_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long long); } break; \
271 case MPI_INT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int8_t); } break; \
272 case MPI_INT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int16_t); } break; \
273 case MPI_INT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int32_t); } break; \
274 case MPI_INT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int64_t); } break; \
275 case MPI_UINT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint8_t); } break; \
276 case MPI_UINT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint16_t); } break; \
277 case MPI_UINT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint32_t); } break; \
278 case MPI_UINT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint64_t); } break; \
279 case MPI_LOGICAL: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int); } break; \
280 case MPI_C_BOOL: for(i=0;i<(*len);i++) { MPI_OP_IMPL(bool); } break; \
282 ckerr << "Type " << *datatype << " with Op "#OPNAME" not supported." << endl; \
283 CkAbort("Unsupported MPI datatype for MPI Op"); \
286 /* For MPI_BAND, MPI_BOR, and MPI_BXOR: */
287 #define MPI_BITWISE_OP_SWITCH(OPNAME) \
289 switch (*datatype) { \
290 case MPI_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed short int); } break; \
291 case MPI_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed int); } break; \
292 case MPI_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long); } break; \
293 case MPI_UNSIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned char); } break; \
294 case MPI_UNSIGNED_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned short); } break; \
295 case MPI_UNSIGNED: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned int); } break; \
296 case MPI_UNSIGNED_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long); } break; \
297 case MPI_LONG_LONG_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long long); } break; \
298 case MPI_SIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed char); } break; \
299 case MPI_UNSIGNED_LONG_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long long); } break; \
300 case MPI_INT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int8_t); } break; \
301 case MPI_INT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int16_t); } break; \
302 case MPI_INT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int32_t); } break; \
303 case MPI_INT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int64_t); } break; \
304 case MPI_UINT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint8_t); } break; \
305 case MPI_UINT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint16_t); } break; \
306 case MPI_UINT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint32_t); } break; \
307 case MPI_UINT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint64_t); } break; \
308 case MPI_BYTE: for(i=0;i<(*len);i++) { MPI_OP_IMPL(char); } break; \
309 case MPI_AINT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(MPI_Aint); } break; \
311 ckerr << "Type " << *datatype << " with Op "#OPNAME" not supported." << endl; \
312 CkAbort("Unsupported MPI datatype for MPI Op"); \
315 void MPI_MAX_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
316 #define MPI_OP_IMPL(type) \
317 if(((type *)invec)[i] > ((type *)inoutvec)[i]) ((type *)inoutvec)[i] = ((type *)invec)[i];
318 MPI_OP_SWITCH(MPI_MAX)
322 void MPI_MIN_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
323 #define MPI_OP_IMPL(type) \
324 if(((type *)invec)[i] < ((type *)inoutvec)[i]) ((type *)inoutvec)[i] = ((type *)invec)[i];
325 MPI_OP_SWITCH(MPI_MIN)
329 void MPI_SUM_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
330 #define MPI_OP_IMPL(type) \
331 ((type *)inoutvec)[i] += ((type *)invec)[i];
332 MPI_OP_SWITCH(MPI_SUM)
336 void MPI_PROD_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
337 #define MPI_OP_IMPL(type) \
338 ((type *)inoutvec)[i] *= ((type *)invec)[i];
339 MPI_OP_SWITCH(MPI_PROD)
343 void MPI_REPLACE_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
344 #define MPI_OP_IMPL(type) \
345 ((type *)inoutvec)[i] = ((type *)invec)[i];
346 MPI_OP_SWITCH(MPI_REPLACE)
350 void MPI_NO_OP_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
354 void MPI_LAND_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
355 #define MPI_OP_IMPL(type) \
356 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] && ((type *)invec)[i];
357 MPI_LOGICAL_OP_SWITCH(MPI_LAND)
361 void MPI_BAND_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
362 #define MPI_OP_IMPL(type) \
363 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] & ((type *)invec)[i];
364 MPI_BITWISE_OP_SWITCH(MPI_BAND)
368 void MPI_LOR_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
369 #define MPI_OP_IMPL(type) \
370 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] || ((type *)invec)[i];
371 MPI_LOGICAL_OP_SWITCH(MPI_LAND)
375 void MPI_BOR_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
376 #define MPI_OP_IMPL(type) \
377 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] | ((type *)invec)[i];
378 MPI_BITWISE_OP_SWITCH(MPI_BAND)
382 void MPI_LXOR_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
383 #define MPI_OP_IMPL(type) \
384 ((type *)inoutvec)[i] = (((type *)inoutvec)[i]&&(!((type *)invec)[i]))||(!(((type *)inoutvec)[i])&&((type *)invec)[i]);
385 MPI_LOGICAL_OP_SWITCH(MPI_LAND)
389 void MPI_BXOR_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
390 #define MPI_OP_IMPL(type) \
391 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] ^ ((type *)invec)[i];
392 MPI_BITWISE_OP_SWITCH(MPI_BAND)
397 #define MIN(a,b) (a < b ? a : b)
400 void MPI_MAXLOC_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
405 for(i=0;i<(*len);i++){
406 if(((FloatInt *)invec)[i].val > ((FloatInt *)inoutvec)[i].val)
407 ((FloatInt *)inoutvec)[i] = ((FloatInt *)invec)[i];
408 else if(((FloatInt *)invec)[i].val == ((FloatInt *)inoutvec)[i].val)
409 ((FloatInt *)inoutvec)[i].idx = MIN(((FloatInt *)inoutvec)[i].idx, ((FloatInt *)invec)[i].idx);
413 for(i=0;i<(*len);i++){
414 if(((DoubleInt *)invec)[i].val > ((DoubleInt *)inoutvec)[i].val)
415 ((DoubleInt *)inoutvec)[i] = ((DoubleInt *)invec)[i];
416 else if(((DoubleInt *)invec)[i].val == ((DoubleInt *)inoutvec)[i].val)
417 ((DoubleInt *)inoutvec)[i].idx = MIN(((DoubleInt *)inoutvec)[i].idx, ((DoubleInt *)invec)[i].idx);
421 for(i=0;i<(*len);i++){
422 if(((LongInt *)invec)[i].val > ((LongInt *)inoutvec)[i].val)
423 ((LongInt *)inoutvec)[i] = ((LongInt *)invec)[i];
424 else if(((LongInt *)invec)[i].val == ((LongInt *)inoutvec)[i].val)
425 ((LongInt *)inoutvec)[i].idx = MIN(((LongInt *)inoutvec)[i].idx, ((LongInt *)invec)[i].idx);
429 for(i=0;i<(*len);i++){
430 if(((IntInt *)invec)[i].val > ((IntInt *)inoutvec)[i].val)
431 ((IntInt *)inoutvec)[i] = ((IntInt *)invec)[i];
432 else if(((IntInt *)invec)[i].val == ((IntInt *)inoutvec)[i].val)
433 ((IntInt *)inoutvec)[i].idx = MIN(((IntInt *)inoutvec)[i].idx, ((IntInt *)invec)[i].idx);
437 for(i=0;i<(*len);i++){
438 if(((ShortInt *)invec)[i].val > ((ShortInt *)inoutvec)[i].val)
439 ((ShortInt *)inoutvec)[i] = ((ShortInt *)invec)[i];
440 else if(((ShortInt *)invec)[i].val == ((ShortInt *)inoutvec)[i].val)
441 ((ShortInt *)inoutvec)[i].idx = MIN(((ShortInt *)inoutvec)[i].idx, ((ShortInt *)invec)[i].idx);
444 case MPI_LONG_DOUBLE_INT:
445 for(i=0;i<(*len);i++){
446 if(((LongdoubleInt *)invec)[i].val > ((LongdoubleInt *)inoutvec)[i].val)
447 ((LongdoubleInt *)inoutvec)[i] = ((LongdoubleInt *)invec)[i];
448 else if(((LongdoubleInt *)invec)[i].val == ((LongdoubleInt *)inoutvec)[i].val)
449 ((LongdoubleInt *)inoutvec)[i].idx = MIN(((LongdoubleInt *)inoutvec)[i].idx, ((LongdoubleInt *)invec)[i].idx);
453 for(i=0;i<(*len);i++){
454 if(((FloatFloat *)invec)[i].val > ((FloatFloat *)inoutvec)[i].val)
455 ((FloatFloat *)inoutvec)[i] = ((FloatFloat *)invec)[i];
456 else if(((FloatFloat *)invec)[i].val == ((FloatFloat *)inoutvec)[i].val)
457 ((FloatFloat *)inoutvec)[i].idx = MIN(((FloatFloat *)inoutvec)[i].idx, ((FloatFloat *)invec)[i].idx);
461 for(i=0;i<(*len);i++){
462 if(((DoubleDouble *)invec)[i].val > ((DoubleDouble *)inoutvec)[i].val)
463 ((DoubleDouble *)inoutvec)[i] = ((DoubleDouble *)invec)[i];
464 else if(((DoubleDouble *)invec)[i].val == ((DoubleDouble *)inoutvec)[i].val)
465 ((DoubleDouble *)inoutvec)[i].idx = MIN(((DoubleDouble *)inoutvec)[i].idx, ((DoubleDouble *)invec)[i].idx);
469 ckerr << "Type " << *datatype << " with Op MPI_MAXLOC not supported." << endl;
474 void MPI_MINLOC_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
478 for(i=0;i<(*len);i++){
479 if(((FloatInt *)invec)[i].val < ((FloatInt *)inoutvec)[i].val)
480 ((FloatInt *)inoutvec)[i] = ((FloatInt *)invec)[i];
481 else if(((FloatInt *)invec)[i].val == ((FloatInt *)inoutvec)[i].val)
482 ((FloatInt *)inoutvec)[i].idx = MIN(((FloatInt *)inoutvec)[i].idx, ((FloatInt *)invec)[i].idx);
486 for(i=0;i<(*len);i++){
487 if(((DoubleInt *)invec)[i].val < ((DoubleInt *)inoutvec)[i].val)
488 ((DoubleInt *)inoutvec)[i] = ((DoubleInt *)invec)[i];
489 else if(((DoubleInt *)invec)[i].val == ((DoubleInt *)inoutvec)[i].val)
490 ((DoubleInt *)inoutvec)[i].idx = MIN(((DoubleInt *)inoutvec)[i].idx, ((DoubleInt *)invec)[i].idx);
494 for(i=0;i<(*len);i++){
495 if(((LongInt *)invec)[i].val < ((LongInt *)inoutvec)[i].val)
496 ((LongInt *)inoutvec)[i] = ((LongInt *)invec)[i];
497 else if(((LongInt *)invec)[i].val == ((LongInt *)inoutvec)[i].val)
498 ((LongInt *)inoutvec)[i].idx = MIN(((LongInt *)inoutvec)[i].idx, ((LongInt *)invec)[i].idx);
502 for(i=0;i<(*len);i++){
503 if(((IntInt *)invec)[i].val < ((IntInt *)inoutvec)[i].val)
504 ((IntInt *)inoutvec)[i] = ((IntInt *)invec)[i];
505 else if(((IntInt *)invec)[i].val == ((IntInt *)inoutvec)[i].val)
506 ((IntInt *)inoutvec)[i].idx = MIN(((IntInt *)inoutvec)[i].idx, ((IntInt *)invec)[i].idx);
510 for(i=0;i<(*len);i++){
511 if(((ShortInt *)invec)[i].val < ((ShortInt *)inoutvec)[i].val)
512 ((ShortInt *)inoutvec)[i] = ((ShortInt *)invec)[i];
513 else if(((ShortInt *)invec)[i].val == ((ShortInt *)inoutvec)[i].val)
514 ((ShortInt *)inoutvec)[i].idx = MIN(((ShortInt *)inoutvec)[i].idx, ((ShortInt *)invec)[i].idx);
517 case MPI_LONG_DOUBLE_INT:
518 for(i=0;i<(*len);i++){
519 if(((LongdoubleInt *)invec)[i].val < ((LongdoubleInt *)inoutvec)[i].val)
520 ((LongdoubleInt *)inoutvec)[i] = ((LongdoubleInt *)invec)[i];
521 else if(((LongdoubleInt *)invec)[i].val == ((LongdoubleInt *)inoutvec)[i].val)
522 ((LongdoubleInt *)inoutvec)[i].idx = MIN(((LongdoubleInt *)inoutvec)[i].idx, ((LongdoubleInt *)invec)[i].idx);
526 for(i=0;i<(*len);i++){
527 if(((FloatFloat *)invec)[i].val < ((FloatFloat *)inoutvec)[i].val)
528 ((FloatFloat *)inoutvec)[i] = ((FloatFloat *)invec)[i];
529 else if(((FloatFloat *)invec)[i].val == ((FloatFloat *)inoutvec)[i].val)
530 ((FloatFloat *)inoutvec)[i].idx = MIN(((FloatFloat *)inoutvec)[i].idx, ((FloatFloat *)invec)[i].idx);
534 for(i=0;i<(*len);i++){
535 if(((DoubleDouble *)invec)[i].val < ((DoubleDouble *)inoutvec)[i].val)
536 ((DoubleDouble *)inoutvec)[i] = ((DoubleDouble *)invec)[i];
537 else if(((DoubleDouble *)invec)[i].val == ((DoubleDouble *)inoutvec)[i].val)
538 ((DoubleDouble *)inoutvec)[i].idx = MIN(((DoubleDouble *)inoutvec)[i].idx, ((DoubleDouble *)invec)[i].idx);
542 ckerr << "Type " << *datatype << " with Op MPI_MINLOC not supported." << endl;
548 * AMPI's generic reducer type, AmpiReducer, is used only
549 * for MPI_Op/MPI_Datatype combinations that Charm++ does
550 * not have built-in support for. AmpiReducer reduction
551 * contributions all contain an AmpiOpHeader, that contains
552 * the function pointer to an MPI_User_function* that is
553 * applied to all contributions in AmpiReducerFunc().
555 * If AmpiReducer is used, the final reduction message will
556 * have an additional sizeof(AmpiOpHeader) bytes in the
557 * buffer before any user data. ampi::processRednMsg() strips
560 * If a non-commutative (user-defined) reduction is used,
561 * ampi::processNoncommutativeRednMsg() strips the headers
562 * and applies the op to all contributions in rank order.
564 CkReduction::reducerType AmpiReducer;
566 // every msg contains a AmpiOpHeader structure before user data
567 CkReductionMsg *AmpiReducerFunc(int nMsg, CkReductionMsg **msgs){
568 AmpiOpHeader *hdr = (AmpiOpHeader *)msgs[0]->getData();
570 int szhdr, szdata, len;
571 MPI_User_function* func;
574 szdata = hdr->szdata;
576 szhdr = sizeof(AmpiOpHeader);
578 //Assuming extent == size
579 vector<char> ret(szhdr+szdata);
580 char *retPtr = &ret[0];
581 memcpy(retPtr,msgs[0]->getData(),szhdr+szdata);
582 for(int i=1;i<nMsg;i++){
583 (*func)((void *)((char *)msgs[i]->getData()+szhdr),(void *)(retPtr+szhdr),&len,&dtype);
585 CkReductionMsg *retmsg = CkReductionMsg::buildNew(szhdr+szdata,retPtr);
589 static CkReduction::reducerType getBuiltinReducerType(MPI_Datatype type, MPI_Op op)
593 if (getDDT()->getSize(MPI_INT32_T) != getDDT()->getSize(MPI_INT)) break;
594 // else: fall thru to MPI_INT
597 case MPI_MAX: return CkReduction::max_int;
598 case MPI_MIN: return CkReduction::min_int;
599 case MPI_SUM: return CkReduction::sum_int;
600 case MPI_PROD: return CkReduction::product_int;
601 case MPI_LAND: return CkReduction::logical_and_int;
602 case MPI_LOR: return CkReduction::logical_or_int;
603 case MPI_LXOR: return CkReduction::logical_xor_int;
604 case MPI_BAND: return CkReduction::bitvec_and_int;
605 case MPI_BOR: return CkReduction::bitvec_or_int;
606 case MPI_BXOR: return CkReduction::bitvec_xor_int;
611 case MPI_MAX: return CkReduction::max_float;
612 case MPI_MIN: return CkReduction::min_float;
613 case MPI_SUM: return CkReduction::sum_float;
614 case MPI_PROD: return CkReduction::product_float;
619 case MPI_MAX: return CkReduction::max_double;
620 case MPI_MIN: return CkReduction::min_double;
621 case MPI_SUM: return CkReduction::sum_double;
622 case MPI_PROD: return CkReduction::product_double;
626 if (getDDT()->getSize(MPI_INT8_T) != getDDT()->getSize(MPI_CHAR)) break;
627 // else: fall thru to MPI_CHAR
630 case MPI_MAX: return CkReduction::max_char;
631 case MPI_MIN: return CkReduction::min_char;
632 case MPI_SUM: return CkReduction::sum_char;
633 case MPI_PROD: return CkReduction::product_char;
637 if (getDDT()->getSize(MPI_INT16_T) != getDDT()->getSize(MPI_SHORT)) break;
638 // else: fall thru to MPI_SHORT
641 case MPI_MAX: return CkReduction::max_short;
642 case MPI_MIN: return CkReduction::min_short;
643 case MPI_SUM: return CkReduction::sum_short;
644 case MPI_PROD: return CkReduction::product_short;
649 case MPI_MAX: return CkReduction::max_long;
650 case MPI_MIN: return CkReduction::min_long;
651 case MPI_SUM: return CkReduction::sum_long;
652 case MPI_PROD: return CkReduction::product_long;
656 if (getDDT()->getSize(MPI_INT64_T) != getDDT()->getSize(MPI_LONG_LONG)) break;
657 // else: fall thru to MPI_LONG_LONG
660 case MPI_MAX: return CkReduction::max_long_long;
661 case MPI_MIN: return CkReduction::min_long_long;
662 case MPI_SUM: return CkReduction::sum_long_long;
663 case MPI_PROD: return CkReduction::product_long_long;
667 if (getDDT()->getSize(MPI_UINT8_T) != getDDT()->getSize(MPI_UNSIGNED_CHAR)) break;
668 // else: fall thru to MPI_UNSIGNED_CHAR
669 case MPI_UNSIGNED_CHAR:
671 case MPI_MAX: return CkReduction::max_uchar;
672 case MPI_MIN: return CkReduction::min_uchar;
673 case MPI_SUM: return CkReduction::sum_uchar;
674 case MPI_PROD: return CkReduction::product_uchar;
678 if (getDDT()->getSize(MPI_UINT16_T) != getDDT()->getSize(MPI_UNSIGNED_SHORT)) break;
679 // else: fall thru to MPI_UNSIGNED_SHORT
680 case MPI_UNSIGNED_SHORT:
682 case MPI_MAX: return CkReduction::max_ushort;
683 case MPI_MIN: return CkReduction::min_ushort;
684 case MPI_SUM: return CkReduction::sum_ushort;
685 case MPI_PROD: return CkReduction::product_ushort;
689 if (getDDT()->getSize(MPI_UINT32_T) != getDDT()->getSize(MPI_UNSIGNED)) break;
690 // else: fall thru to MPI_UNSIGNED
693 case MPI_MAX: return CkReduction::max_uint;
694 case MPI_MIN: return CkReduction::min_uint;
695 case MPI_SUM: return CkReduction::sum_uint;
696 case MPI_PROD: return CkReduction::product_uint;
699 case MPI_UNSIGNED_LONG:
701 case MPI_MAX: return CkReduction::max_ulong;
702 case MPI_MIN: return CkReduction::min_ulong;
703 case MPI_SUM: return CkReduction::sum_ulong;
704 case MPI_PROD: return CkReduction::product_ulong;
708 if (getDDT()->getSize(MPI_UINT64_T) != getDDT()->getSize(MPI_UNSIGNED_LONG_LONG)) break;
709 // else: fall thru to MPI_UNSIGNED_LONG_LONG
710 case MPI_UNSIGNED_LONG_LONG:
712 case MPI_MAX: return CkReduction::max_ulong_long;
713 case MPI_MIN: return CkReduction::min_ulong_long;
714 case MPI_SUM: return CkReduction::sum_ulong_long;
715 case MPI_PROD: return CkReduction::product_ulong_long;
720 case MPI_LAND: return CkReduction::logical_and_bool;
721 case MPI_LOR: return CkReduction::logical_or_bool;
722 case MPI_LXOR: return CkReduction::logical_xor_bool;
727 case MPI_LAND: return CkReduction::logical_and_int;
728 case MPI_LOR: return CkReduction::logical_or_int;
729 case MPI_LXOR: return CkReduction::logical_xor_int;
734 case MPI_BAND: return CkReduction::bitvec_and_bool;
735 case MPI_BOR: return CkReduction::bitvec_or_bool;
736 case MPI_BXOR: return CkReduction::bitvec_xor_bool;
742 return CkReduction::invalid;
747 int tag_ub,host,io,wtime_is_global,appnum,universe_size;
749 int win_disp_unit,win_create_flavor,win_model;
753 tag_ub = MPI_TAG_UB_VALUE;
754 host = MPI_PROC_NULL;
762 win_create_flavor = MPI_WIN_FLAVOR_CREATE;
763 win_model = MPI_WIN_SEPARATE;
768 // ------------ startup support -----------
769 int _ampi_fallback_setup_count;
770 CDECL void AMPI_Setup(void);
771 FDECL void FTN_NAME(AMPI_SETUP,ampi_setup)(void);
773 FDECL void FTN_NAME(MPI_MAIN,mpi_main)(void);
775 /*Main routine used when missing MPI_Setup routine*/
777 void AMPI_Fallback_Main(int argc,char **argv)
780 AMPI_Main_cpp(argc,argv);
781 AMPI_Main_c(argc,argv);
782 FTN_NAME(MPI_MAIN,mpi_main)();
785 void ampiCreateMain(MPI_MainFn mainFn, const char *name,int nameLen);
786 /*Startup routine used if user *doesn't* write
787 a TCHARM_User_setup routine.
790 void AMPI_Setup_Switch(void) {
791 _ampi_fallback_setup_count=0;
792 FTN_NAME(AMPI_SETUP,ampi_setup)();
794 if (_ampi_fallback_setup_count==2)
795 { //Missing AMPI_Setup in both C and Fortran:
796 ampiCreateMain(AMPI_Fallback_Main,"default",strlen("default"));
800 static bool nodeinit_has_been_called=false;
801 CtvDeclare(ampiParent*, ampiPtr);
802 CtvDeclare(bool, ampiInitDone);
803 CtvDeclare(void*,stackBottom);
804 CtvDeclare(bool, ampiFinalized);
805 CkpvDeclare(Builtin_kvs, bikvs);
806 CkpvDeclare(int, ampiThreadLevel);
809 long ampiCurrentStackUsage(void){
812 unsigned long p1 = (unsigned long)((void*)&localVariable);
813 unsigned long p2 = (unsigned long)(CtvAccess(stackBottom));
822 void FTN_NAME(AMPICURRENTSTACKUSAGE, ampicurrentstackusage)(void){
823 long usage = ampiCurrentStackUsage();
824 CkPrintf("[%d] Stack usage is currently %ld\n", CkMyPe(), usage);
828 void AMPI_threadstart(void *data);
829 static int AMPI_threadstart_idx = -1;
831 static void ampiNodeInit(void)
834 for(int i=0;i<MPI_MAX_COMM_WORLDS; i++)
836 MPI_COMM_UNIVERSE[i] = MPI_COMM_WORLD+1+i;
838 TCHARM_Set_fallback_setup(AMPI_Setup_Switch);
840 AmpiReducer = CkReduction::addReducer(AmpiReducerFunc);
842 CkAssert(AMPI_threadstart_idx == -1); // only initialize once
843 AMPI_threadstart_idx = TCHARM_Register_thread_function(AMPI_threadstart);
845 nodeinit_has_been_called=true;
847 // ASSUME NO ANYTIME MIGRATION and STATIC INSERTON
848 _isAnytimeMigration = false;
849 _isStaticInsertion = true;
853 static double totalidle=0.0, startT=0.0;
854 static int beginHandle, endHandle;
855 static void BeginIdle(void *dummy,double curWallTime)
857 startT = curWallTime;
859 static void EndIdle(void *dummy,double curWallTime)
861 totalidle += curWallTime - startT;
865 static void ampiProcInit(void){
866 CtvInitialize(ampiParent*, ampiPtr);
867 CtvInitialize(bool,ampiInitDone);
868 CtvInitialize(bool,ampiFinalized);
869 CtvInitialize(void*,stackBottom);
871 CkpvInitialize(int, ampiThreadLevel);
872 CkpvAccess(ampiThreadLevel) = MPI_THREAD_SINGLE;
874 CkpvInitialize(Builtin_kvs, bikvs); // built-in key-values
875 CkpvAccess(bikvs) = Builtin_kvs();
877 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
880 initAmpiProjections();
883 char **argv=CkGetArgv();
884 msgLogWrite = CmiGetArgFlag(argv, "+msgLogWrite");
885 if (CmiGetArgIntDesc(argv,"+msgLogRead", &msgLogRank, "Re-play message processing order for AMPI")) {
889 if (CmiGetArgStringDesc(argv, "+msgLogRanks", &procs, "A list of AMPI processors to record , e.g. 0,10,20-30")) {
890 msgLogRanks.set(procs);
892 CmiGetArgString(argv, "+msgLogFilename", &msgLogFilename);
894 if (msgLogWrite) CkPrintf("Writing AMPI messages of rank %s to log: %s\n", procs?procs:"", msgLogFilename);
895 if (msgLogRead) CkPrintf("Reading AMPI messages of rank %s from log: %s\n", procs?procs:"", msgLogFilename);
901 static inline int record_msglog(int rank){
902 return msgLogRanks.includes(rank);
906 PUPfunctionpointer(MPI_MainFn)
908 class MPI_threadstart_t {
911 MPI_threadstart_t() {}
912 MPI_threadstart_t(MPI_MainFn fn_):fn(fn_) {}
914 char **argv=CmiCopyArgs(CkGetArgv());
915 int argc=CkGetArgc();
917 // Set a pointer to somewhere close to the bottom of the stack.
918 // This is used for roughly estimating the stack usage later.
919 CtvAccess(stackBottom) = &argv;
921 #if CMK_AMPI_FNPTR_HACK
922 AMPI_Fallback_Main(argc,argv);
927 void pup(PUP::er &p) {
931 PUPmarshall(MPI_threadstart_t)
934 void AMPI_threadstart(void *data)
936 STARTUP_DEBUG("MPI_threadstart")
939 #if CMK_TRACE_IN_CHARM
940 if(CpvAccess(traceOn)) CthTraceResume(CthSelf());
945 void ampiCreateMain(MPI_MainFn mainFn, const char *name,int nameLen)
947 STARTUP_DEBUG("ampiCreateMain")
948 int _nchunks=TCHARM_Get_num_chunks();
949 //Make a new threads array:
950 MPI_threadstart_t s(mainFn);
951 memBuf b; pupIntoBuf(b,s);
952 TCHARM_Create_data(_nchunks,AMPI_threadstart_idx,
953 b.getData(), b.getSize());
956 /* TCharm Semaphore ID's for AMPI startup */
957 #define AMPI_TCHARM_SEMAID 0x00A34100 /* __AMPI__ */
958 #define AMPI_BARRIER_SEMAID 0x00A34200 /* __AMPI__ */
960 static CProxy_ampiWorlds ampiWorldsGroup;
962 void ampiParent::initOps(void)
964 ops.resize(MPI_NO_OP+1);
965 ops[MPI_MAX] = OpStruct(MPI_MAX_USER_FN);
966 ops[MPI_MIN] = OpStruct(MPI_MIN_USER_FN);
967 ops[MPI_SUM] = OpStruct(MPI_SUM_USER_FN);
968 ops[MPI_PROD] = OpStruct(MPI_PROD_USER_FN);
969 ops[MPI_LAND] = OpStruct(MPI_LAND_USER_FN);
970 ops[MPI_BAND] = OpStruct(MPI_BAND_USER_FN);
971 ops[MPI_LOR] = OpStruct(MPI_LOR_USER_FN);
972 ops[MPI_BOR] = OpStruct(MPI_BOR_USER_FN);
973 ops[MPI_LXOR] = OpStruct(MPI_LXOR_USER_FN);
974 ops[MPI_BXOR] = OpStruct(MPI_BXOR_USER_FN);
975 ops[MPI_MAXLOC] = OpStruct(MPI_MAXLOC_USER_FN);
976 ops[MPI_MINLOC] = OpStruct(MPI_MINLOC_USER_FN);
977 ops[MPI_REPLACE] = OpStruct(MPI_REPLACE_USER_FN);
978 ops[MPI_NO_OP] = OpStruct(MPI_NO_OP_USER_FN);
982 Called from MPI_Init, a collective initialization call:
983 creates a new AMPI array and attaches it to the current
984 set of TCHARM threads.
986 static ampi *ampiInit(char **argv)
988 FUNCCALL_DEBUG(CkPrintf("Calling from proc %d for tcharm element %d\n", CkMyPe(), TCHARM_Element());)
989 if (CtvAccess(ampiInitDone)) return NULL; /* Already called ampiInit */
990 STARTUP_DEBUG("ampiInit> begin")
995 CProxy_ampiParent parent;
996 if (TCHARM_Element()==0) //the rank of a tcharm object
997 { /* I'm responsible for building the arrays: */
998 STARTUP_DEBUG("ampiInit> creating arrays")
1000 // FIXME: Need to serialize global communicator allocation in one place.
1001 //Allocate the next communicator
1002 if(_mpi_nworlds == MPI_MAX_COMM_WORLDS)
1004 CkAbort("AMPI> Number of registered comm_worlds exceeded limit.\n");
1006 int new_idx=_mpi_nworlds;
1007 new_world=MPI_COMM_WORLD+new_idx;
1009 //Create and attach the ampiParent array
1011 opts=TCHARM_Attach_start(&threads,&_nchunks);
1012 opts.setSectionAutoDelegate(false);
1013 CkArrayCreatedMsg *m;
1014 CProxy_ampiParent::ckNew(new_world, threads, opts, CkCallbackResumeThread((void*&)m));
1015 parent = CProxy_ampiParent(m->aid);
1016 STARTUP_DEBUG("ampiInit> array size "<<_nchunks);
1018 int *barrier = (int *)TCharm::get()->semaGet(AMPI_BARRIER_SEMAID);
1020 FUNCCALL_DEBUG(CkPrintf("After BARRIER: sema size %d from tcharm's ele %d\n", TCharm::get()->sema.size(), TCHARM_Element());)
1022 if (TCHARM_Element()==0)
1024 //Make a new ampi array
1027 ampiCommStruct worldComm(new_world,empty,_nchunks);
1029 CkArrayCreatedMsg *m;
1030 CProxy_ampi::ckNew(parent, worldComm, opts, CkCallbackResumeThread((void*&)m));
1031 arr = CProxy_ampi(m->aid);
1033 //Broadcast info. to the mpi_worlds array
1034 // FIXME: remove race condition from MPI_COMM_UNIVERSE broadcast
1035 ampiCommStruct newComm(new_world,arr,_nchunks);
1036 if (ampiWorldsGroup.ckGetGroupID().isZero())
1037 ampiWorldsGroup=CProxy_ampiWorlds::ckNew(newComm);
1039 ampiWorldsGroup.add(newComm);
1040 STARTUP_DEBUG("ampiInit> arrays created")
1043 // Find our ampi object:
1044 ampi *ptr=(ampi *)TCharm::get()->semaGet(AMPI_TCHARM_SEMAID);
1045 CtvAccess(ampiInitDone)=true;
1046 CtvAccess(ampiFinalized)=false;
1047 STARTUP_DEBUG("ampiInit> complete")
1048 #if CMK_BIGSIM_CHARM
1049 // TRACE_BG_AMPI_START(ptr->getThread(), "AMPI_START");
1050 TRACE_BG_ADD_TAG("AMPI_START");
1053 getAmpiParent()->initOps(); // initialize reduction operations
1054 getAmpiParent()->setCommAttr(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, &_nchunks);
1055 ptr->setCommName("MPI_COMM_WORLD");
1057 getAmpiParent()->ampiInitCallDone = 0;
1059 CProxy_ampi cbproxy = ptr->getProxy();
1060 CkCallback cb(CkReductionTarget(ampi, allInitDone), cbproxy[0]);
1061 ptr->contribute(cb);
1063 ampiParent *thisParent = getAmpiParent();
1064 while(thisParent->ampiInitCallDone!=1){
1065 thisParent->getTCharmThread()->stop();
1067 * thisParent needs to be updated in case of the parent is being pupped.
1068 * In such case, thisParent got changed
1070 thisParent = getAmpiParent();
1073 #if CMK_BIGSIM_CHARM
1074 BgSetStartOutOfCore();
1080 /// This group is used to broadcast the MPI_COMM_UNIVERSE communicators.
1081 class ampiWorlds : public CBase_ampiWorlds {
1083 ampiWorlds(const ampiCommStruct &nextWorld) {
1084 ampiWorldsGroup=thisgroup;
1087 ampiWorlds(CkMigrateMessage *m): CBase_ampiWorlds(m) {}
1088 void pup(PUP::er &p) { }
1089 void add(const ampiCommStruct &nextWorld) {
1090 int new_idx=nextWorld.getComm()-(MPI_COMM_WORLD);
1091 mpi_worlds[new_idx]=nextWorld;
1092 if (_mpi_nworlds<=new_idx) _mpi_nworlds=new_idx+1;
1093 STARTUP_DEBUG("ampiInit> listed MPI_COMM_UNIVERSE "<<new_idx)
1097 //-------------------- ampiParent -------------------------
1098 ampiParent::ampiParent(MPI_Comm worldNo_,CProxy_TCharm threads_)
1099 :threads(threads_), worldNo(worldNo_), isTmpRProxySet(false)
1101 int barrier = 0x1234;
1102 STARTUP_DEBUG("ampiParent> starting up")
1105 userAboutToMigrateFn=NULL;
1106 userJustMigratedFn=NULL;
1112 thread->semaPut(AMPI_BARRIER_SEMAID,&barrier);
1113 AsyncEvacuate(false);
1116 ampiParent::ampiParent(CkMigrateMessage *msg):CBase_ampiParent(msg) {
1123 AsyncEvacuate(false);
1126 PUPfunctionpointer(MPI_MigrateFn)
1128 void ampiParent::pup(PUP::er &p) {
1151 p|userAboutToMigrateFn;
1152 p|userJustMigratedFn;
1160 void ampiParent::prepareCtv(void) {
1161 thread=threads[thisIndex].ckLocal();
1162 if (thread==NULL) CkAbort("AMPIParent cannot find its thread!\n");
1163 CtvAccessOther(thread->getThread(),ampiPtr) = this;
1164 STARTUP_DEBUG("ampiParent> found TCharm")
1167 void ampiParent::init(){
1168 CkAssert(groups.size() == 0);
1169 groups.push_back(new groupStruct);
1170 resumeOnRecv = false;
1171 resumeOnColl = false;
1174 if(msgLogWrite && record_msglog(thisIndex)){
1176 sprintf(fname, "%s.%d", msgLogFilename,thisIndex);
1177 #if CMK_PROJECTIONS_USE_ZLIB && 0
1178 fMsgLog = gzopen(fname,"wb");
1179 toPUPer = new PUP::tozDisk(fMsgLog);
1181 fMsgLog = fopen(fname,"wb");
1182 CkAssert(fMsgLog != NULL);
1183 toPUPer = new PUP::toDisk(fMsgLog);
1185 }else if(msgLogRead){
1187 sprintf(fname, "%s.%d", msgLogFilename,msgLogRank);
1188 #if CMK_PROJECTIONS_USE_ZLIB && 0
1189 fMsgLog = gzopen(fname,"rb");
1190 fromPUPer = new PUP::fromzDisk(fMsgLog);
1192 fMsgLog = fopen(fname,"rb");
1193 CkAssert(fMsgLog != NULL);
1194 fromPUPer = new PUP::fromDisk(fMsgLog);
1196 CkPrintf("AMPI> opened message log file: %s for replay\n", fname);
1201 void ampiParent::finalize(){
1203 if(msgLogWrite && record_msglog(thisIndex)){
1205 #if CMK_PROJECTIONS_USE_ZLIB && 0
1210 }else if(msgLogRead){
1212 #if CMK_PROJECTIONS_USE_ZLIB && 0
1221 void ampiParent::setUserAboutToMigrateFn(MPI_MigrateFn f) {
1222 userAboutToMigrateFn = f;
1225 void ampiParent::setUserJustMigratedFn(MPI_MigrateFn f) {
1226 userJustMigratedFn = f;
1229 void ampiParent::ckAboutToMigrate(void) {
1230 if (userAboutToMigrateFn) {
1231 (*userAboutToMigrateFn)();
1235 void ampiParent::ckJustMigrated(void) {
1236 ArrayElement1D::ckJustMigrated();
1238 if (userJustMigratedFn) {
1239 (*userJustMigratedFn)();
1243 void ampiParent::ckJustRestored(void) {
1244 FUNCCALL_DEBUG(CkPrintf("Call just restored from ampiParent[%d] with ampiInitCallDone %d\n", thisIndex, ampiInitCallDone);)
1245 ArrayElement1D::ckJustRestored();
1249 ampiParent::~ampiParent() {
1250 STARTUP_DEBUG("ampiParent> destructor called");
1254 //Children call this when they are first created or just migrated
1255 TCharm *ampiParent::registerAmpi(ampi *ptr,ampiCommStruct s,bool forMigration)
1257 if (thread==NULL) prepareCtv(); //Prevents CkJustMigrated race condition
1259 if (s.getComm()>=MPI_COMM_WORLD)
1260 { //We now have our COMM_WORLD-- register it
1261 //Note that split communicators don't keep a raw pointer, so
1262 //they don't need to re-register on migration.
1263 if (worldPtr!=NULL) CkAbort("One ampiParent has two MPI_COMM_WORLDs");
1267 //MPI_COMM_SELF has the same member as MPI_COMM_WORLD, but it's alone:
1268 vector<int> _indices;
1269 _indices.push_back(thisIndex);
1270 selfStruct = ampiCommStruct(MPI_COMM_SELF,s.getProxy(),1,_indices);
1271 selfStruct.setName("MPI_COMM_SELF");
1275 { //Register the new communicator:
1276 MPI_Comm comm = s.getComm();
1277 STARTUP_DEBUG("ampiParent> registering new communicator "<<comm)
1278 if (comm>=MPI_COMM_WORLD) {
1279 // Pass the new ampi to the waiting ampiInit
1280 thread->semaPut(AMPI_TCHARM_SEMAID, ptr);
1281 } else if (isSplit(comm)) {
1282 splitChildRegister(s);
1283 } else if (isGroup(comm)) {
1284 groupChildRegister(s);
1285 } else if (isCart(comm)) {
1286 cartChildRegister(s);
1287 } else if (isGraph(comm)) {
1288 graphChildRegister(s);
1289 } else if (isInter(comm)) {
1290 interChildRegister(s);
1291 } else if (isIntra(comm)) {
1292 intraChildRegister(s);
1294 CkAbort("ampiParent recieved child with bad communicator");
1300 // reduction client data - preparation for checkpointing
1301 class ckptClientStruct {
1304 ampiParent *ampiPtr;
1305 ckptClientStruct(const char *s, ampiParent *a): dname(s), ampiPtr(a) {}
1308 static void checkpointClient(void *param,void *msg)
1310 ckptClientStruct *client = (ckptClientStruct*)param;
1311 const char *dname = client->dname;
1312 ampiParent *ampiPtr = client->ampiPtr;
1313 ampiPtr->Checkpoint(strlen(dname), dname);
1317 void ampiParent::startCheckpoint(const char* dname){
1319 ckptClientStruct *clientData = new ckptClientStruct(dname, this);
1320 CkCallback *cb = new CkCallback(checkpointClient, clientData);
1321 thisProxy.ckSetReductionClient(cb);
1327 #if CMK_BIGSIM_CHARM
1328 TRACE_BG_ADD_TAG("CHECKPOINT_RESUME");
1332 void ampiParent::Checkpoint(int len, const char* dname){
1334 // memory checkpoint
1335 CkCallback cb(CkIndex_ampiParent::ResumeThread(),thisArrayID);
1336 CkStartMemCheckpoint(cb);
1340 strncpy(dirname,dname,len);
1342 CkCallback cb(CkIndex_ampiParent::ResumeThread(),thisArrayID);
1343 CkStartCheckpoint(dirname,cb);
1347 void ampiParent::ResumeThread(void){
1351 int ampiParent::createKeyval(MPI_Comm_copy_attr_function *copy_fn, MPI_Comm_delete_attr_function *delete_fn,
1352 int *keyval, void* extra_state){
1353 KeyvalNode* newnode = new KeyvalNode(copy_fn, delete_fn, extra_state);
1354 int idx = kvlist.size();
1355 kvlist.resize(idx+1);
1356 kvlist[idx] = newnode;
1361 int ampiParent::freeKeyval(int *keyval){
1362 #if AMPI_ERROR_CHECKING
1363 if(*keyval<0 || *keyval >= kvlist.size() || !kvlist[*keyval])
1364 return MPI_ERR_KEYVAL;
1366 delete kvlist[*keyval];
1367 kvlist[*keyval] = NULL;
1368 *keyval = MPI_KEYVAL_INVALID;
1372 int ampiParent::setUserKeyval(MPI_Comm comm, int keyval, void *attribute_val){
1373 #if AMPI_ERROR_CHECKING
1374 if(keyval<0 || keyval >= kvlist.size() || (kvlist[keyval]==NULL))
1375 return MPI_ERR_KEYVAL;
1377 ampiCommStruct &cs = *(ampiCommStruct *)&comm2CommStruct(comm);
1378 // Enlarge the keyval list:
1379 if(cs.getKeyvals().size()<=keyval) cs.getKeyvals().resize(keyval+1, NULL);
1380 cs.getKeyvals()[keyval]=attribute_val;
1384 int ampiParent::setWinAttr(MPI_Win win, int keyval, void* attribute_val){
1385 if(kv_set_builtin(keyval,attribute_val))
1387 MPI_Comm comm = (getAmpiParent()->getWinStruct(win))->comm;
1388 return setUserKeyval(comm, keyval, attribute_val);
1391 int ampiParent::setCommAttr(MPI_Comm comm, int keyval, void* attribute_val){
1392 if(kv_set_builtin(keyval,attribute_val))
1394 return setUserKeyval(comm, keyval, attribute_val);
1397 bool ampiParent::kv_set_builtin(int keyval, void* attribute_val) {
1399 case MPI_TAG_UB: /*immutable*/ return false;
1400 case MPI_HOST: /*immutable*/ return false;
1401 case MPI_IO: /*immutable*/ return false;
1402 case MPI_WTIME_IS_GLOBAL: /*immutable*/ return false;
1403 case MPI_APPNUM: /*immutable*/ return false;
1404 case MPI_UNIVERSE_SIZE: (CkpvAccess(bikvs).universe_size) = *((int*)attribute_val); return true;
1405 case MPI_WIN_BASE: (CkpvAccess(bikvs).win_base) = attribute_val; return true;
1406 case MPI_WIN_SIZE: (CkpvAccess(bikvs).win_size) = *((MPI_Aint*)attribute_val); return true;
1407 case MPI_WIN_DISP_UNIT: (CkpvAccess(bikvs).win_disp_unit) = *((int*)attribute_val); return true;
1408 case MPI_WIN_CREATE_FLAVOR: (CkpvAccess(bikvs).win_create_flavor) = *((int*)attribute_val); return true;
1409 case MPI_WIN_MODEL: (CkpvAccess(bikvs).win_model) = *((int*)attribute_val); return true;
1410 case AMPI_MY_WTH: /*immutable*/ return false;
1411 case AMPI_NUM_WTHS: /*immutable*/ return false;
1412 case AMPI_MY_PROCESS: /*immutable*/ return false;
1413 case AMPI_NUM_PROCESSES: /*immutable*/ return false;
1414 default: return false;
1418 bool ampiParent::kv_get_builtin(int keyval) {
1421 case MPI_TAG_UB: kv_builtin_storage = &(CkpvAccess(bikvs).tag_ub); return true;
1422 case MPI_HOST: kv_builtin_storage = &(CkpvAccess(bikvs).host); return true;
1423 case MPI_IO: kv_builtin_storage = &(CkpvAccess(bikvs).io); return true;
1424 case MPI_WTIME_IS_GLOBAL: kv_builtin_storage = &(CkpvAccess(bikvs).wtime_is_global); return true;
1425 case MPI_APPNUM: kv_builtin_storage = &(CkpvAccess(bikvs).appnum); return true;
1426 case MPI_UNIVERSE_SIZE: kv_builtin_storage = &(CkpvAccess(bikvs).universe_size); return true;
1427 case MPI_WIN_BASE: win_base_storage = &(CkpvAccess(bikvs).win_base); return true;
1428 case MPI_WIN_SIZE: win_size_storage = &(CkpvAccess(bikvs).win_size); return true;
1429 case MPI_WIN_DISP_UNIT: kv_builtin_storage = &(CkpvAccess(bikvs).win_disp_unit); return true;
1430 case MPI_WIN_CREATE_FLAVOR: kv_builtin_storage = &(CkpvAccess(bikvs).win_create_flavor); return true;
1431 case MPI_WIN_MODEL: kv_builtin_storage = &(CkpvAccess(bikvs).win_model); return true;
1432 case AMPI_MY_WTH: tmp = CkMyPe(); kv_builtin_storage = &tmp; return true;
1433 case AMPI_NUM_WTHS: tmp = CkNumPes(); kv_builtin_storage = &tmp; return true;
1434 case AMPI_MY_PROCESS: tmp = CkMyNode(); kv_builtin_storage = &tmp; return true;
1435 case AMPI_NUM_PROCESSES: tmp = CkNumNodes(); kv_builtin_storage = &tmp; return true;
1436 default: return false;
1440 bool ampiParent::getBuiltinKeyval(int keyval, void *attribute_val) {
1441 if (kv_get_builtin(keyval)){
1442 /* All builtin keyvals are ints except MPI_WIN_BASE, which is a pointer
1443 * to the window's base address in C but an integer representation of
1444 * the base address in Fortran.
1445 * Also, MPI_WIN_SIZE is an MPI_Aint. */
1446 if (keyval == MPI_WIN_BASE)
1447 *((void**)attribute_val) = *win_base_storage;
1448 else if (keyval == MPI_WIN_SIZE)
1449 *(MPI_Aint**)attribute_val = win_size_storage;
1451 *(int **)attribute_val = kv_builtin_storage;
1457 bool ampiParent::getUserKeyval(MPI_Comm comm, int keyval, void *attribute_val, int *flag) {
1459 if (keyval<0 || keyval >= kvlist.size() || (kvlist[keyval]==NULL))
1461 ampiCommStruct &cs=*(ampiCommStruct *)&comm2CommStruct(comm);
1462 if (keyval>=cs.getKeyvals().size())
1463 return true; /* we don't have a value yet */
1464 if (cs.getKeyvals()[keyval]==NULL)
1465 return true; /* we had a value, but now it's NULL */
1466 /* Otherwise, we have a good value */
1468 *(void **)attribute_val = cs.getKeyvals()[keyval];
1472 int ampiParent::getCommAttr(MPI_Comm comm, int keyval, void *attribute_val, int *flag) {
1474 if (getBuiltinKeyval(keyval, attribute_val)) {
1478 if (getUserKeyval(comm, keyval, attribute_val, flag))
1480 return MPI_ERR_KEYVAL;
1483 int ampiParent::getWinAttr(MPI_Win win, int keyval, void *attribute_val, int *flag) {
1485 if (getBuiltinKeyval(keyval, attribute_val)) {
1489 MPI_Comm comm = (getAmpiParent()->getWinStruct(win))->comm;
1490 if (getUserKeyval(comm, keyval, attribute_val, flag))
1492 return MPI_ERR_KEYVAL;
1495 int ampiParent::deleteCommAttr(MPI_Comm comm, int keyval){
1496 /* no way to delete an attribute: just overwrite it with NULL */
1497 return setUserKeyval(comm, keyval, NULL);
1500 int ampiParent::deleteWinAttr(MPI_Win win, int keyval){
1501 /* no way to delete an attribute: just overwrite it with NULL */
1502 MPI_Comm comm = (getAmpiParent()->getWinStruct(win))->comm;
1503 return setUserKeyval(comm, keyval, NULL);
1507 * AMPI Message Matching (Amm) Interface
1508 * messages are matched based on 2 ints: [tag, src]
1510 struct AmmEntryStruct
1514 int tags[AMM_NTAGS];
1517 struct AmmTableStruct
1525 AmmTable result = (AmmTable)malloc(sizeof(struct AmmTableStruct));
1527 result->lasth = &(result->first);
1531 void AmmFree(AmmTable t)
1533 if (t==NULL) return;
1534 #if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
1535 if (t->first!=NULL) CmiAbort("AMPI> Cannot free a non-empty message table!");
1540 /* free all table entries but not the space pointed by "msg" */
1541 void AmmFreeAll(AmmTable t)
1544 if (t==NULL) return;
1547 AmmEntry toDel = cur;
1553 void AmmPut(AmmTable t, int* tags, void* msg)
1555 AmmEntry e = (AmmEntry)malloc(sizeof(struct AmmEntryStruct));
1558 for (int i=0; i<AMM_NTAGS; i++) e->tags[i] = tags[i];
1560 t->lasth = &(e->next);
1563 static bool AmmMatch(const int tags1[AMM_NTAGS], const int tags2[AMM_NTAGS])
1565 if (tags1[AMM_TAG]==tags2[AMM_TAG] && tags1[AMM_SRC]==tags2[AMM_SRC]) {
1566 // tag and src match
1569 else if (tags1[AMM_TAG]==tags2[AMM_TAG] && (tags1[AMM_SRC]==MPI_ANY_SOURCE || tags2[AMM_SRC]==MPI_ANY_SOURCE)) {
1570 // tag matches, src is MPI_ANY_SOURCE
1573 else if (tags1[AMM_SRC]==tags2[AMM_SRC] && (tags1[AMM_TAG]==MPI_ANY_TAG || tags2[AMM_TAG]==MPI_ANY_TAG)) {
1574 // src matches, tag is MPI_ANY_TAG
1583 void* AmmGet(AmmTable t, const int tags[AMM_NTAGS], int* rtags)
1589 /* added by Chao Mei in case that t is already freed
1590 * which happens in ~ampi() when doing out-of-core emulation for AMPI programs */
1591 if (t==NULL) return NULL;
1596 if (ent==NULL) return NULL;
1597 if (AmmMatch(tags, ent->tags)) {
1598 if (rtags) for (int i=0; i<AMM_NTAGS; i++) rtags[i] = ent->tags[i];
1600 // unlike probe, delete the matched entry:
1601 AmmEntry next = ent->next;
1603 if (next==NULL) t->lasth = enth;
1607 enth = &(ent->next);
1611 void* AmmProbe(AmmTable t, const int tags[AMM_NTAGS], int* rtags)
1617 /* added by Chao Mei in case that t is already freed
1618 * which happens in ~ampi() when doing out-of-core emulation for AMPI programs */
1619 if (t==NULL) return NULL;
1624 if (ent==NULL) return NULL;
1625 if (AmmMatch(tags, ent->tags)) {
1626 if (rtags) for (int i=0; i<AMM_NTAGS; i++) rtags[i] = ent->tags[i];
1630 enth = &(ent->next);
1635 int AmmEntries(AmmTable t)
1638 AmmEntry e = t->first;
1646 AmmTable AmmPup(pup_er p, AmmTable t, AmmPupMessageFn msgpup)
1650 if (!pup_isUnpacking(p)) {
1652 AmmEntry e = t->first;
1653 nentries = AmmEntries(t);
1654 pup_int(p, &nentries);
1656 pup_ints(p, e->tags, AMM_NTAGS);
1660 if (pup_isDeleting(p)) {
1664 if (pup_isDeleting(p)) {
1675 pup_int(p, &nentries);
1676 for (int i=0; i<nentries; i++) {
1679 tags = (int*)malloc(AMM_NTAGS*sizeof(int));
1680 pup_ints(p, tags, AMM_NTAGS);
1682 AmmPut(t, tags, msg);
1687 return NULL; // <- never executed
1690 //----------------------- ampi -------------------------
1691 void ampi::init(void) {
1697 AsyncEvacuate(false);
1702 /* this constructor only exists so we can create an empty array during split */
1703 CkAbort("Default ampi constructor should never be called");
1706 ampi::ampi(CkArrayID parent_,const ampiCommStruct &s):parentProxy(parent_)
1710 myComm=s; myComm.setArrayID(thisArrayID);
1711 myRank=myComm.getRankForIndex(thisIndex);
1716 posted_ireqs = AmmNew();
1719 ampi::ampi(CkMigrateMessage *msg):CBase_ampi(msg)
1724 void ampi::ckJustMigrated(void)
1727 ArrayElement1D::ckJustMigrated();
1730 void ampi::ckJustRestored(void)
1732 FUNCCALL_DEBUG(CkPrintf("Call just restored from ampi[%d]\n", thisIndex);)
1734 ArrayElement1D::ckJustRestored();
1737 void ampi::findParent(bool forMigration) {
1738 STARTUP_DEBUG("ampi> finding my parent")
1739 parent=parentProxy[thisIndex].ckLocal();
1740 if (parent==NULL) CkAbort("AMPI can't find its parent!");
1741 thread=parent->registerAmpi(this,myComm,forMigration);
1742 if (thread==NULL) CkAbort("AMPI can't find its thread!");
1745 //The following method should be called on the first element of the
1747 void ampi::allInitDone(){
1748 FUNCCALL_DEBUG(CkPrintf("All mpi_init have been called!\n");)
1749 thisProxy.setInitDoneFlag();
1752 void ampi::setInitDoneFlag(){
1753 parent->ampiInitCallDone=1;
1754 parent->getTCharmThread()->start();
1757 static void cmm_pup_ampi_message(pup_er p,void **msg) {
1758 CkPupMessage(*(PUP::er *)p,msg,1);
1759 if (pup_isDeleting(p)) delete (AmpiMsg *)*msg;
1762 static void cmm_pup_posted_ireq(pup_er p,void **msg) {
1763 pup_int(p, (int *)msg);
1766 void ampi::pup(PUP::er &p)
1776 if (!p.isUnpacking()) {
1778 nonnull = blockingReq->getType();
1785 if (p.isUnpacking()) {
1788 blockingReq = new PersReq;
1791 blockingReq = new IReq;
1794 blockingReq = new RednReq;
1796 case MPI_GATHER_REQ:
1797 blockingReq = new GatherReq;
1799 case MPI_GATHERV_REQ:
1800 blockingReq = new GathervReq;
1803 blockingReq = new SendReq;
1806 blockingReq = new SsendReq;
1809 blockingReq = new IATAReq;
1813 blockingReq->pup(p);
1817 if (p.isDeleting()) {
1818 delete blockingReq; blockingReq = NULL;
1821 msgs=AmmPup((pup_er)&p,msgs,cmm_pup_ampi_message);
1823 posted_ireqs = AmmPup((pup_er)&p, posted_ireqs, cmm_pup_posted_ireq);
1830 if (CkInRestarting() || _BgOutOfCoreFlag==1) {
1831 // in restarting, we need to flush messages
1832 int tags[2] = { MPI_ANY_TAG, MPI_ANY_SOURCE };
1834 AmpiMsg *msg = (AmpiMsg *) AmmGet(msgs, tags, (int*)&sts);
1837 msg = (AmpiMsg *) AmmGet(msgs, tags, (int*)&sts);
1841 delete blockingReq; blockingReq = NULL;
1843 AmmFreeAll(posted_ireqs);
1846 //------------------------ Communicator Splitting ---------------------
1847 class ampiSplitKey {
1850 int color; //New class of processes we'll belong to
1851 int key; //To determine rank in new ordering
1852 int rank; //Rank in old ordering
1854 ampiSplitKey(int nextSplitComm_,int color_,int key_,int rank_)
1855 :nextSplitComm(nextSplitComm_), color(color_), key(key_), rank(rank_) {}
1858 #define MPI_INTER 10
1860 /* "type" may indicate whether call is for a cartesian topology etc. */
1861 void ampi::split(int color,int key,MPI_Comm *dest, int type)
1863 #if CMK_BIGSIM_CHARM
1864 void *curLog; // store current log in timeline
1865 _TRACE_BG_TLINE_END(&curLog);
1867 if (type == MPI_CART) {
1868 ampiSplitKey splitKey(parent->getNextCart(),color,key,myRank);
1869 int rootIdx=myComm.getIndexForRank(0);
1870 CkCallback cb(CkIndex_ampi::splitPhase1(0),CkArrayIndex1D(rootIdx),myComm.getProxy());
1871 contribute(sizeof(splitKey),&splitKey,CkReduction::concat,cb);
1873 thread->suspend(); //Resumed by ampiParent::cartChildRegister
1874 MPI_Comm newComm=parent->getNextCart()-1;
1877 else if (type == MPI_INTER) {
1878 ampiSplitKey splitKey(parent->getNextInter(),color,key,myRank);
1879 int rootIdx=myComm.getIndexForRank(0);
1880 CkCallback cb(CkIndex_ampi::splitPhaseInter(0),CkArrayIndex1D(rootIdx),myComm.getProxy());
1881 contribute(sizeof(splitKey),&splitKey,CkReduction::concat,cb);
1883 thread->suspend(); //Resumed by ampiParent::interChildRegister
1884 MPI_Comm newComm=parent->getNextInter()-1;
1888 ampiSplitKey splitKey(parent->getNextSplit(),color,key,myRank);
1889 int rootIdx=myComm.getIndexForRank(0);
1890 CkCallback cb(CkIndex_ampi::splitPhase1(0),CkArrayIndex1D(rootIdx),myComm.getProxy());
1891 contribute(sizeof(splitKey),&splitKey,CkReduction::concat,cb);
1893 thread->suspend(); //Resumed by ampiParent::splitChildRegister
1894 MPI_Comm newComm=parent->getNextSplit()-1;
1897 #if CMK_BIGSIM_CHARM
1898 _TRACE_BG_SET_INFO(NULL, "SPLIT_RESUME", NULL, 0);
1903 int compareAmpiSplitKey(const void *a_, const void *b_) {
1904 const ampiSplitKey *a=(const ampiSplitKey *)a_;
1905 const ampiSplitKey *b=(const ampiSplitKey *)b_;
1906 if (a->color!=b->color) return a->color-b->color;
1907 if (a->key!=b->key) return a->key-b->key;
1908 return a->rank-b->rank;
1911 CProxy_ampi ampi::createNewChildAmpiSync() {
1912 CkArrayOptions opts;
1913 opts.bindTo(parentProxy);
1914 opts.setSectionAutoDelegate(false);
1915 opts.setNumInitial(0);
1916 CkArrayID unusedAID;
1917 ampiCommStruct unusedComm;
1918 CkCallback cb(CkCallback::resumeThread);
1919 CProxy_ampi::ckNew(unusedAID, unusedComm, opts, cb);
1920 CkArrayCreatedMsg *newAmpiMsg = static_cast<CkArrayCreatedMsg*>(cb.thread_delay());
1921 CProxy_ampi newAmpi = newAmpiMsg->aid;
1923 newAmpi.doneInserting(); //<- Meaning, I need to do my own creation race resolution
1927 void ampi::splitPhase1(CkReductionMsg *msg)
1929 //Order the keys, which orders the ranks properly:
1930 int nKeys=msg->getSize()/sizeof(ampiSplitKey);
1931 ampiSplitKey *keys=(ampiSplitKey *)msg->getData();
1932 if (nKeys!=myComm.getSize()) CkAbort("ampi::splitReduce expected a split contribution from every rank!");
1933 qsort(keys,nKeys,sizeof(ampiSplitKey),compareAmpiSplitKey);
1935 MPI_Comm newComm = -1;
1936 for(int i=0;i<nKeys;i++){
1937 if(keys[i].nextSplitComm>newComm)
1938 newComm = keys[i].nextSplitComm;
1941 //Loop over the sorted keys, which gives us the new arrays:
1942 int lastColor=keys[0].color-1; //The color we're building an array for
1943 CProxy_ampi lastAmpi; //The array for lastColor
1944 int lastRoot=0; //C value for new rank 0 process for latest color
1945 ampiCommStruct lastComm; //Communicator info. for latest color
1946 for (int c=0;c<nKeys;c++) {
1947 if (keys[c].color!=lastColor)
1948 { //Hit a new color-- need to build a new communicator and array
1949 lastColor=keys[c].color;
1952 lastAmpi = createNewChildAmpiSync();
1954 vector<int> indices; //Maps rank to array indices for new array
1955 for (int i=c;i<nKeys;i++) {
1956 if (keys[i].color!=lastColor) break; //Done with this color
1957 int idx=myComm.getIndexForRank(keys[i].rank);
1958 indices.push_back(idx);
1961 //FIXME: create a new communicator for each color, instead of
1962 // (confusingly) re-using the same MPI_Comm number for each.
1963 lastComm=ampiCommStruct(newComm,lastAmpi,indices.size(),indices);
1965 int newRank=c-lastRoot;
1966 int newIdx=lastComm.getIndexForRank(newRank);
1968 lastAmpi[newIdx].insert(parentProxy,lastComm);
1974 void ampi::splitPhaseInter(CkReductionMsg *msg)
1976 //Order the keys, which orders the ranks properly:
1977 int nKeys=msg->getSize()/sizeof(ampiSplitKey);
1978 ampiSplitKey *keys=(ampiSplitKey *)msg->getData();
1979 if (nKeys!=myComm.getSize()) CkAbort("ampi::splitReduce expected a split contribution from every rank!");
1980 qsort(keys,nKeys,sizeof(ampiSplitKey),compareAmpiSplitKey);
1982 MPI_Comm newComm = -1;
1983 for(int i=0;i<nKeys;i++){
1984 if(keys[i].nextSplitComm>newComm)
1985 newComm = keys[i].nextSplitComm; // FIXME: use nextSplitr instead of nextInter?
1988 //Loop over the sorted keys, which gives us the new arrays:
1989 int lastColor=keys[0].color-1; //The color we're building an array for
1990 CProxy_ampi lastAmpi; //The array for lastColor
1991 int lastRoot=0; //C value for new rank 0 process for latest color
1992 ampiCommStruct lastComm; //Communicator info. for latest color
1994 lastAmpi = createNewChildAmpiSync();
1996 for (int c=0;c<nKeys;c++) {
1997 vector<int> indices; // Maps rank to array indices for new array
1998 if (keys[c].color!=lastColor)
1999 { //Hit a new color-- need to build a new communicator and array
2000 lastColor=keys[c].color;
2003 for (int i=c;i<nKeys;i++) {
2004 if (keys[i].color!=lastColor) break; //Done with this color
2005 int idx=myComm.getIndexForRank(keys[i].rank);
2006 indices.push_back(idx);
2010 lastComm=ampiCommStruct(newComm,lastAmpi,indices.size(),indices, myComm.getRemoteIndices());
2011 for (int i=0; i<indices.size(); i++) {
2012 lastAmpi[indices[i]].insert(parentProxy,lastComm);
2018 parentProxy[0].ExchangeProxy(lastAmpi);
2022 //...newly created array elements register with the parent, which calls:
2023 void ampiParent::splitChildRegister(const ampiCommStruct &s) {
2024 int idx=s.getComm()-MPI_COMM_FIRST_SPLIT;
2025 if (splitComm.size()<=idx) splitComm.resize(idx+1);
2026 splitComm[idx]=new ampiCommStruct(s);
2027 thread->resume(); //Matches suspend at end of ampi::split
2030 //-----------------create communicator from group--------------
2031 // The procedure is like that of comm_split very much,
2032 // so the code is shamelessly copied from above
2033 // 1. reduction to make sure all members have called
2034 // 2. the root in the old communicator create the new array
2035 // 3. ampiParent::register is called to register new array as new comm
2040 vecStruct():nextgroup(-1){}
2041 vecStruct(int nextgroup_, groupStruct vec_)
2042 : nextgroup(nextgroup_), vec(vec_) { }
2045 void ampi::commCreate(const groupStruct vec,MPI_Comm* newcomm){
2048 CkCallback cb(CkReductionTarget(ampi,commCreatePhase1),CkArrayIndex1D(rootIdx),myComm.getProxy());
2049 MPI_Comm nextgroup = parent->getNextGroup();
2050 contribute(sizeof(nextgroup), &nextgroup,CkReduction::max_int,cb);
2052 if(getPosOp(thisIndex,vec)>=0){
2053 thread->suspend(); //Resumed by ampiParent::groupChildRegister
2054 MPI_Comm retcomm = parent->getNextGroup()-1;
2057 *newcomm = MPI_COMM_NULL;
2061 void ampi::insertNewChildAmpiElements(MPI_Comm nextComm, CProxy_ampi newAmpi) {
2062 ampiCommStruct newCommStruct = ampiCommStruct(nextComm, newAmpi, tmpVec.size(), tmpVec);
2063 for (int i = 0; i < tmpVec.size(); ++i)
2064 newAmpi[tmpVec[i]].insert(parentProxy, newCommStruct);
2067 void ampi::commCreatePhase1(MPI_Comm nextGroupComm){
2068 CProxy_ampi newAmpi = createNewChildAmpiSync();
2069 insertNewChildAmpiElements(nextGroupComm, newAmpi);
2072 void ampiParent::groupChildRegister(const ampiCommStruct &s) {
2073 int idx=s.getComm()-MPI_COMM_FIRST_GROUP;
2074 if (groupComm.size()<=idx) groupComm.resize(idx+1);
2075 groupComm[idx]=new ampiCommStruct(s);
2076 thread->resume(); //Matches suspend at end of ampi::split
2079 /* Virtual topology communicator creation */
2080 void ampi::cartCreate(const groupStruct vec,MPI_Comm* newcomm){
2083 CkCallback cb(CkReductionTarget(ampi,commCreatePhase1),CkArrayIndex1D(rootIdx),myComm.getProxy());
2085 MPI_Comm nextcart = parent->getNextCart();
2086 contribute(sizeof(nextcart), &nextcart,CkReduction::max_int,cb);
2088 if(getPosOp(thisIndex,vec)>=0){
2089 thread->suspend(); //Resumed by ampiParent::cartChildRegister
2090 MPI_Comm retcomm = parent->getNextCart()-1;
2093 *newcomm = MPI_COMM_NULL;
2096 void ampiParent::cartChildRegister(const ampiCommStruct &s) {
2097 int idx=s.getComm()-MPI_COMM_FIRST_CART;
2098 if (cartComm.size()<=idx) {
2099 cartComm.resize(idx+1);
2100 cartComm.length()=idx+1;
2102 cartComm[idx]=new ampiCommStruct(s);
2103 thread->resume(); //Matches suspend at end of ampi::cartCreate
2106 void ampi::graphCreate(const groupStruct vec,MPI_Comm* newcomm){
2109 CkCallback cb(CkReductionTarget(ampi,commCreatePhase1),CkArrayIndex1D(rootIdx),
2111 MPI_Comm nextgraph = parent->getNextGraph();
2112 contribute(sizeof(nextgraph), &nextgraph,CkReduction::max_int,cb);
2114 if(getPosOp(thisIndex,vec)>=0){
2115 thread->suspend(); //Resumed by ampiParent::graphChildRegister
2116 MPI_Comm retcomm = parent->getNextGraph()-1;
2119 *newcomm = MPI_COMM_NULL;
2122 void ampiParent::graphChildRegister(const ampiCommStruct &s) {
2123 int idx=s.getComm()-MPI_COMM_FIRST_GRAPH;
2124 if (graphComm.size()<=idx) {
2125 graphComm.resize(idx+1);
2126 graphComm.length()=idx+1;
2128 graphComm[idx]=new ampiCommStruct(s);
2129 thread->resume(); //Matches suspend at end of ampi::graphCreate
2132 void ampi::intercommCreate(const groupStruct remoteVec, const int root, MPI_Comm tcomm, MPI_Comm *ncomm){
2134 if (tcomm == MPI_COMM_SELF) {
2136 intercommCreatePhaseSelf(parent->getNextInter());
2139 if(thisIndex==root) { // not everybody gets the valid rvec
2142 CkCallback cb(CkReductionTarget(ampi, intercommCreatePhase1),CkArrayIndex1D(root),myComm.getProxy());
2143 MPI_Comm nextinter = parent->getNextInter();
2144 contribute(sizeof(nextinter), &nextinter,CkReduction::max_int,cb);
2146 thread->suspend(); //Not resumed by ampiParent::interChildRegister. Resumed by ExchangeProxy.
2147 *ncomm = parent->getNextInter()-1;
2150 void ampi::intercommCreatePhase1(MPI_Comm nextInterComm){
2152 CProxy_ampi newAmpi = createNewChildAmpiSync();
2153 groupStruct lgroup = myComm.getIndices();
2154 ampiCommStruct newCommstruct = ampiCommStruct(nextInterComm,newAmpi,lgroup.size(),lgroup,tmpVec);
2155 for(int i=0;i<lgroup.size();i++){
2156 int newIdx=lgroup[i];
2157 newAmpi[newIdx].insert(parentProxy,newCommstruct);
2160 parentProxy[0].ExchangeProxy(newAmpi);
2163 void ampi::intercommCreatePhaseSelf(MPI_Comm nextInterComm) {
2164 CProxy_ampi newAmpi = createNewChildAmpiSync();
2165 std::vector<int> vec(1,0);
2166 groupStruct lgroup = vec;
2167 ampiCommStruct newCommstruct = ampiCommStruct(nextInterComm,newAmpi,lgroup.size(),lgroup,tmpVec);
2168 for(int i=0;i<lgroup.size();i++){
2169 int newIdx=lgroup[i];
2170 newAmpi[newIdx].insert(parentProxy,newCommstruct);
2173 parentProxy[0].ExchangeProxy(newAmpi);
2176 void ampiParent::interChildRegister(const ampiCommStruct &s) {
2177 int idx=s.getComm()-MPI_COMM_FIRST_INTER;
2178 if (interComm.size()<=idx) interComm.resize(idx+1);
2179 interComm[idx]=new ampiCommStruct(s);
2180 // don't resume the thread yet, till parent set remote proxy
2183 void ampi::intercommMerge(int first, MPI_Comm *ncomm){ // first valid only at local root
2184 if(myRank == 0 && first == 1){ // first (lower) group creates the intracommunicator for the higher group
2185 groupStruct lvec = myComm.getIndices();
2186 groupStruct rvec = myComm.getRemoteIndices();
2187 int rsize = rvec.size();
2189 for(int i=0;i<rsize;i++)
2190 tmpVec.push_back(rvec[i]);
2191 if(tmpVec.size()==0) CkAbort("Error in ampi::intercommMerge: merging empty comms!\n");
2196 int rootIdx=myComm.getIndexForRank(0);
2197 CkCallback cb(CkReductionTarget(ampi, intercommMergePhase1),CkArrayIndex1D(rootIdx),myComm.getProxy());
2198 MPI_Comm nextintra = parent->getNextIntra();
2199 contribute(sizeof(nextintra), &nextintra,CkReduction::max_int,cb);
2201 thread->suspend(); //Resumed by ampiParent::interChildRegister
2202 MPI_Comm newcomm=parent->getNextIntra()-1;
2206 void ampi::intercommMergePhase1(MPI_Comm nextIntraComm){
2207 // gets called on two roots, first root creates the comm
2208 if(tmpVec.size()==0) return;
2209 CProxy_ampi newAmpi = createNewChildAmpiSync();
2210 insertNewChildAmpiElements(nextIntraComm, newAmpi);
2213 void ampiParent::intraChildRegister(const ampiCommStruct &s) {
2214 int idx=s.getComm()-MPI_COMM_FIRST_INTRA;
2215 if (intraComm.size()<=idx) intraComm.resize(idx+1);
2216 intraComm[idx]=new ampiCommStruct(s);
2217 thread->resume(); //Matches suspend at end of ampi::split
2220 //------------------------ communication -----------------------
2221 const ampiCommStruct &universeComm2CommStruct(MPI_Comm universeNo)
2223 if (universeNo>MPI_COMM_WORLD) {
2224 int worldDex=universeNo-MPI_COMM_WORLD-1;
2225 if (worldDex>=_mpi_nworlds)
2226 CkAbort("Bad world communicator passed to universeComm2CommStruct");
2227 return mpi_worlds[worldDex];
2229 CkAbort("Bad communicator passed to universeComm2CommStruct");
2230 return mpi_worlds[0]; // meaningless return
2233 void ampiParent::block(void){
2237 void ampiParent::yield(void){
2241 void ampi::unblock(void){
2245 void ampiParent::blockOnRecv(void){
2246 resumeOnRecv = true;
2248 resumeOnRecv = false;
2251 ampi* ampi::blockOnRecv(void){
2252 parent->resumeOnRecv = true;
2253 // In case this thread is migrated while suspended,
2254 // save myComm to get the ampi instance back. Then
2255 // return "dis" in case the caller needs it.
2256 MPI_Comm comm = myComm.getComm();
2258 ampi *dis = getAmpiInstance(comm);
2259 dis->parent->resumeOnRecv = false;
2263 ampi* ampi::blockOnColl(void){
2264 parent->resumeOnColl = true;
2265 MPI_Comm comm = myComm.getComm();
2267 ampi *dis = getAmpiInstance(comm);
2268 dis->parent->resumeOnColl = false;
2272 // block on (All)Reduce or (All)Gather(v)
2273 ampi* ampi::blockOnRedn(AmpiRequest *req){
2277 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
2278 _LOG_E_END_AMPI_PROCESSING(thisIndex)
2280 #if CMK_BIGSIM_CHARM
2281 void *curLog; // store current log in timeline
2282 _TRACE_BG_TLINE_END(&curLog);
2283 #if CMK_TRACE_IN_CHARM
2284 if(CpvAccess(traceOn)) traceSuspend();
2288 ampi* dis = blockOnColl();
2290 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2291 CpvAccess(_currentObj) = dis;
2293 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
2294 _LOG_E_BEGIN_AMPI_PROCESSING(thisIndex, dis->blockingReq->src, dis->blockingReq->count)
2296 #if CMK_BIGSIM_CHARM
2297 #if CMK_TRACE_IN_CHARM
2298 if(CpvAccess(traceOn)) CthTraceResume(dis->thread->getThread());
2300 TRACE_BG_AMPI_BREAK(dis->thread->getThread(), "RECV_RESUME", NULL, 0, 0);
2301 if (dis->blockingReq->eventPe == CkMyPe()) _TRACE_BG_ADD_BACKWARD_DEP(dis->blockingReq->event);
2304 delete dis->blockingReq; dis->blockingReq = NULL;
2308 void ampi::ssend_ack(int sreq_idx){
2310 thread->resume(); // MPI_Ssend
2312 sreq_idx -= 2; // start from 2
2313 AmpiRequestList *reqs = &(parent->ampiReqs);
2314 SsendReq *sreq = (SsendReq *)(*reqs)[sreq_idx];
2315 sreq->statusIreq = true;
2316 if (parent->resumeOnRecv) {
2322 void ampi::generic(AmpiMsg* msg)
2325 CkPrintf("AMPI vp %d arrival: tag=%d, src=%d, comm=%d (seq %d) resumeOnRecv %d\n",
2326 thisIndex, msg->getTag(), msg->getSrcRank(), msg->getComm(this->getComm()), msg->getSeq(), parent->resumeOnRecv);
2328 #if CMK_BIGSIM_CHARM
2329 TRACE_BG_ADD_TAG("AMPI_generic");
2333 if(msg->getSeq() != -1) {
2334 // If message was sent over MPI_COMM_SELF, srcRank needs to be this rank in MPI_COMM_WORLD:
2335 int srcRank = (msg->getComm(this->getComm()) == MPI_COMM_SELF) ? this->getRank(MPI_COMM_WORLD) : msg->getSrcRank();
2336 int n=oorder.put(srcRank,msg);
2337 if (n>0) { // This message was in-order
2339 if (n>1) { // It enables other, previously out-of-order messages
2340 while((msg=oorder.getOutOfOrder(srcRank))!=0) {
2345 } else { //Cross-world or system messages are unordered
2348 // msg may be free'ed from calling inorder()
2350 if(parent->resumeOnRecv && parent->numBlockedReqs==0){
2355 inline static AmpiRequestList *getReqs(void);
2357 void ampi::inorder(AmpiMsg* msg)
2360 CkPrintf("AMPI vp %d inorder: tag=%d, src=%d, comm=%d (seq %d)\n",
2361 thisIndex, msg->getTag(), msg->getSrcRank(), msg->getComm(this->getComm()), msg->getSeq());
2364 // check posted recvs
2365 int tags[2] = { msg->getTag(), msg->getSrcRank() };
2368 #if CMK_BIGSIM_CHARM
2369 _TRACE_BG_TLINE_END(&msg->event); // store current log
2370 msg->eventPe = CkMyPe();
2373 //in case ampi has not initialized and posted_ireqs are only inserted
2374 //at AMPI_Irecv (MPI_Irecv)
2375 AmpiRequestList *reqL = &(parent->ampiReqs);
2376 //When storing the req index, it's 1-based. The reason is stated in the comments
2377 //in the ampi::irecv function.
2378 int ireqIdx = (int)((long)AmmGet(posted_ireqs, tags, (int*)&sts));
2380 if(reqL->size()>0 && ireqIdx>0)
2381 ireq = (IReq *)(*reqL)[ireqIdx-1];
2382 if (ireq) { // receive posted
2383 if (ireq->isBlocked()) {
2384 parent->numBlockedReqs--;
2386 ireq->receive(this, msg);
2388 AmmPut(msgs, tags, msg);
2392 AmpiMsg *ampi::getMessage(int t, int s, MPI_Comm comm, int *sts) const
2394 int tags[2] = { t, s };
2395 AmpiMsg *msg = (AmpiMsg *) AmmGet(msgs, tags, sts);
2399 void handle_MPI_BOTTOM(void* &buf, MPI_Datatype type)
2401 if (buf == MPI_BOTTOM) {
2402 buf = (void*)getDDT()->getType(type)->getLB();
2403 getDDT()->getType(type)->setAbsolute(true);
2407 void handle_MPI_BOTTOM(void* &buf1, MPI_Datatype type1, void* &buf2, MPI_Datatype type2)
2409 if (buf1 == MPI_BOTTOM) {
2410 buf1 = (void*)getDDT()->getType(type1)->getLB();
2411 getDDT()->getType(type1)->setAbsolute(true);
2413 if (buf2 == MPI_BOTTOM) {
2414 buf2 = (void*)getDDT()->getType(type2)->getLB();
2415 getDDT()->getType(type2)->setAbsolute(true);
2419 AmpiMsg *ampi::makeAmpiMsg(int destIdx,int t,int sRank,const void *buf,int count,
2420 MPI_Datatype type,MPI_Comm destcomm, int sync)
2422 CkDDT_DataType *ddt = getDDT()->getType(type);
2423 int len = ddt->getSize(count);
2426 if (destIdx>=0 && destcomm<=MPI_COMM_WORLD && t<=MPI_ATA_SEQ_TAG) //Not cross-module: set seqno
2427 seq = oorder.nextOutgoing(destIdx);
2428 AmpiMsg *msg = new (len, 0) AmpiMsg(seq, t, sRank, len, destcomm);
2429 if (sync) UsrToEnv(msg)->setRef(sync);
2430 ddt->serialize((char*)buf, msg->getData(), count, 1);
2434 static inline void freeNonPersReq(int &request) {
2435 AmpiRequestList* reqs = getReqs();
2436 if ((*reqs)[request]->getType() != MPI_PERS_REQ) { // only free non-blocking request
2437 reqs->free(request);
2438 request = MPI_REQUEST_NULL;
2442 void ampi::send(int t, int sRank, const void* buf, int count, MPI_Datatype type,
2443 int rank, MPI_Comm destcomm, int sync)
2445 #if CMK_TRACE_IN_CHARM
2446 TRACE_BG_AMPI_BREAK(thread->getThread(), "AMPI_SEND", NULL, 0, 1);
2449 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2450 MPI_Comm disComm = myComm.getComm();
2451 ampi *dis = getAmpiInstance(disComm);
2452 CpvAccess(_currentObj) = dis;
2455 const ampiCommStruct &dest=comm2CommStruct(destcomm);
2456 delesend(t,sRank,buf,count,type,rank,destcomm,dest.getProxy(),sync);
2458 #if CMK_TRACE_IN_CHARM
2459 TRACE_BG_AMPI_BREAK(thread->getThread(), "AMPI_SEND_END", NULL, 0, 1);
2463 // waiting for receiver side
2464 parent->resumeOnRecv = false; // so no one else awakes it
2469 void ampi::sendraw(int t, int sRank, void* buf, int len, CkArrayID aid, int idx)
2471 AmpiMsg *msg = new (len, 0) AmpiMsg(-1, t, sRank, len);
2472 memcpy(msg->getData(), buf, len);
2473 CProxy_ampi pa(aid);
2474 pa[idx].generic(msg);
2477 void ampi::delesend(int t, int sRank, const void* buf, int count, MPI_Datatype type, int rank,
2478 MPI_Comm destcomm, CProxy_ampi arrproxy, int sync)
2480 if(rank==MPI_PROC_NULL) return;
2481 const ampiCommStruct &dest=comm2CommStruct(destcomm);
2482 int destIdx = dest.getIndexForRank(rank);
2485 destIdx = dest.getIndexForRemoteRank(rank);
2486 arrproxy = remoteProxy;
2489 CkPrintf("AMPI vp %d send: tag=%d, src=%d, comm=%d (to %d)\n",thisIndex,t,sRank,destcomm,destIdx);
2492 arrproxy[destIdx].generic(makeAmpiMsg(destIdx,t,sRank,buf,count,type,destcomm,sync));
2494 void ampi::processAmpiMsg(AmpiMsg *msg, void* buf, MPI_Datatype type, int count)
2496 int ssendReq = UsrToEnv(msg)->getRef();
2497 if (ssendReq > 0) { // send an ack to sender
2498 int srcRank = (msg->getComm(this->getComm()) == MPI_COMM_SELF) ? this->getRank(MPI_COMM_WORLD) : msg->getSrcRank();
2499 int srcIdx = getIndexForRank(srcRank);
2500 thisProxy[srcIdx].ssend_ack(ssendReq);
2503 CkDDT_DataType *ddt = getDDT()->getType(type);
2504 int len = ddt->getSize(count);
2506 if(msg->getLength() < len){ // only at rare case shall we reset count by using divide
2507 count = msg->getLength()/(ddt->getSize(1));
2510 ddt->serialize((char*)buf, msg->getData(), count, (-1));
2513 void ampi::processRednMsg(CkReductionMsg *msg, void* buf, MPI_Datatype type, int count)
2515 // The first sizeof(AmpiOpHeader) bytes in the redn msg data are reserved
2516 // for an AmpiOpHeader if our custom AmpiReducer type was used.
2517 int szhdr = (msg->getReducer() == AmpiReducer) ? sizeof(AmpiOpHeader) : 0;
2518 getDDT()->getType(type)->serialize((char*)buf, (char*)msg->getData()+szhdr, count, (-1));
2521 void ampi::processNoncommutativeRednMsg(CkReductionMsg *msg, void* buf, MPI_Datatype type, int count, MPI_User_function* func)
2523 CkReduction::tupleElement* results = NULL;
2524 int numReductions = 0;
2525 msg->toTuple(&results, &numReductions);
2527 // Contributions are unordered and consist of a (srcRank, data) tuple
2528 CkReduction::setElement *currentSrc = (CkReduction::setElement*)results[0].data;
2529 CkReduction::setElement *currentData = (CkReduction::setElement*)results[1].data;
2530 CkDDT_DataType *ddt = getDDT()->getType(type);
2531 int contributionSize = ddt->getSize(count);
2532 int commSize = getSize(getComm());
2534 // Store pointers to each contribution's data at index 'srcRank' in contributionData
2535 vector<void *> contributionData(commSize);
2536 for (int i=0; i<commSize; i++) {
2537 CkAssert(currentSrc && currentData);
2538 int srcRank = *((int*)currentSrc->data);
2539 CkAssert(currentData->dataSize == contributionSize);
2540 contributionData[srcRank] = currentData->data;
2541 currentSrc = currentSrc->next();
2542 currentData = currentData->next();
2545 // Copy rank 0's contribution into buf first
2546 memcpy(buf, contributionData[0], contributionSize);
2548 // Invoke the MPI_User_function on the contributions in 'rank' order
2549 for (int i=1; i<commSize; i++) {
2550 (*func)(contributionData[i], buf, &count, &type);
2554 void ampi::processGatherMsg(CkReductionMsg *msg, void* buf, MPI_Datatype type, int recvCount)
2556 CkReduction::tupleElement* results = NULL;
2557 int numReductions = 0;
2558 msg->toTuple(&results, &numReductions);
2560 // Re-order the gather data based on the rank of the contributor
2561 CkReduction::setElement *currentSrc = (CkReduction::setElement*)results[0].data;
2562 CkReduction::setElement *currentData = (CkReduction::setElement*)results[1].data;
2563 CkDDT_DataType *ddt = getDDT()->getType(type);
2564 int contributionSize = ddt->getSize(recvCount);
2565 int contributionExtent = ddt->getExtent()*recvCount;
2567 for (int i=0; i<getSize(getComm()); i++) {
2568 CkAssert(currentSrc && currentData);
2569 int srcRank = *((int*)currentSrc->data);
2570 CkAssert(currentData->dataSize == contributionSize);
2571 ddt->serialize(&(((char*)buf)[srcRank*contributionExtent]), currentData->data, recvCount, (-1));
2572 currentSrc = currentSrc->next();
2573 currentData = currentData->next();
2577 void ampi::processGathervMsg(CkReductionMsg *msg, void* buf, MPI_Datatype type,
2578 int* recvCounts, int* displs)
2580 CkReduction::tupleElement* results = NULL;
2581 int numReductions = 0;
2582 msg->toTuple(&results, &numReductions);
2584 // Re-order the gather data based on the rank of the contributor
2585 CkReduction::setElement *currentSrc = (CkReduction::setElement*)results[0].data;
2586 CkReduction::setElement *currentData = (CkReduction::setElement*)results[1].data;
2587 CkDDT_DataType *ddt = getDDT()->getType(type);
2588 int contributionSize = ddt->getSize();
2589 int contributionExtent = ddt->getExtent();
2591 for (int i=0; i<getSize(getComm()); i++) {
2592 CkAssert(currentSrc && currentData);
2593 int srcRank = *((int*)currentSrc->data);
2594 CkAssert(currentData->dataSize == contributionSize*recvCounts[srcRank]);
2595 ddt->serialize(&((char*)buf)[displs[srcRank]*contributionExtent], currentData->data, recvCounts[srcRank], (-1));
2596 currentSrc = currentSrc->next();
2597 currentData = currentData->next();
2601 int ampi::recv(int t, int s, void* buf, int count, MPI_Datatype type, MPI_Comm comm, MPI_Status *sts)
2603 MPI_Comm disComm = myComm.getComm();
2604 if(s==MPI_PROC_NULL) {
2605 sts->MPI_SOURCE = MPI_PROC_NULL;
2606 sts->MPI_TAG = MPI_ANY_TAG;
2607 sts->MPI_COMM = comm;
2608 sts->MPI_LENGTH = 0;
2609 sts->MPI_CANCEL = 0;
2612 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
2613 _LOG_E_END_AMPI_PROCESSING(thisIndex)
2615 #if CMK_BIGSIM_CHARM
2616 void *curLog; // store current log in timeline
2617 _TRACE_BG_TLINE_END(&curLog);
2618 #if CMK_TRACE_IN_CHARM
2619 if(CpvAccess(traceOn)) traceSuspend();
2624 s = myComm.getIndexForRemoteRank(s);
2628 CkPrintf("AMPI vp %d blocking recv: tag=%d, src=%d, comm=%d\n",thisIndex,t,s,comm);
2631 ampi *dis = getAmpiInstance(disComm);
2632 int tags[2] = { t, s };
2633 AmpiMsg *msg = NULL;
2634 msg = (AmpiMsg *)AmmGet(msgs, tags, (int*)sts);
2635 if (msg) { // the matching message has already arrived
2637 sts->MPI_SOURCE = msg->getSrcRank();
2638 sts->MPI_TAG = msg->getTag();
2639 sts->MPI_COMM = msg->getComm(comm);
2640 sts->MPI_LENGTH = msg->getLength();
2641 sts->MPI_CANCEL = 0;
2643 processAmpiMsg(msg, buf, type, count);
2644 #if CMK_BIGSIM_CHARM
2645 TRACE_BG_AMPI_BREAK(thread->getThread(), "RECV_RESUME", NULL, 0, 0);
2646 if (msg->eventPe == CkMyPe()) _TRACE_BG_ADD_BACKWARD_DEP(msg->event);
2650 else { // post a request and block until the matching message arrives
2651 int request = postReq(new IReq(buf, count, type, s, t, comm, AMPI_REQ_BLOCKED));
2652 CkAssert(parent->numBlockedReqs == 0);
2653 parent->numBlockedReqs = 1;
2654 dis = dis->blockOnRecv(); // "dis" is updated in case an ampi thread is migrated while waiting for a message
2656 AmpiRequestList* reqs = getReqs();
2657 AmpiRequest& req = *(*reqs)[request];
2658 sts->MPI_SOURCE = req.src;
2659 sts->MPI_TAG = req.tag;
2660 sts->MPI_COMM = req.comm;
2661 sts->MPI_LENGTH = req.count * getDDT()->getSize(type);
2662 sts->MPI_CANCEL = 0;
2664 freeNonPersReq(request);
2667 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2668 CpvAccess(_currentObj) = dis;
2669 MSG_ORDER_DEBUG( printf("[%d] AMPI thread rescheduled to Index %d buf %p src %d\n",CkMyPe(),dis->thisIndex,buf,s); )
2671 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
2672 _LOG_E_BEGIN_AMPI_PROCESSING(thisIndex,s,count)
2674 #if CMK_BIGSIM_CHARM && CMK_TRACE_IN_CHARM
2675 //Due to the reason mentioned the in the else-statement above, we need to
2676 //use "dis" as "this" in the case of migration (or out-of-core execution in BigSim)
2677 if(CpvAccess(traceOn)) CthTraceResume(dis->thread->getThread());
2683 void ampi::probe(int t, int s, MPI_Comm comm, MPI_Status *sts)
2686 #if CMK_BIGSIM_CHARM
2687 void *curLog; // store current log in timeline
2688 _TRACE_BG_TLINE_END(&curLog);
2691 ampi *dis = getAmpiInstance(comm);
2694 tags[0] = t; tags[1] = s;
2695 msg = (AmpiMsg *) AmmProbe(dis->msgs, tags, (int*)sts);
2697 // "dis" is updated in case an ampi thread is migrated while waiting for a message
2698 dis = dis->blockOnRecv();
2702 sts->MPI_SOURCE = msg->getSrcRank();
2703 sts->MPI_TAG = msg->getTag();
2704 sts->MPI_COMM = msg->getComm(comm);
2705 sts->MPI_LENGTH = msg->getLength();
2706 sts->MPI_CANCEL = 0;
2709 #if CMK_BIGSIM_CHARM
2710 _TRACE_BG_SET_INFO((char *)msg, "PROBE_RESUME", &curLog, 1);
2714 int ampi::iprobe(int t, int s, MPI_Comm comm, MPI_Status *sts)
2718 tags[0] = t; tags[1] = s;
2719 msg = (AmpiMsg *) AmmProbe(msgs, tags, (int*)sts);
2722 sts->MPI_SOURCE = msg->getSrcRank();
2723 sts->MPI_TAG = msg->getTag();
2724 sts->MPI_COMM = msg->getComm(comm);
2725 sts->MPI_LENGTH = msg->getLength();
2726 sts->MPI_CANCEL = 0;
2730 #if CMK_BIGSIM_CHARM
2731 void *curLog; // store current log in timeline
2732 _TRACE_BG_TLINE_END(&curLog);
2735 #if CMK_BIGSIM_CHARM
2736 _TRACE_BG_SET_INFO(NULL, "IPROBE_RESUME", &curLog, 1);
2741 void ampi::bcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm destcomm)
2743 if (root==getRank(destcomm)) {
2744 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2745 CpvAccess(_currentObj) = this;
2747 thisProxy.generic(makeAmpiMsg(-1, MPI_BCAST_TAG, root, buf, count, type, destcomm));
2750 if (-1==recv(MPI_BCAST_TAG, root, buf, count, type, destcomm)) CkAbort("AMPI> Error in broadcast");
2753 void ampi::ibcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm destcomm, MPI_Request* request)
2755 if (root==getRank(destcomm)) {
2756 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2757 CpvAccess(_currentObj) = this;
2759 thisProxy.generic(makeAmpiMsg(-1, MPI_BCAST_TAG, root, buf, count, type, destcomm));
2762 // call irecv to post an IReq and check for any pending messages
2763 irecv(buf, count, type, root, MPI_BCAST_TAG, destcomm, request);
2766 void ampi::bcastraw(void* buf, int len, CkArrayID aid)
2768 AmpiMsg *msg = new (len, 0) AmpiMsg(-1, MPI_BCAST_TAG, 0, len);
2769 memcpy(msg->getData(), buf, len);
2770 CProxy_ampi pa(aid);
2774 AmpiMsg* ampi::Alltoall_RemoteIget(MPI_Aint disp, int cnt, MPI_Datatype type, int tag)
2776 CkAssert(tag==MPI_ATA_TAG && AlltoallGetFlag);
2778 CkDDT_DataType *ddt = getDDT()->getType(type);
2779 unit = ddt->getSize(1);
2780 int totalsize = unit*cnt;
2782 AmpiMsg *msg = new (totalsize, 0) AmpiMsg(-1, MPI_ATA_TAG, thisIndex,totalsize);
2783 char* addr = (char*)Alltoallbuff+disp*unit;
2784 ddt->serialize(msg->getData(), addr, cnt, (-1));
2788 int MPI_comm_null_copy_fn(MPI_Comm comm, int keyval, void *extra_state,
2789 void *attr_in, void *attr_out, int *flag){
2791 return (MPI_SUCCESS);
2794 int MPI_comm_dup_fn(MPI_Comm comm, int keyval, void *extra_state,
2795 void *attr_in, void *attr_out, int *flag){
2796 (*(void **)attr_out) = attr_in;
2798 return (MPI_SUCCESS);
2801 int MPI_comm_null_delete_fn(MPI_Comm comm, int keyval, void *attr, void *extra_state){
2802 return (MPI_SUCCESS);
2805 int MPI_type_null_copy_fn(MPI_Datatype type, int keyval, void *extra_state,
2806 void *attr_in, void *attr_out, int *flag){
2808 return (MPI_SUCCESS);
2811 int MPI_type_dup_fn(MPI_Datatype type, int keyval, void *extra_state,
2812 void *attr_in, void *attr_out, int *flag){
2813 (*(void **)attr_out) = attr_in;
2815 return (MPI_SUCCESS);
2818 int MPI_type_null_delete_fn(MPI_Datatype type, int keyval, void *attr, void *extra_state){
2819 return (MPI_SUCCESS);
2822 AmpiSeqQ::~AmpiSeqQ () {
2825 void AmpiSeqQ::pup(PUP::er &p) {
2830 void AmpiSeqQ::putOutOfOrder(int srcRank, AmpiMsg *msg)
2832 AmpiOtherElement &el=elements[srcRank];
2833 #if CMK_ERROR_CHECKING
2834 if (msg->getSeq() < el.seqIncoming)
2835 CkAbort("AMPI Logic error: received late out-of-order message!\n");
2838 el.nOut++; // We have another message in the out-of-order queue
2841 AmpiMsg *AmpiSeqQ::getOutOfOrder(int srcRank)
2843 AmpiOtherElement &el=elements[srcRank];
2844 if (el.nOut==0) return 0; // No more out-of-order left.
2845 // Walk through our out-of-order queue, searching for our next message:
2846 for (int i=0;i<out.length();i++) {
2847 AmpiMsg *msg=out.deq();
2848 if (msg->getSrcRank()==srcRank && msg->getSeq()==el.seqIncoming) {
2850 el.nOut--; // We have one less message out-of-order
2856 // We walked the whole queue-- ours is not there.
2860 void AmpiRequest::print(){
2861 CkPrintf("In AmpiRequest: buf=%p, count=%d, type=%d, src=%d, tag=%d, comm=%d, isvalid=%d\n", buf, count, type, src, tag, comm, isvalid);
2864 void PersReq::print(){
2865 AmpiRequest::print();
2866 CkPrintf("In PersReq: sndrcv=%d\n", sndrcv);
2870 AmpiRequest::print();
2871 CkPrintf("In IReq: this=%p, status=%d, length=%d\n", this, statusIreq, length);
2874 void RednReq::print(){
2875 AmpiRequest::print();
2876 CkPrintf("In RednReq: this=%p, status=%d\n", this, statusIreq);
2879 void GatherReq::print(){
2880 AmpiRequest::print();
2881 CkPrintf("In GatherReq: this=%p, status=%d\n", this, statusIreq);
2884 void GathervReq::print(){
2885 AmpiRequest::print();
2886 CkPrintf("In GathervReq: this=%p, status=%d\n", this, statusIreq);
2889 void IATAReq::print(){ //not complete for myreqs
2890 AmpiRequest::print();
2891 CkPrintf("In IATAReq: elmcount=%d, idx=%d\n", elmcount, idx);
2894 void SendReq::print(){
2895 AmpiRequest::print();
2896 CkPrintf("In SendReq: this=%p, status=%d\n", this, statusIreq);
2899 void SsendReq::print(){
2900 AmpiRequest::print();
2901 CkPrintf("In SsendReq: this=%p, status=%d\n", this, statusIreq);
2904 void AmpiRequestList::pup(PUP::er &p) {
2905 if(!CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC)){
2909 p(blklen); //Allocated size of block
2910 p(len); //Number of used elements in block
2911 if(p.isUnpacking()){
2912 makeBlock(blklen,len);
2915 for(int i=0;i<len;i++){
2917 if(!p.isUnpacking()){
2918 if(block[i] == NULL){
2921 nonnull = block[i]->getType();
2926 if(p.isUnpacking()){
2929 block[i] = new PersReq;
2932 block[i] = new IReq;
2935 block[i] = new RednReq;
2937 case MPI_GATHER_REQ:
2938 block[i] = new GatherReq;
2940 case MPI_GATHERV_REQ:
2941 block[i] = new GathervReq;
2944 block[i] = new SendReq;
2947 block[i] = new SsendReq;
2950 block[i] = new IATAReq;
2965 //------------------ External Interface -----------------
2966 ampiParent *getAmpiParent(void) {
2967 ampiParent *p = CtvAccess(ampiPtr);
2968 #if CMK_ERROR_CHECKING
2969 if (p==NULL) CkAbort("Cannot call MPI routines before AMPI is initialized.\n");
2974 ampi *getAmpiInstance(MPI_Comm comm) {
2975 ampi *ptr=getAmpiParent()->comm2ampi(comm);
2976 #if CMK_ERROR_CHECKING
2977 if (ptr==NULL) CkAbort("AMPI's getAmpiInstance> null pointer\n");
2982 bool isAmpiThread(void) {
2983 return (CtvAccess(ampiPtr)) ? true : false;
2986 inline static AmpiRequestList *getReqs(void) {
2987 return &(getAmpiParent()->ampiReqs);
2990 inline void checkComm(MPI_Comm comm){
2991 #if AMPI_ERROR_CHECKING
2992 getAmpiParent()->checkComm(comm);
2996 inline void checkRequest(MPI_Request req){
2997 #if AMPI_ERROR_CHECKING
2998 getReqs()->checkRequest(req);
3002 inline void checkRequests(int n, MPI_Request* reqs){
3003 #if AMPI_ERROR_CHECKING
3004 AmpiRequestList* reqlist = getReqs();
3005 for(int i=0;i<n;i++)
3006 reqlist->checkRequest(reqs[i]);
3010 int testRequest(MPI_Request *reqIdx, int *flag, MPI_Status *sts){
3011 MPI_Status tempStatus;
3012 if(!sts) sts = &tempStatus;
3014 if(*reqIdx==MPI_REQUEST_NULL){
3019 checkRequest(*reqIdx);
3020 AmpiRequestList* reqList = getReqs();
3021 AmpiRequest& req = *(*reqList)[*reqIdx];
3022 if(1 == (*flag = req.itest(sts))){
3024 if(req.getType() != MPI_PERS_REQ) { // only free non-blocking request
3025 reqList->free(*reqIdx);
3026 *reqIdx = MPI_REQUEST_NULL;
3032 int testRequestNoFree(MPI_Request *reqIdx, int *flag, MPI_Status *sts){
3033 MPI_Status tempStatus;
3034 if(!sts) sts = &tempStatus;
3036 if(*reqIdx==MPI_REQUEST_NULL){
3041 checkRequest(*reqIdx);
3042 AmpiRequestList* reqList = getReqs();
3043 AmpiRequest& req = *(*reqList)[*reqIdx];
3044 *flag = req.itest(sts);
3051 int AMPI_Is_thread_main(int *flag)
3053 AMPIAPI_INIT("AMPI_Is_thread_main");
3054 if (isAmpiThread()) {
3063 int AMPI_Query_thread(int *provided)
3065 AMPIAPI("AMPI_Query_thread");
3066 *provided = CkpvAccess(ampiThreadLevel);
3071 int AMPI_Init_thread(int *p_argc, char*** p_argv, int required, int *provided)
3073 if (nodeinit_has_been_called) {
3074 AMPIAPI_INIT("AMPI_Init_thread");
3076 #if AMPI_ERROR_CHECKING
3077 if (required < MPI_THREAD_SINGLE || required > MPI_THREAD_MULTIPLE) {
3078 return ampiErrhandler("AMPI_Init_thread", MPI_ERR_ARG);
3082 if (required == MPI_THREAD_SINGLE) {
3083 CkpvAccess(ampiThreadLevel) = MPI_THREAD_SINGLE;
3086 CkpvAccess(ampiThreadLevel) = MPI_THREAD_FUNNELED;
3088 // AMPI does not support MPI_THREAD_SERIALIZED or MPI_THREAD_MULTIPLE
3090 *provided = CkpvAccess(ampiThreadLevel);
3091 return AMPI_Init(p_argc, p_argv);
3094 { /* Charm hasn't been started yet! */
3095 CkAbort("MPI_Init_thread> AMPI has not been initialized! Possibly due to AMPI requiring '#include \"mpi.h\" be in the same file as main() in C/C++ programs and \'program main\' be renamed to \'subroutine mpi_main\' in Fortran programs!");
3101 int AMPI_Init(int *p_argc, char*** p_argv)
3103 if (nodeinit_has_been_called) {
3104 AMPIAPI_INIT("AMPI_Init");
3106 if (p_argv) argv=*p_argv;
3107 else argv=CkGetArgv();
3109 if (p_argc) *p_argc=CmiGetArgc(argv);
3112 { /* Charm hasn't been started yet! */
3113 CkAbort("MPI_Init> AMPI has not been initialized! Possibly due to AMPI requiring '#include \"mpi.h\" be in the same file as main() in C/C++ programs and \'program main\' be renamed to \'subroutine mpi_main\' in Fortran programs!");
3120 int AMPI_Initialized(int *isInit)
3122 if (nodeinit_has_been_called) {
3123 AMPIAPI_INIT("AMPI_Initialized"); /* in case charm init not called */
3124 *isInit=CtvAccess(ampiInitDone);
3126 else /* !nodeinit_has_been_called */ {
3127 *isInit=nodeinit_has_been_called;
3133 int AMPI_Finalized(int *isFinalized)
3135 AMPIAPI("AMPI_Finalized"); /* in case charm init not called */
3136 *isFinalized=(CtvAccess(ampiFinalized)) ? 1 : 0;
3141 int AMPI_Comm_rank(MPI_Comm comm, int *rank)
3143 AMPIAPI("AMPI_Comm_rank");
3145 #if AMPI_ERROR_CHECKING
3146 int ret = checkCommunicator("AMPI_Comm_rank", comm);
3147 if(ret != MPI_SUCCESS)
3152 ampiParent* pptr = getAmpiParent();
3154 PUParray(*(pptr->fromPUPer), (char*)rank, sizeof(int));
3159 *rank = getAmpiInstance(comm)->getRank(comm);
3162 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3163 PUParray(*(pptr->toPUPer), (char*)rank, sizeof(int));
3170 int AMPI_Comm_size(MPI_Comm comm, int *size)
3172 AMPIAPI("AMPI_Comm_size");
3174 #if AMPI_ERROR_CHECKING
3175 int ret = checkCommunicator("AMPI_Comm_size", comm);
3176 if(ret != MPI_SUCCESS)
3181 ampiParent* pptr = getAmpiParent();
3183 PUParray(*(pptr->fromPUPer), (char*)size, sizeof(int));
3188 *size = getAmpiInstance(comm)->getSize(comm);
3191 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3192 PUParray(*(pptr->toPUPer), (char*)size, sizeof(int));
3200 int AMPI_Comm_compare(MPI_Comm comm1,MPI_Comm comm2, int *result)
3202 AMPIAPI("AMPI_Comm_compare");
3204 #if AMPI_ERROR_CHECKING
3206 ret = checkCommunicator("AMPI_Comm_compare", comm1);
3207 if(ret != MPI_SUCCESS)
3209 ret = checkCommunicator("AMPI_Comm_compare", comm2);
3210 if(ret != MPI_SUCCESS)
3214 if(comm1==comm2) *result=MPI_IDENT;
3217 vector<int> ind1, ind2;
3218 ind1 = getAmpiInstance(comm1)->getIndices();
3219 ind2 = getAmpiInstance(comm2)->getIndices();
3220 if(ind1.size()==ind2.size()){
3221 for(int i=0;i<ind1.size();i++){
3223 for(int j=0;j<ind2.size();j++){
3224 if(ind1[i]==ind2[j]){
3226 if(i!=j) congruent=0;
3230 *result=MPI_UNEQUAL;
3235 if(congruent==1) *result=MPI_CONGRUENT;
3236 else *result=MPI_SIMILAR;
3242 void AMPI_Exit(int /*exitCode*/)
3244 AMPIAPI("AMPI_Exit");
3249 void FTN_NAME(MPI_EXIT,mpi_exit)(int *exitCode)
3251 AMPI_Exit(*exitCode);
3255 int AMPI_Finalize(void)
3257 AMPIAPI("AMPI_Finalize");
3259 CkPrintf("[%d] Idle time %fs.\n", CkMyPe(), totalidle);
3261 CtvAccess(ampiFinalized)=true;
3263 #if CMK_BIGSIM_CHARM && CMK_TRACE_IN_CHARM
3264 if(CpvAccess(traceOn)) traceSuspend();
3271 MPI_Request ampi::postReq(AmpiRequest* newreq)
3273 MPI_Request request = getReqs()->insert(newreq);
3274 // Completed requests should not be inserted into the posted_ireqs queue.
3275 // All types of send requests are matched by their request number,
3276 // not by (tag, src, comm), so they should not be inserted either.
3277 if (!newreq->statusIreq &&
3278 newreq->getType() != MPI_SEND_REQ &&
3279 newreq->getType() != MPI_SSEND_REQ &&
3280 !(newreq->getType() == MPI_PERS_REQ && ((PersReq*)newreq)->sndrcv != 2)) {
3281 int tags[2] = { newreq->tag, newreq->src };
3282 AmmPut(posted_ireqs, tags, (void *)(CmiIntPtr)(request+1));
3288 int AMPI_Send(void *msg, int count, MPI_Datatype type, int dest, int tag, MPI_Comm comm) {
3289 AMPIAPI("AMPI_Send");
3291 handle_MPI_BOTTOM(msg, type);
3293 #if AMPI_ERROR_CHECKING
3295 ret = errorCheck("AMPI_Send", comm, 1, count, 1, type, 1, tag, 1, dest, 1, msg, 1);
3296 if(ret != MPI_SUCCESS)
3306 ampi *ptr = getAmpiInstance(comm);
3307 ptr->send(tag, ptr->getRank(comm), msg, count, type, dest, comm);
3313 int AMPI_Ssend(void *msg, int count, MPI_Datatype type, int dest, int tag, MPI_Comm comm)
3315 AMPIAPI("AMPI_Ssend");
3317 handle_MPI_BOTTOM(msg, type);
3319 #if AMPI_ERROR_CHECKING
3320 int ret = errorCheck("AMPI_Ssend", comm, 1, count, 1, type, 1, tag, 1, dest, 1, msg, 1);
3321 if(ret != MPI_SUCCESS)
3331 ampi *ptr = getAmpiInstance(comm);
3332 ptr->send(tag, ptr->getRank(comm), msg, count, type, dest, comm, 1);
3338 int AMPI_Issend(void *buf, int count, MPI_Datatype type, int dest,
3339 int tag, MPI_Comm comm, MPI_Request *request)
3341 AMPIAPI("AMPI_Issend");
3343 handle_MPI_BOTTOM(buf, type);
3345 #if AMPI_ERROR_CHECKING
3346 int ret = errorCheck("AMPI_Issend", comm, 1, count, 1, type, 1, tag, 1, dest, 1, buf, 1);
3347 if(ret != MPI_SUCCESS){
3348 *request = MPI_REQUEST_NULL;
3354 ampiParent* pptr = getAmpiParent();
3356 PUParray(*(pptr->fromPUPer), (char *)request, sizeof(MPI_Request));
3361 USER_CALL_DEBUG("AMPI_Issend("<<type<<","<<dest<<","<<tag<<","<<comm<<")");
3362 ampi *ptr = getAmpiInstance(comm);
3363 *request = ptr->postReq(new SsendReq(comm));
3364 // 1: blocking now - used by MPI_Ssend
3365 // >=2: the index of the requests - used by MPI_Issend
3366 ptr->send(tag, ptr->getRank(comm), buf, count, type, dest, comm, *request+2);
3369 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3370 PUParray(*(pptr->toPUPer), (char *)request, sizeof(MPI_Request));
3378 int AMPI_Recv(void *msg, int count, MPI_Datatype type, int src, int tag,
3379 MPI_Comm comm, MPI_Status *status)
3381 AMPIAPI("AMPI_Recv");
3383 MPI_Status tempStatus;
3384 if(!status) status = &tempStatus;
3386 handle_MPI_BOTTOM(msg, type);
3388 #if AMPI_ERROR_CHECKING
3389 int ret = errorCheck("AMPI_Recv", comm, 1, count, 1, type, 1, tag, 1, src, 1, msg, 1);
3390 if(ret != MPI_SUCCESS)
3395 ampiParent* pptr = getAmpiParent();
3397 (*(pptr->fromPUPer))|(pptr->pupBytes);
3398 PUParray(*(pptr->fromPUPer), (char *)msg, (pptr->pupBytes));
3399 PUParray(*(pptr->fromPUPer), (char *)status, sizeof(MPI_Status));
3404 ampi *ptr = getAmpiInstance(comm);
3405 if(-1==ptr->recv(tag,src,msg,count,type,comm,status)) CkAbort("AMPI> Error in MPI_Recv");
3408 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3409 (pptr->pupBytes) = getDDT()->getSize(type) * count;
3410 (*(pptr->toPUPer))|(pptr->pupBytes);
3411 PUParray(*(pptr->toPUPer), (char *)msg, (pptr->pupBytes));
3412 PUParray(*(pptr->toPUPer), (char *)status, sizeof(MPI_Status));
3420 int AMPI_Probe(int src, int tag, MPI_Comm comm, MPI_Status *status)
3422 AMPIAPI("AMPI_Probe");
3424 #if AMPI_ERROR_CHECKING
3425 int ret = errorCheck("AMPI_Probe", comm, 1, 0, 0, 0, 0, tag, 1, src, 1, 0, 0);
3426 if(ret != MPI_SUCCESS)
3430 MPI_Status tempStatus;
3431 if(!status) status = &tempStatus;
3433 ampi *ptr = getAmpiInstance(comm);
3434 ptr->probe(tag, src, comm, status);
3439 int AMPI_Iprobe(int src,int tag,MPI_Comm comm,int *flag,MPI_Status *status)
3441 AMPIAPI("AMPI_Iprobe");
3443 #if AMPI_ERROR_CHECKING
3444 int ret = errorCheck("AMPI_Iprobe", comm, 1, 0, 0, 0, 0, tag, 1, src, 1, 0, 0);
3445 if(ret != MPI_SUCCESS)
3448 MPI_Status tempStatus;
3449 if(!status) status = &tempStatus;
3451 ampi *ptr = getAmpiInstance(comm);
3452 *flag = ptr->iprobe(tag, src, comm, status);
3456 void ampi::sendrecv(void *sbuf, int scount, MPI_Datatype stype, int dest, int stag,
3457 void *rbuf, int rcount, MPI_Datatype rtype, int src, int rtag,
3458 MPI_Comm comm, MPI_Status *sts)
3460 send(stag, getRank(comm), sbuf, scount, stype, dest, comm);
3462 if(-1==recv(rtag, src, rbuf, rcount, rtype, comm, sts))
3463 CkAbort("AMPI> Error in MPI_Sendrecv!\n");
3467 int AMPI_Sendrecv(void *sbuf, int scount, MPI_Datatype stype, int dest,
3468 int stag, void *rbuf, int rcount, MPI_Datatype rtype,
3469 int src, int rtag, MPI_Comm comm, MPI_Status *sts)
3471 AMPIAPI("AMPI_Sendrecv");
3473 handle_MPI_BOTTOM(sbuf, stype, rbuf, rtype);
3475 #if AMPI_ERROR_CHECKING
3476 if(sbuf == MPI_IN_PLACE || rbuf == MPI_IN_PLACE)
3477 CkAbort("MPI_sendrecv does not accept MPI_IN_PLACE; use MPI_Sendrecv_replace instead.");
3479 ret = errorCheck("AMPI_Sendrecv", comm, 1, scount, 1, stype, 1, stag, 1, dest, 1, sbuf, 1);
3480 if(ret != MPI_SUCCESS)
3482 ret = errorCheck("AMPI_Sendrecv", comm, 1, rcount, 1, rtype, 1, rtag, 1, src, 1, rbuf, 1);
3483 if(ret != MPI_SUCCESS)
3487 MPI_Status tempStatus;
3488 if(!sts) sts = &tempStatus;
3489 ampi *ptr = getAmpiInstance(comm);
3491 ptr->sendrecv(sbuf, scount, stype, dest, stag,
3492 rbuf, rcount, rtype, src, rtag,
3499 int AMPI_Sendrecv_replace(void* buf, int count, MPI_Datatype datatype,
3500 int dest, int sendtag, int source, int recvtag,
3501 MPI_Comm comm, MPI_Status *status)
3503 AMPIAPI("AMPI_Sendrecv_replace");
3504 return AMPI_Sendrecv(buf, count, datatype, dest, sendtag,
3505 buf, count, datatype, source, recvtag, comm, status);
3508 void ampi::barrier()
3510 CkCallback barrierCB(CkReductionTarget(ampi, barrierResult), getProxy());
3511 contribute(barrierCB);
3512 thread->suspend(); //Resumed by ampi::barrierResult
3515 void ampi::barrierResult(void)
3517 MSG_ORDER_DEBUG(CkPrintf("[%d] barrierResult called\n", thisIndex));
3522 int AMPI_Barrier(MPI_Comm comm)
3524 AMPIAPI("AMPI_Barrier");
3526 #if AMPI_ERROR_CHECKING
3527 int ret = checkCommunicator("AMPI_Barrier", comm);
3528 if(ret != MPI_SUCCESS)
3532 if(comm==MPI_COMM_SELF)
3534 if(getAmpiParent()->isInter(comm))
3535 CkAbort("AMPI does not implement MPI_Barrier for Inter-communicators!");
3537 #if CMK_BIGSIM_CHARM
3538 TRACE_BG_AMPI_LOG(MPI_BARRIER, 0);
3541 ampi *ptr = getAmpiInstance(comm);
3542 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Barrier called on comm %d\n", ptr->thisIndex, comm));
3549 void ampi::ibarrier(MPI_Request *request)
3551 CkCallback ibarrierCB(CkReductionTarget(ampi, ibarrierResult), getProxy());
3552 contribute(ibarrierCB);
3554 // use an IReq to non-block the caller and get a request ptr
3555 *request = postReq(new IReq(NULL, 0, MPI_INT, AMPI_COLL_SOURCE, MPI_ATA_TAG, AMPI_COLL_COMM));
3558 void ampi::ibarrierResult(void)
3560 MSG_ORDER_DEBUG(CkPrintf("[%d] ibarrierResult called\n", thisIndex));
3561 ampi::sendraw(MPI_ATA_TAG, AMPI_COLL_SOURCE, NULL, 0, thisArrayID, thisIndex);
3565 int AMPI_Ibarrier(MPI_Comm comm, MPI_Request *request)
3567 AMPIAPI("AMPI_Ibarrier");
3569 #if AMPI_ERROR_CHECKING
3570 int ret = checkCommunicator("AMPI_Ibarrier", comm);
3571 if(ret != MPI_SUCCESS){
3572 *request = MPI_REQUEST_NULL;
3577 ampi *ptr = getAmpiInstance(comm);
3579 if(comm==MPI_COMM_SELF){
3580 *request = ptr->postReq(new IReq(NULL, 0, MPI_INT, AMPI_COLL_SOURCE, MPI_ATA_TAG, AMPI_COLL_COMM,
3581 AMPI_REQ_COMPLETED));
3584 if(getAmpiParent()->isInter(comm))
3585 CkAbort("AMPI does not implement MPI_Ibarrier for Inter-communicators!");
3587 #if CMK_BIGSIM_CHARM
3588 TRACE_BG_AMPI_LOG(MPI_BARRIER, 0);
3591 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Ibarrier called on comm %d\n", ptr->thisIndex, comm));
3593 ptr->ibarrier(request);
3599 int AMPI_Bcast(void *buf, int count, MPI_Datatype type, int root, MPI_Comm comm)
3601 AMPIAPI("AMPI_Bcast");
3603 handle_MPI_BOTTOM(buf, type);
3605 #if AMPI_ERROR_CHECKING
3606 int ret = errorCheck("AMPI_Bcast", comm, 1, count, 1, type, 1, 0, 0, root, 1, buf, 1);
3607 if(ret != MPI_SUCCESS)
3611 if(comm==MPI_COMM_SELF)
3613 if(getAmpiParent()->isInter(comm))
3614 CkAbort("AMPI does not implement MPI_Bcast for Inter-communicators!");
3617 ampiParent* pptr = getAmpiParent();
3619 (*(pptr->fromPUPer))|(pptr->pupBytes);
3620 PUParray(*(pptr->fromPUPer), (char *)buf, (pptr->pupBytes));
3625 ampi* ptr = getAmpiInstance(comm);
3626 ptr->bcast(root, buf, count, type,comm);
3629 if(msgLogWrite && record_msglog(pptr->thisIndex)) {
3630 (pptr->pupBytes) = getDDT()->getSize(type) * count;
3631 (*(pptr->toPUPer))|(pptr->pupBytes);
3632 PUParray(*(pptr->toPUPer), (char *)buf, (pptr->pupBytes));
3640 int AMPI_Ibcast(void *buf, int count, MPI_Datatype type, int root,
3641 MPI_Comm comm, MPI_Request *request)
3643 AMPIAPI("AMPI_Ibcast");
3645 handle_MPI_BOTTOM(buf, type);
3647 #if AMPI_ERROR_CHECKING
3648 int ret = errorCheck("AMPI_Ibcast", comm, 1, count, 1, type, 1, 0, 0, root, 1, buf, 1);
3649 if(ret != MPI_SUCCESS){
3650 *request = MPI_REQUEST_NULL;
3655 ampi* ptr = getAmpiInstance(comm);
3657 if(comm==MPI_COMM_SELF){
3658 *request = ptr->postReq(new IReq(buf, count, type, root, MPI_BCAST_TAG, comm,
3659 AMPI_REQ_COMPLETED));
3662 if(getAmpiParent()->isInter(comm))
3663 CkAbort("AMPI does not implement MPI_Ibcast for Inter-communicators!");
3666 ampiParent* pptr = getAmpiParent();
3668 (*(pptr->fromPUPer))|(pptr->pupBytes);
3669 PUParray(*(pptr->fromPUPer), (char *)buf, (pptr->pupBytes));
3674 ptr->ibcast(root, buf, count, type, comm, request);
3677 if(msgLogWrite && record_msglog(pptr->thisIndex)) {
3678 (pptr->pupBytes) = getDDT()->getSize(type) * count;
3679 (*(pptr->toPUPer))|(pptr->pupBytes);
3680 PUParray(*(pptr->toPUPer), (char *)buf, (pptr->pupBytes));
3687 // This routine is called with the results of an (All)Reduce or (All)Gather(v)
3688 void ampi::rednResult(CkReductionMsg *msg)
3690 MSG_ORDER_DEBUG(CkPrintf("[%d] rednResult called on comm %d\n", thisIndex, myComm.getComm()));
3692 if (blockingReq == NULL) {
3693 CkAbort("AMPI> recv'ed a blocking reduction unexpectedly!\n");
3696 #if CMK_BIGSIM_CHARM
3697 TRACE_BG_ADD_TAG("AMPI_generic");
3699 _TRACE_BG_TLINE_END(&msg->event); // store current log
3700 msg->eventPe = CkMyPe();
3703 blockingReq->receive(this, msg);
3705 if (parent->resumeOnColl) {
3708 // [nokeep] entry method, so do not delete msg
3711 // This routine is called with the results of an I(all)reduce or I(all)gather(v)
3712 void ampi::irednResult(CkReductionMsg *msg)
3714 MSG_ORDER_DEBUG(CkPrintf("[%d] irednResult called on comm %d\n", thisIndex, myComm.getComm()));
3717 int tags[2] = { MPI_REDN_TAG, AMPI_COLL_SOURCE };
3718 AmpiRequestList *reqL = &(parent->ampiReqs);
3719 int rednReqIdx = (int)((long)AmmGet(posted_ireqs, tags, (int*)&sts));
3720 AmpiRequest *rednReq = NULL;
3721 if(reqL->size()>0 && rednReqIdx>0)
3722 rednReq = (AmpiRequest *)(*reqL)[rednReqIdx-1];
3723 if (rednReq == NULL)
3724 CkAbort("AMPI> recv'ed a non-blocking reduction unexpectedly!\n");
3726 #if CMK_BIGSIM_CHARM
3727 TRACE_BG_ADD_TAG("AMPI_generic");
3729 _TRACE_BG_TLINE_END(&msg->event); // store current log
3730 msg->eventPe = CkMyPe();
3734 PUParray(*(getAmpiParent()->fromPUPer), (char *)rednReq, sizeof(int));
3739 if (rednReq->isBlocked()) {
3740 parent->numBlockedReqs--;
3742 rednReq->receive(this, msg);
3745 if(msgLogWrite && record_msglog(getAmpiParent()->thisIndex)){
3746 PUParray(*(getAmpiParent()->toPUPer), (char *)reqnReq, sizeof(int));
3750 if (parent->resumeOnColl && parent->numBlockedReqs==0) {
3753 // [nokeep] entry method, so do not delete msg
3756 static CkReductionMsg *makeRednMsg(CkDDT_DataType *ddt,const void *inbuf,int count,int type,int rank,MPI_Op op)
3758 CkReductionMsg *msg;
3759 ampiParent *parent = getAmpiParent();
3760 int szdata = ddt->getSize(count);
3761 CkReduction::reducerType reducer = getBuiltinReducerType(type, op);
3763 if (reducer != CkReduction::invalid) {
3764 // MPI predefined op matches a Charm++ builtin reducer type
3765 AMPI_DEBUG("[%d] In makeRednMsg, using Charm++ built-in reducer type for a predefined op\n", thisIndex);
3766 msg = CkReductionMsg::buildNew(szdata, NULL, reducer);
3767 ddt->serialize((char*)inbuf, (char*)msg->getData(), count, 1);
3769 else if (parent->opIsCommutative(op)) {
3770 // Either an MPI predefined reducer operation with no Charm++ builtin
3771 // reducer type equivalent, or a commutative user-defined reducer operation
3772 AMPI_DEBUG("[%d] In makeRednMsg, using custom AmpiReducer type for a commutative op\n", thisIndex);
3773 AmpiOpHeader newhdr = parent->op2AmpiOpHeader(op, type, count);
3774 int szhdr = sizeof(AmpiOpHeader);
3775 msg = CkReductionMsg::buildNew(szdata+szhdr, NULL, AmpiReducer);
3776 memcpy(msg->getData(), &newhdr, szhdr);
3777 ddt->serialize((char*)inbuf, (char*)msg->getData()+szhdr, count, 1);
3780 // Non-commutative user-defined reducer operation
3781 AMPI_DEBUG("[%d] In makeRednMsg, using a non-commutative user-defined operation\n", thisIndex);
3782 const int tupleSize = 2;
3783 CkReduction::tupleElement tupleRedn[tupleSize];
3784 tupleRedn[0] = CkReduction::tupleElement(sizeof(int), &rank, CkReduction::set);
3785 if (!ddt->isContig()) {
3786 vector<char> sbuf(szdata);
3787 ddt->serialize((char*)inbuf, &sbuf[0], count, 1);
3788 tupleRedn[1] = CkReduction::tupleElement(szdata, &sbuf[0], CkReduction::set);
3791 tupleRedn[1] = CkReduction::tupleElement(szdata, (void*)inbuf, CkReduction::set);
3793 msg = CkReductionMsg::buildFromTuple(tupleRedn, tupleSize);
3798 // Copy the MPI datatype "type" from inbuf to outbuf
3799 static int copyDatatype(MPI_Comm comm,MPI_Datatype type,int count,const void *inbuf,void *outbuf) {
3800 ampi *ptr = getAmpiInstance(comm);
3801 CkDDT_DataType *ddt = ptr->getDDT()->getType(type);
3802 int len = ddt->getSize(count);
3804 if (ddt->isContig()) {
3805 memcpy(outbuf, inbuf, len);
3807 // ddts don't have "copy", so fake it by serializing into a temp buffer, then
3808 // deserializing into the output.
3809 vector<char> serialized(len);
3810 ddt->serialize((char*)inbuf, &serialized[0], count, 1);
3811 ddt->serialize((char*)outbuf, &serialized[0], count, -1);
3817 static void handle_MPI_IN_PLACE(void* &inbuf, void* &outbuf)
3819 if (inbuf == MPI_IN_PLACE) inbuf = outbuf;
3820 if (outbuf == MPI_IN_PLACE) outbuf = inbuf;
3821 CkAssert(inbuf != MPI_IN_PLACE && outbuf != MPI_IN_PLACE);
3824 #define SYNCHRONOUS_REDUCE 0
3827 int AMPI_Reduce(void *inbuf, void *outbuf, int count, MPI_Datatype type, MPI_Op op, int root, MPI_Comm comm)
3829 AMPIAPI("AMPI_Reduce");
3831 handle_MPI_BOTTOM(inbuf, type, outbuf, type);
3832 handle_MPI_IN_PLACE(inbuf, outbuf);
3834 #if AMPI_ERROR_CHECKING
3835 if(op == MPI_OP_NULL)
3836 return ampiErrhandler("AMPI_Reduce", MPI_ERR_OP);
3837 int ret = errorCheck("AMPI_Reduce", comm, 1, count, 1, type, 1, 0, 0, root, 1, inbuf, 1,
3838 outbuf, getAmpiInstance(comm)->getRank(comm) == root);
3839 if(ret != MPI_SUCCESS)
3843 if(comm==MPI_COMM_SELF)
3844 return copyDatatype(comm,type,count,inbuf,outbuf);
3845 if(getAmpiParent()->isInter(comm))
3846 CkAbort("AMPI does not implement MPI_Reduce for Inter-communicators!");
3849 ampiParent* pptr = getAmpiParent();
3851 (*(pptr->fromPUPer))|(pptr->pupBytes);
3852 PUParray(*(pptr->fromPUPer), (char *)outbuf, (pptr->pupBytes));
3857 ampi *ptr = getAmpiInstance(comm);
3858 int rootIdx=ptr->comm2CommStruct(comm).getIndexForRank(root);
3860 CkReductionMsg *msg=makeRednMsg(ptr->getDDT()->getType(type),inbuf,count,type,ptr->getRank(comm),op);
3862 CkCallback reduceCB(CkIndex_ampi::rednResult(0),CkArrayIndex1D(rootIdx),ptr->getProxy());
3863 msg->setCallback(reduceCB);
3864 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Reduce called on comm %d root %d \n",ptr->thisIndex,comm,rootIdx));
3865 ptr->contribute(msg);
3867 if (ptr->thisIndex == rootIdx){
3868 ptr = ptr->blockOnRedn(new RednReq(outbuf, count, type, comm, op));
3870 #if SYNCHRONOUS_REDUCE
3871 AmpiMsg *msg = new (0, 0) AmpiMsg(-1, MPI_REDN_TAG, -1, rootIdx, 0, comm);
3872 CProxy_ampi pa(ptr->getProxy());
3876 #if SYNCHRONOUS_REDUCE
3877 ptr->recv(MPI_REDN_TAG, AMPI_COLL_SOURCE, NULL, 0, type, comm);
3881 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3882 (pptr->pupBytes) = getDDT()->getSize(type) * count;
3883 (*(pptr->toPUPer))|(pptr->pupBytes);
3884 PUParray(*(pptr->toPUPer), (char *)outbuf, (pptr->pupBytes));
3892 int AMPI_Allreduce(void *inbuf, void *outbuf, int count, MPI_Datatype type, MPI_Op op, MPI_Comm comm)
3894 AMPIAPI("AMPI_Allreduce");
3896 handle_MPI_BOTTOM(inbuf, type, outbuf, type);
3897 handle_MPI_IN_PLACE(inbuf, outbuf);
3899 #if AMPI_ERROR_CHECKING
3900 if(op == MPI_OP_NULL)
3901 return ampiErrhandler("AMPI_Allreduce", MPI_ERR_OP);
3902 int ret = errorCheck("AMPI_Allreduce", comm, 1, count, 1, type, 1, 0, 0, 0, 0, inbuf, 1, outbuf, 1);
3903 if(ret != MPI_SUCCESS)
3907 if(comm==MPI_COMM_SELF)
3908 return copyDatatype(comm,type,count,inbuf,outbuf);
3909 if(getAmpiParent()->isInter(comm))
3910 CkAbort("AMPI does not implement MPI_Allreduce for Inter-communicators!");
3912 #if CMK_BIGSIM_CHARM
3913 TRACE_BG_AMPI_LOG(MPI_ALLREDUCE, getAmpiInstance(comm)->getDDT()->getType(type)->getSize(count));
3917 ampiParent* pptr = getAmpiParent();
3919 (*(pptr->fromPUPer))|(pptr->pupBytes);
3920 PUParray(*(pptr->fromPUPer), (char *)outbuf, (pptr->pupBytes));
3925 ampi *ptr = getAmpiInstance(comm);
3927 CkReductionMsg *msg=makeRednMsg(ptr->getDDT()->getType(type), inbuf, count, type, ptr->getRank(comm), op);
3928 CkCallback allreduceCB(CkIndex_ampi::rednResult(0),ptr->getProxy());
3929 msg->setCallback(allreduceCB);
3930 ptr->contribute(msg);
3932 ptr->blockOnRedn(new RednReq(outbuf, count, type, comm, op));
3935 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3936 (pptr->pupBytes) = getDDT()->getSize(type) * count;
3937 (*(pptr->toPUPer))|(pptr->pupBytes);
3938 PUParray(*(pptr->toPUPer), (char *)outbuf, (pptr->pupBytes));
3946 int AMPI_Iallreduce(void *inbuf, void *outbuf, int count, MPI_Datatype type, MPI_Op op,
3947 MPI_Comm comm, MPI_Request* request)
3949 AMPIAPI("AMPI_Iallreduce");
3951 handle_MPI_BOTTOM(inbuf, type, outbuf, type);
3952 handle_MPI_IN_PLACE(inbuf, outbuf);
3954 #if AMPI_ERROR_CHECKING
3955 if(op == MPI_OP_NULL)
3956 return ampiErrhandler("AMPI_Iallreduce", MPI_ERR_OP);
3957 int ret = errorCheck("AMPI_Iallreduce", comm, 1, count, 1, type, 1, 0, 0, 0, 0, inbuf, 1, outbuf, 1);
3958 if(ret != MPI_SUCCESS){
3959 *request = MPI_REQUEST_NULL;
3964 ampi *ptr = getAmpiInstance(comm);
3966 if(comm==MPI_COMM_SELF){
3967 *request = ptr->postReq(new RednReq(outbuf,count,type,comm,op,AMPI_REQ_COMPLETED));
3968 return copyDatatype(comm,type,count,inbuf,outbuf);
3970 if(getAmpiParent()->isInter(comm))
3971 CkAbort("AMPI does not implement MPI_Iallreduce for Inter-communicators!");
3973 CkReductionMsg *msg=makeRednMsg(ptr->getDDT()->getType(type),inbuf,count,type,ptr->getRank(comm),op);
3974 CkCallback allreduceCB(CkIndex_ampi::irednResult(0),ptr->getProxy());
3975 msg->setCallback(allreduceCB);
3976 ptr->contribute(msg);
3978 // use a RednReq to non-block the caller and get a request ptr
3979 *request = ptr->postReq(new RednReq(outbuf,count,type,comm,op));
3985 int AMPI_Reduce_local(void *inbuf, void *outbuf, int count, MPI_Datatype type, MPI_Op op)
3987 AMPIAPI("AMPI_Reduce_local");
3989 handle_MPI_BOTTOM(inbuf, type, outbuf, type);
3991 #if AMPI_ERROR_CHECKING
3992 if(op == MPI_OP_NULL)
3993 return ampiErrhandler("AMPI_Reduce_local", MPI_ERR_OP);
3994 if(inbuf == MPI_IN_PLACE || outbuf == MPI_IN_PLACE)
3995 CkAbort("MPI_Reduce_local does not accept MPI_IN_PLACE!");
3996 int ret = errorCheck("AMPI_Reduce_local", MPI_COMM_SELF, 1, count, 1, type, 1, 0, 0, 0, 1, inbuf, 1, outbuf, 1);
3997 if(ret != MPI_SUCCESS)
4001 getAmpiParent()->applyOp(type, op, count, inbuf, outbuf);
4006 int AMPI_Reduce_scatter_block(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype,
4007 MPI_Op op, MPI_Comm comm)
4009 AMPIAPI("AMPI_Reduce_scatter_block");
4011 handle_MPI_BOTTOM(sendbuf, datatype, recvbuf, datatype);
4012 handle_MPI_IN_PLACE(sendbuf, recvbuf);
4014 #if AMPI_ERROR_CHECKING
4015 if(op == MPI_OP_NULL)
4016 return ampiErrhandler("AMPI_Reduce_scatter_block", MPI_ERR_OP);
4017 int ret = errorCheck("AMPI_Reduce_scatter_block", comm, 1, 0, 0, datatype, 1, 0, 0, 0, 0, sendbuf, 1, recvbuf, 1);
4018 if(ret != MPI_SUCCESS)
4022 if(comm==MPI_COMM_SELF)
4023 return copyDatatype(comm, datatype, count, sendbuf, recvbuf);
4024 if(getAmpiParent()->isInter(comm))
4025 CkAbort("AMPI does not implement MPI_Reduce_scatter_block for Inter-communicators!");
4027 ampi *ptr = getAmpiInstance(comm);
4028 int size = ptr->getSize(comm);
4029 vector<char> tmpbuf(ptr->getDDT()->getType(datatype)->getSize(count)*size);
4031 AMPI_Reduce(sendbuf, &tmpbuf[0], count*size, datatype, op, AMPI_COLL_SOURCE, comm);
4032 AMPI_Scatter(&tmpbuf[0], count, datatype, recvbuf, count, datatype, AMPI_COLL_SOURCE, comm);
4038 int AMPI_Reduce_scatter(void* sendbuf, void* recvbuf, int *recvcounts, MPI_Datatype datatype,
4039 MPI_Op op, MPI_Comm comm)
4041 AMPIAPI("AMPI_Reduce_scatter");
4043 handle_MPI_BOTTOM(sendbuf, datatype, recvbuf, datatype);
4044 handle_MPI_IN_PLACE(sendbuf, recvbuf);
4046 #if AMPI_ERROR_CHECKING
4047 if(op == MPI_OP_NULL)
4048 return ampiErrhandler("AMPI_Reduce_scatter", MPI_ERR_OP);
4049 int ret = errorCheck("AMPI_Reduce_scatter", comm, 1, 0, 0, datatype, 1, 0, 0, 0, 0, sendbuf, 1, recvbuf, 1);
4050 if(ret != MPI_SUCCESS)
4054 if(comm==MPI_COMM_SELF)
4055 return copyDatatype(comm,datatype,recvcounts[0],sendbuf,recvbuf);
4056 if(getAmpiParent()->isInter(comm))
4057 CkAbort("AMPI does not implement MPI_Reduce_scatter for Inter-communicators!");
4059 ampi *ptr = getAmpiInstance(comm);
4060 int size = ptr->getSize(comm);
4062 vector<int> displs(size);
4065 //under construction
4066 for(int i=0;i<size;i++){
4068 count+= recvcounts[i];
4070 vector<char> tmpbuf(ptr->getDDT()->getType(datatype)->getSize(count));
4071 AMPI_Reduce(sendbuf, &tmpbuf[0], count, datatype, op, AMPI_COLL_SOURCE, comm);
4072 AMPI_Scatterv(&tmpbuf[0], recvcounts, &displs[0], datatype,
4073 recvbuf, recvcounts[ptr->getRank(comm)], datatype, AMPI_COLL_SOURCE, comm);
4078 int AMPI_Scan(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype,
4079 MPI_Op op, MPI_Comm comm ){
4080 AMPIAPI("AMPI_Scan");
4082 handle_MPI_BOTTOM(sendbuf, datatype, recvbuf, datatype);
4083 handle_MPI_IN_PLACE(sendbuf,recvbuf);
4085 #if AMPI_ERROR_CHECKING
4086 if(op == MPI_OP_NULL)
4087 return ampiErrhandler("AMPI_Scan", MPI_ERR_OP);
4088 int ret = errorCheck("AMPI_Scan", comm, 1, count, 1, datatype, 1, 0, 0, 0, 0, sendbuf, 1, recvbuf, 1);
4089 if(ret != MPI_SUCCESS)
4094 ampi *ptr = getAmpiInstance(comm);
4095 int size = ptr->getSize(comm);
4096 int blklen = ptr->getDDT()->getType(datatype)->getSize(count);
4097 int rank = ptr->getRank(comm);
4100 vector<char> tmp_buf(blklen);
4101 vector<char> partial_scan(blklen);
4103 memcpy(recvbuf, sendbuf, blklen);
4104 memcpy(&partial_scan[0], sendbuf, blklen);
4108 ptr->sendrecv(&partial_scan[0], count, datatype, dst, MPI_SCAN_TAG,
4109 &tmp_buf[0], count, datatype, dst, MPI_SCAN_TAG, comm, &sts);
4111 getAmpiParent()->applyOp(datatype, op, count, &tmp_buf[0], &partial_scan[0]);
4112 getAmpiParent()->applyOp(datatype, op, count, &tmp_buf[0], recvbuf);
4114 getAmpiParent()->applyOp(datatype, op, count, &partial_scan[0], &tmp_buf[0]);
4115 memcpy(&partial_scan[0],&tmp_buf[0],blklen);
4125 int AMPI_Exscan(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype,
4126 MPI_Op op, MPI_Comm comm){
4127 AMPIAPI("AMPI_Exscan");
4129 handle_MPI_BOTTOM(sendbuf, datatype, recvbuf, datatype);
4130 handle_MPI_IN_PLACE(sendbuf,recvbuf);
4132 #if AMPI_ERROR_CHECKING
4133 if(op == MPI_OP_NULL)
4134 return ampiErrhandler("AMPI_Exscan", MPI_ERR_OP);
4135 int ret = errorCheck("AMPI_Excan", comm, 1, count, 1, datatype, 1, 0, 0, 0, 0, sendbuf, 1, recvbuf, 1);
4136 if(ret != MPI_SUCCESS)
4141 ampi *ptr = getAmpiInstance(comm);
4142 int size = ptr->getSize(comm);
4143 int blklen = ptr->getDDT()->getType(datatype)->getSize(count);
4144 int rank = ptr->getRank(comm);
4147 vector<char> tmp_buf(blklen);
4148 vector<char> partial_scan(blklen);
4150 memcpy(recvbuf, sendbuf, blklen);
4151 memcpy(&partial_scan[0], sendbuf, blklen);
4157 ptr->sendrecv(&partial_scan[0], count, datatype, dst, MPI_EXSCAN_TAG,
4158 &tmp_buf[0], count, datatype, dst, MPI_EXSCAN_TAG, comm, &sts);
4160 getAmpiParent()->applyOp(datatype, op, count, &tmp_buf[0], &partial_scan[0]);
4163 memcpy(recvbuf,&tmp_buf[0],blklen);
4167 getAmpiParent()->applyOp(datatype, op, count, &tmp_buf[0], recvbuf);
4172 getAmpiParent()->applyOp(datatype, op, count, &partial_scan[0], &tmp_buf[0]);
4173 memcpy(&partial_scan[0],&tmp_buf[0],blklen);
4183 int AMPI_Op_create(MPI_User_function *function, int commute, MPI_Op *op){
4184 AMPIAPI("AMPI_Op_create");
4185 *op = getAmpiParent()->createOp(function, commute);
4190 int AMPI_Op_free(MPI_Op *op){
4191 AMPIAPI("AMPI_Op_free");
4197 int AMPI_Op_commutative(MPI_Op op, int *commute){
4198 AMPIAPI("AMPI_Op_commutative");
4199 *commute = (int)getAmpiParent()->opIsCommutative(op);
4204 double AMPI_Wtime(void)
4206 //AMPIAPI("AMPI_Wtime");
4209 double ret=TCHARM_Wall_timer();
4210 ampiParent* pptr = getAmpiParent();
4212 (*(pptr->fromPUPer))|ret;
4216 if(msgLogWrite && record_msglog(pptr->thisIndex)){
4217 (*(pptr->toPUPer))|ret;
4221 #if CMK_BIGSIM_CHARM
4224 return TCHARM_Wall_timer();
4229 double AMPI_Wtick(void){
4230 //AMPIAPI("AMPI_Wtick");
4234 int PersReq::start(){
4235 if(sndrcv == 1 || sndrcv == 3) { // send or ssend request
4236 ampi *ptr=getAmpiInstance(comm);
4237 ptr->send(tag, ptr->getRank(comm), buf, count, type, src, comm, sndrcv==3?1:0);
4243 int AMPI_Start(MPI_Request *request)
4245 AMPIAPI("AMPI_Start");
4246 checkRequest(*request);
4247 AmpiRequestList *reqs = getReqs();
4248 if(-1==(*reqs)[*request]->start()) {
4249 CkAbort("MPI_Start could be used only on persistent communication requests!");
4255 int AMPI_Startall(int count, MPI_Request *requests){
4256 AMPIAPI("AMPI_Startall");
4257 checkRequests(count,requests);
4258 AmpiRequestList *reqs = getReqs();
4259 for(int i=0;i<count;i++){
4260 if(-1==(*reqs)[requests[i]]->start())
4261 CkAbort("MPI_Start could be used only on persistent communication requests!");
4266 int PersReq::wait(MPI_Status *sts){
4268 if(-1==getAmpiInstance(comm)->recv(tag, src, buf, count, type, comm, sts))
4269 CkAbort("AMPI> Error in persistent request wait");
4270 #if CMK_BIGSIM_CHARM
4271 _TRACE_BG_TLINE_END(&event);
4277 int IReq::wait(MPI_Status *sts){
4278 //Copy "this" to a local variable in the case that "this" pointer
4279 //is updated during the out-of-core emulation.
4281 // optimization for Irecv
4282 // generic() writes directly to the buffer, so the only thing we
4283 // do here is to wait
4284 ampi *dis = getAmpiInstance(comm);
4286 while (statusIreq == false) {
4287 // "dis" is updated in case an ampi thread is migrated while waiting for a message
4288 dis->parent->resumeOnRecv = true;
4289 dis->parent->numBlockedReqs = 1;
4291 dis->parent->block();
4293 dis = getAmpiInstance(comm);
4296 sts->MPI_CANCEL = 1;
4298 dis->parent->resumeOnRecv = false;
4302 #if CMK_BIGSIM_CHARM
4303 //Because of the out-of-core emulation, this pointer is changed after in-out
4304 //memory operation. So we need to return from this function and do the while loop
4305 //in the outer function call.
4306 if(_BgInOutOfCoreMode)
4310 dis->parent->resumeOnRecv = false;
4312 AMPI_DEBUG("IReq::wait has resumed\n");
4315 AMPI_DEBUG("Setting sts->MPI_TAG to this->tag=%d in IReq::wait this=%p\n", (int)this->tag, this);
4317 sts->MPI_SOURCE = src;
4318 sts->MPI_COMM = comm;
4319 sts->MPI_LENGTH = length;
4320 sts->MPI_CANCEL = 0;
4326 int RednReq::wait(MPI_Status *sts){
4327 //Copy "this" to a local variable in the case that "this" pointer
4328 //is updated during the out-of-core emulation.
4330 // ampi::irednResult writes directly to the buffer, so the only thing we
4331 // do here is to wait
4332 ampi *dis = getAmpiInstance(comm);
4334 while (!statusIreq) {
4335 dis->parent->resumeOnColl = true;
4336 dis->parent->numBlockedReqs = 1;
4338 dis->parent->block();
4340 dis = getAmpiInstance(comm);
4342 #if CMK_BIGSIM_CHARM
4343 //Because of the out-of-core emulation, this pointer is changed after in-out
4344 //memory operation. So we need to return from this function and do the while loop
4345 //in the outer function call.
4346 if (_BgInOutOfCoreMode)
4350 dis->parent->resumeOnColl = false;
4352 AMPI_DEBUG("RednReq::wait has resumed\n");
4356 sts->MPI_SOURCE = src;
4357 sts->MPI_COMM = comm;
4358 sts->MPI_CANCEL = 0;
4363 int GatherReq::wait(MPI_Status *sts){
4364 //Copy "this" to a local variable in the case that "this" pointer
4365 //is updated during the out-of-core emulation.
4367 // ampi::irednResult writes directly to the buffer, so the only thing we
4368 // do here is to wait
4369 ampi *dis = getAmpiInstance(comm);
4371 while (!statusIreq) {
4372 dis->parent->resumeOnColl = true;
4373 dis->parent->numBlockedReqs = 1;
4375 dis->parent->block();
4377 dis = getAmpiInstance(comm);
4379 #if CMK_BIGSIM_CHARM
4380 //Because of the out-of-core emulation, this pointer is changed after in-out
4381 //memory operation. So we need to return from this function and do the while loop
4382 //in the outer function call.
4383 if (_BgInOutOfCoreMode)
4387 dis->parent->resumeOnColl = false;
4389 AMPI_DEBUG("GatherReq::wait has resumed\n");
4393 sts->MPI_SOURCE = src;
4394 sts->MPI_COMM = comm;
4395 sts->MPI_CANCEL = 0;
4400 int GathervReq::wait(MPI_Status *sts){
4401 //Copy "this" to a local variable in the case that "this" pointer
4402 //is updated during the out-of-core emulation.
4404 // ampi::irednResult writes directly to the buffer, so the only thing we
4405 // do here is to wait
4406 ampi *dis = getAmpiInstance(comm);
4408 while (!statusIreq) {
4409 dis->parent->resumeOnColl = true;
4410 dis->parent->numBlockedReqs = 1;
4412 dis->parent->block();
4414 dis = getAmpiInstance(comm);
4416 #if CMK_BIGSIM_CHARM
4417 //Because of the out-of-core emulation, this pointer is changed after in-out
4418 //memory operation. So we need to return from this function and do the while loop
4419 //in the outer function call.
4420 if (_BgInOutOfCoreMode)
4424 dis->parent->resumeOnColl = false;
4426 AMPI_DEBUG("GathervReq::wait has resumed\n");
4430 sts->MPI_SOURCE = src;
4431 sts->MPI_COMM = comm;
4432 sts->MPI_CANCEL = 0;
4437 int SendReq::wait(MPI_Status *sts){
4438 ampi *dis = getAmpiInstance(comm);
4439 while (!statusIreq) {
4440 dis->parent->resumeOnRecv = true;
4441 dis->parent->numBlockedReqs = 1;
4443 dis->parent->block();
4445 // "dis" is updated in case an ampi thread is migrated while waiting for a message
4446 dis = getAmpiInstance(comm);
4448 dis->parent->resumeOnRecv = false;
4449 AMPI_DEBUG("SendReq::wait has resumed\n");
4451 sts->MPI_COMM = comm;
4452 sts->MPI_CANCEL = 0;
4457 int SsendReq::wait(MPI_Status *sts){
4458 ampi *dis = getAmpiInstance(comm);
4459 while (!statusIreq) {
4460 // "dis" is updated in case an ampi thread is migrated while waiting for a message
4461 dis = dis->blockOnRecv();
4464 sts->MPI_COMM = comm;
4465 sts->MPI_CANCEL = 0;
4470 int IATAReq::wait(MPI_Status *sts){
4472 for(i=0;i<elmcount;i++){
4473 if(-1==getAmpiInstance(myreqs[i].comm)->recv(myreqs[i].tag, myreqs[i].src, myreqs[i].buf,
4474 myreqs[i].count, myreqs[i].type,
4475 myreqs[i].comm, sts))
4476 CkAbort("AMPI> Error in ialltoall request wait");
4477 #if CMK_BIGSIM_CHARM
4478 _TRACE_BG_TLINE_END(&myreqs[i].event);
4481 #if CMK_BIGSIM_CHARM
4482 TRACE_BG_AMPI_BREAK(getAmpiInstance(MPI_COMM_WORLD)->getThread(), "IATAReq_wait", NULL, 0, 1);
4483 for (i=0; i<elmcount; i++)
4484 _TRACE_BG_ADD_BACKWARD_DEP(myreqs[i].event);
4485 _TRACE_BG_TLINE_END(&event);
4491 int AMPI_Wait(MPI_Request *request, MPI_Status *sts)
4493 AMPIAPI("AMPI_Wait");
4495 MPI_Status tempStatus;
4496 if(!sts) sts = &tempStatus;
4498 if(*request == MPI_REQUEST_NULL){
4502 checkRequest(*request);
4503 AmpiRequestList* reqs = getReqs();
4506 ampiParent* pptr = getAmpiParent();
4508 (*(pptr->fromPUPer))|(pptr->pupBytes);
4509 PUParray(*(pptr->fromPUPer), (char *)((*reqs)[*request]->buf), (pptr->pupBytes));
4510 PUParray(*(pptr->fromPUPer), (char *)sts, sizeof(MPI_Status));
4515 #if CMK_BIGSIM_CHARM
4516 void *curLog; // store current log in timeline
4517 _TRACE_BG_TLINE_END(&curLog);
4520 AMPI_DEBUG("AMPI_Wait request=%d (*reqs)[*request]=%p (*reqs)[*request]->tag=%d\n",
4521 *request, (*reqs)[*request], (int)((*reqs)[*request]->tag));
4522 AMPI_DEBUG("MPI_Wait: request=%d, reqs.size=%d, &reqs=%d\n",
4523 *request, reqs->size(), reqs);
4524 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4525 int waitResult = -1;
4527 AmpiRequest& waitReq = *(*reqs)[*request];
4528 waitResult = waitReq.wait(sts);
4529 #if CMK_BIGSIM_CHARM
4530 if(_BgInOutOfCoreMode){
4534 }while(waitResult==-1);
4536 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4537 AMPI_DEBUG("AMPI_Wait after calling wait, request=%d (*reqs)[*request]=%p (*reqs)[*request]->tag=%d\n",
4538 *request, (*reqs)[*request], (int)((*reqs)[*request]->tag));
4541 if(msgLogWrite && record_msglog(pptr->thisIndex)){
4542 (pptr->pupBytes) = getDDT()->getSize((*reqs)[*request]->type) * ((*reqs)[*request]->count);
4543 (*(pptr->toPUPer))|(pptr->pupBytes);
4544 PUParray(*(pptr->toPUPer), (char *)((*reqs)[*request]->buf), (pptr->pupBytes));
4545 PUParray(*(pptr->toPUPer), (char *)sts, sizeof(MPI_Status));
4549 #if CMK_BIGSIM_CHARM
4550 TRACE_BG_AMPI_WAIT(reqs); // setup forward and backward dependence
4553 freeNonPersReq(*request);
4555 AMPI_DEBUG("End of AMPI_Wait\n");
4561 int AMPI_Waitall(int count, MPI_Request request[], MPI_Status sts[])
4563 AMPIAPI("AMPI_Waitall");
4565 checkRequests(count, request);
4566 if (count == 0) return MPI_SUCCESS;
4568 AmpiRequestList* reqs = getReqs();
4569 ampiParent* pptr = getAmpiParent();
4570 CkAssert(pptr->numBlockedReqs == 0);
4574 for(int i=0;i<count;i++){
4575 if(request[i] == MPI_REQUEST_NULL){
4579 AmpiRequest *waitReq = (*reqs)[request[i]];
4580 (*(pptr->fromPUPer))|(pptr->pupBytes);
4581 PUParray(*(pptr->fromPUPer), (char *)(waitReq->buf), pptr->pupBytes);
4582 PUParray(*(pptr->fromPUPer), (char *)(&sts[i]), sizeof(MPI_Status));
4587 #if CMK_BIGSIM_CHARM
4588 void *curLog; // store current log in timeline
4589 _TRACE_BG_TLINE_END(&curLog);
4592 MPI_Status tmpStatus;
4594 // First check for any incomplete requests
4595 for (int i=0; i<count; i++) {
4596 if (request[i] == MPI_REQUEST_NULL) {
4601 AmpiRequest& req = *(*reqs)[request[i]];
4602 if (req.itest(sts ? &sts[i] : &tmpStatus)) {
4603 req.complete(sts ? &sts[i] : &tmpStatus);
4604 req.setBlocked(false);
4606 if(msgLogWrite && record_msglog(pptr->thisIndex)){
4607 (pptr->pupBytes) = getDDT()->getSize(req.type) * req.count;
4608 (*(pptr->toPUPer))|(pptr->pupBytes);
4609 PUParray(*(pptr->toPUPer), (char *)(req.buf), pptr->pupBytes);
4610 PUParray(*(pptr->toPUPer), (char *)(&sts[i]), sizeof(MPI_Status));
4613 freeNonPersReq(request[i]);
4616 req.setBlocked(true);
4617 pptr->numBlockedReqs++;
4621 // If any requests are incomplete, block until all have been completed
4622 if (pptr->numBlockedReqs > 0) {
4623 getAmpiParent()->blockOnRecv();
4624 reqs = getReqs(); //update pointer in case of migration while suspended
4625 pptr = getAmpiParent();
4627 for (int i=0; i<count; i++) {
4628 if (request[i] == MPI_REQUEST_NULL) {
4631 AmpiRequest& req = *(*reqs)[request[i]];
4632 #if CMK_ERROR_CHECKING
4633 if (!req.itest(sts ? &sts[i] : &tmpStatus))
4634 CkAbort("In AMPI_Waitall, all requests should have completed by now!");
4636 req.complete(sts ? &sts[i] : &tmpStatus);
4637 req.setBlocked(false);
4639 if(msgLogWrite && record_msglog(pptr->thisIndex)){
4640 (pptr->pupBytes) = getDDT()->getSize(req.type) * req.count;
4641 (*(pptr->toPUPer))|(pptr->pupBytes);
4642 PUParray(*(pptr->toPUPer), (char *)(req.buf), pptr->pupBytes);
4643 PUParray(*(pptr->toPUPer), (char *)(&sts[i]), sizeof(MPI_Status));
4646 freeNonPersReq(request[i]);
4650 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4652 #if CMK_BIGSIM_CHARM
4653 TRACE_BG_AMPI_WAITALL(reqs); // setup forward and backward dependence
4660 int AMPI_Waitany(int count, MPI_Request *request, int *idx, MPI_Status *sts)
4662 AMPIAPI("AMPI_Waitany");
4664 checkRequests(count, request);
4666 *idx = MPI_UNDEFINED;
4670 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4672 AmpiRequestList* reqs = getReqs();
4673 MPI_Status tmpStatus;
4674 if (!sts) sts = &tmpStatus;
4677 // First check for an already complete request
4678 for (int i=0; i<count; i++) {
4679 if (request[i] == MPI_REQUEST_NULL) {
4683 AmpiRequest& req = *(*reqs)[request[i]];
4684 if (req.itest(sts)) {
4686 reqs->unblockReqs(&request[0], i);
4687 freeNonPersReq(request[i]);
4689 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4693 req.setBlocked(true);
4697 if (nullReqs == count) {
4699 *idx = MPI_UNDEFINED;
4700 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4703 else { // block until one of the requests is completed
4704 getAmpiParent()->numBlockedReqs = 1;
4705 getAmpiParent()->blockOnRecv();
4706 reqs = getReqs(); // update pointer in case of migration while suspended
4708 for (int i=0; i<count; i++) {
4709 if (request[i] == MPI_REQUEST_NULL) {
4712 AmpiRequest& req = *(*reqs)[request[i]];
4713 if (req.itest(sts)) {
4715 reqs->unblockReqs(&request[i], count-i);
4716 freeNonPersReq(request[i]);
4718 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4722 req.setBlocked(false);
4725 #if CMK_ERROR_CHECKING
4726 CkAbort("In AMPI_Waitany, a request should have completed by now!");
4733 int AMPI_Waitsome(int incount, MPI_Request *array_of_requests, int *outcount,
4734 int *array_of_indices, MPI_Status *array_of_statuses)
4736 AMPIAPI("AMPI_Waitsome");
4738 checkRequests(incount, array_of_requests);
4740 *outcount = MPI_UNDEFINED;
4744 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4746 AmpiRequestList* reqs = getReqs();
4751 for (int i=0; i<incount; i++) {
4752 if (array_of_requests[i] == MPI_REQUEST_NULL) {
4753 if (array_of_statuses)
4754 stsempty(array_of_statuses[i]);
4758 AmpiRequest& req = *(*reqs)[array_of_requests[i]];
4759 if (req.itest(&sts)) {
4761 array_of_indices[(*outcount)] = i;
4763 if (array_of_statuses)
4764 array_of_statuses[(*outcount)] = sts;
4765 freeNonPersReq(array_of_requests[i]);
4768 req.setBlocked(true);
4772 if (*outcount > 0) {
4773 reqs->unblockReqs(&array_of_requests[0], incount);
4774 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4777 else if (nullReqs == incount) {
4778 *outcount = MPI_UNDEFINED;
4779 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4782 else { // block until one of the requests is completed
4783 getAmpiParent()->numBlockedReqs = 1;
4784 getAmpiParent()->blockOnRecv();
4785 reqs = getReqs(); // update pointer in case of migration while suspended
4787 for (int i=0; i<incount; i++) {
4788 if (array_of_requests[i] == MPI_REQUEST_NULL) {
4791 AmpiRequest& req = *(*reqs)[array_of_requests[i]];
4792 if (req.itest(&sts)) {
4794 array_of_indices[(*outcount)] = i;
4796 if (array_of_statuses)
4797 array_of_statuses[(*outcount)] = sts;
4798 reqs->unblockReqs(&array_of_requests[i], incount-i);
4799 freeNonPersReq(array_of_requests[i]);
4800 CkAssert(getAmpiParent()->numBlockedReqs == 0);
4804 req.setBlocked(false);
4807 #if CMK_ERROR_CHECKING
4808 CkAbort("In AMPI_Waitsome, a request should have completed by now!");
4814 bool PersReq::test(MPI_Status *sts){
4815 if(sndrcv == 2) // recv request
4816 return getAmpiInstance(comm)->iprobe(tag, src, comm, sts);
4817 else // send request
4821 bool PersReq::itest(MPI_Status *sts){
4825 bool IReq::test(MPI_Status *sts){
4828 sts->MPI_CANCEL = 1;
4831 else if (statusIreq) {
4832 sts->MPI_SOURCE = src;
4834 sts->MPI_COMM = comm;
4835 sts->MPI_LENGTH = length;
4836 sts->MPI_CANCEL = 0;
4839 getAmpiParent()->yield();
4847 getAmpiParent()->yield();
4853 bool IReq::itest(MPI_Status *sts){
4856 sts->MPI_CANCEL = 1;
4859 else if (statusIreq) {
4860 sts->MPI_SOURCE = src;
4862 sts->MPI_COMM = comm;
4863 sts->MPI_LENGTH = length;
4864 sts->MPI_CANCEL = 0;
4867 else if (cancelled) {
4873 bool RednReq::test(MPI_Status *sts){
4875 getAmpiParent()->yield();
4880 bool RednReq::itest(MPI_Status *sts){
4884 bool GatherReq::test(MPI_Status *sts){
4886 getAmpiParent()->yield();
4891 bool GatherReq::itest(MPI_Status *sts){
4895 bool GathervReq::test(MPI_Status *sts){
4897 getAmpiParent()->yield();
4902 bool GathervReq::itest(MPI_Status *sts){
4906 bool SendReq::test(MPI_Status *sts){
4908 getAmpiParent()->yield();
4913 bool SendReq::itest(MPI_Status *sts){
4917 bool SsendReq::test(MPI_Status *sts){
4919 getAmpiParent()->yield();
4924 bool SsendReq::itest(MPI_Status *sts){
4928 bool IATAReq::test(MPI_Status *sts){
4929 for(int i=0;i<elmcount;i++){
4930 if(false==myreqs[i].itest(sts)){
4931 getAmpiParent()->yield();
4938 bool IATAReq::itest(MPI_Status *sts){
4939 for(int i=0;i<elmcount;i++){
4940 if(false==myreqs[i].itest(sts))
4946 void PersReq::complete(MPI_Status *sts){
4947 if(-1==getAmpiInstance(comm)->recv(tag, src, buf, count, type, comm, sts))
4948 CkAbort("AMPI> Error in persistent request complete");
4951 void IReq::complete(MPI_Status *sts){
4955 void RednReq::complete(MPI_Status *sts){
4959 void GatherReq::complete(MPI_Status *sts){
4963 void GathervReq::complete(MPI_Status *sts){
4967 void SendReq::complete(MPI_Status *sts){
4971 void SsendReq::complete(MPI_Status *sts){
4975 void IATAReq::complete(MPI_Status *sts){
4976 for(int i=0;i<elmcount;i++){
4977 if(-1==getAmpiInstance(myreqs[i].comm)->recv(myreqs[i].tag, myreqs[i].src, myreqs[i].buf,
4978 myreqs[i].count, myreqs[i].type,
4979 myreqs[i].comm, sts))
4980 CkAbort("AMPI> Error in ialltoall request complete");
4984 void IReq::receive(ampi *ptr, AmpiMsg *msg)
4986 ptr->processAmpiMsg(msg, buf, type, count);
4988 length = msg->getLength();
4989 this->tag = msg->getTag(); // Although not required, we also extract tag from msg
4990 src = msg->getSrcRank(); // Although not required, we also extract src from msg
4991 comm = msg->getComm(ptr->getComm());
4992 AMPI_DEBUG("Setting this->tag to %d in IReq::receive this=%p\n", tag, this);
4993 #if CMK_BIGSIM_CHARM
4995 eventPe = msg->eventPe;
5000 void RednReq::receive(ampi *ptr, CkReductionMsg *msg)
5002 if (ptr->opIsCommutative(op)) {
5003 ptr->processRednMsg(msg, buf, type, count);
5005 MPI_User_function* func = ptr->op2User_function(op);
5006 ptr->processNoncommutativeRednMsg(msg, buf, type, count, func);
5009 comm = ptr->getComm();
5010 #if CMK_BIGSIM_CHARM
5012 eventPe = msg->eventPe;
5014 // ampi::rednResult is a [nokeep] entry method, so do not delete msg
5017 void GatherReq::receive(ampi *ptr, CkReductionMsg *msg)
5019 ptr->processGatherMsg(msg, buf, type, count);
5021 comm = ptr->getComm();
5022 #if CMK_BIGSIM_CHARM
5024 eventPe = msg->eventPe;
5026 // ampi::rednResult is a [nokeep] entry method, so do not delete msg
5029 void GathervReq::receive(ampi *ptr, CkReductionMsg *msg)
5031 ptr->processGathervMsg(msg, buf, type, &recvCounts[0], &displs[0]);
5033 comm = ptr->getComm();
5034 #if CMK_BIGSIM_CHARM
5036 eventPe = msg->eventPe;
5038 // ampi::rednResult is a [nokeep] entry method, so do not delete msg
5042 int AMPI_Request_get_status(MPI_Request request, int *flag, MPI_Status *sts)
5044 AMPIAPI("AMPI_Request_get_status");
5045 testRequestNoFree(&request, flag, sts);
5047 getAmpiParent()->yield();
5052 int AMPI_Test(MPI_Request *request, int *flag, MPI_Status *sts)
5054 AMPIAPI("AMPI_Test");
5055 testRequest(request, flag, sts);
5057 getAmpiParent()->yield();
5062 int AMPI_Testany(int count, MPI_Request *request, int *index, int *flag, MPI_Status *sts){
5063 AMPIAPI("AMPI_Testany");
5065 checkRequests(count, request);
5067 MPI_Status tempStatus;
5068 if (!sts) sts = &tempStatus;
5072 *index = MPI_UNDEFINED;
5080 for (int i=0; i<count; i++) {
5081 if (request[i] == MPI_REQUEST_NULL) {
5085 testRequest(&request[i], flag, sts);
5092 *index = MPI_UNDEFINED;
5093 if (nullReqs == count) {
5098 getAmpiParent()->yield();
5105 int AMPI_Testall(int count, MPI_Request *request, int *flag, MPI_Status *sts)
5107 AMPIAPI("AMPI_Testall");
5109 checkRequests(count, request);
5115 AmpiRequestList* reqs = getReqs();
5116 MPI_Status tmpStatus;
5120 for (int i=0; i<count; i++) {
5121 if (request[i] == MPI_REQUEST_NULL) {
5127 if (!(*reqs)[request[i]]->itest(&tmpStatus)) {
5129 getAmpiParent()->yield();
5134 if (nullReqs != count) {
5135 for (int i=0; i<count; i++) {
5136 int reqIdx = request[i];
5137 if (reqIdx != MPI_REQUEST_NULL) {
5138 AmpiRequest& req = *(*reqs)[reqIdx];
5139 req.complete(sts ? &sts[i] : &tmpStatus);
5140 freeNonPersReq(request[i]);
5149 int AMPI_Testsome(int incount, MPI_Request *array_of_requests, int *outcount,
5150 int *array_of_indices, MPI_Status *array_of_statuses)
5152 AMPIAPI("AMPI_Testsome");
5154 checkRequests(incount, array_of_requests);
5156 *outcount = MPI_UNDEFINED;
5161 int flag = 0, nullReqs = 0;
5164 for (int i=0; i<incount; i++) {
5165 if (array_of_requests[i] == MPI_REQUEST_NULL) {
5166 if (array_of_statuses)
5167 stsempty(array_of_statuses[i]);
5171 testRequest(&array_of_requests[i], &flag, &sts);
5173 array_of_indices[(*outcount)] = i;
5175 if (array_of_statuses)
5176 array_of_statuses[(*outcount)] = sts;
5180 if (nullReqs == incount) {
5181 *outcount = MPI_UNDEFINED;
5183 else if (*outcount == 0) {
5184 getAmpiParent()->yield();
5191 int AMPI_Request_free(MPI_Request *request){
5192 AMPIAPI("AMPI_Request_free");
5193 if(*request==MPI_REQUEST_NULL) return MPI_SUCCESS;
5194 checkRequest(*request);
5195 AmpiRequestList* reqs = getReqs();
5196 reqs->free(*request);
5197 *request = MPI_REQUEST_NULL;
5202 int AMPI_Cancel(MPI_Request *request){
5203 AMPIAPI("AMPI_Cancel");
5204 if(*request == MPI_REQUEST_NULL) return MPI_SUCCESS;
5205 checkRequest(*request);
5206 AmpiRequestList* reqs = getReqs();
5207 AmpiRequest& req = *(*reqs)[*request];
5208 if(req.getType() == MPI_I_REQ) {
5213 return ampiErrhandler("AMPI_Cancel", MPI_ERR_REQUEST);
5218 int AMPI_Test_cancelled(MPI_Status* status, int* flag) {
5219 AMPIAPI("AMPI_Test_cancelled");
5220 // NOTE : current implementation requires AMPI_{Wait,Test}{any,some,all}
5221 // to be invoked before AMPI_Test_cancelled
5222 *flag = status->MPI_CANCEL;
5227 int AMPI_Status_set_cancelled(MPI_Status *status, int flag){
5228 AMPIAPI("AMPI_Status_set_cancelled");
5229 status->MPI_CANCEL = flag;
5234 int AMPI_Recv_init(void *buf, int count, MPI_Datatype type, int src, int tag,
5235 MPI_Comm comm, MPI_Request *req)
5237 AMPIAPI("AMPI_Recv_init");
5239 handle_MPI_BOTTOM(buf, type);
5241 #if AMPI_ERROR_CHECKING
5242 int ret = errorCheck("AMPI_Recv_init", comm, 1, count, 1, type, 1, tag, 1, src, 1, buf, 1);
5243 if(ret != MPI_SUCCESS){
5244 *req = MPI_REQUEST_NULL;
5249 *req = getAmpiInstance(comm)->postReq(new PersReq(buf,count,type,src,tag,comm,2));
5254 int AMPI_Send_init(void *buf, int count, MPI_Datatype type, int dest, int tag,
5255 MPI_Comm comm, MPI_Request *req)
5257 AMPIAPI("AMPI_Send_init");
5259 handle_MPI_BOTTOM(buf, type);
5261 #if AMPI_ERROR_CHECKING
5262 int ret = errorCheck("AMPI_Send_init", comm, 1, count, 1, type, 1, tag, 1, dest, 1, buf, 1);
5263 if(ret != MPI_SUCCESS){
5264 *req = MPI_REQUEST_NULL;
5269 *req = getAmpiInstance(comm)->postReq(new PersReq(buf,count,type,dest,tag,comm,1));
5274 int AMPI_Ssend_init(void *buf, int count, MPI_Datatype type, int dest, int tag,
5275 MPI_Comm comm, MPI_Request *req)
5277 AMPIAPI("AMPI_Ssend_init");
5279 handle_MPI_BOTTOM(buf, type);
5281 #if AMPI_ERROR_CHECKING
5282 int ret = errorCheck("AMPI_Ssend_init", comm, 1, count, 1, type, 1, tag, 1, dest, 1, buf, 1);
5283 if(ret != MPI_SUCCESS){
5284 *req = MPI_REQUEST_NULL;
5289 *req = getAmpiInstance(comm)->postReq(new PersReq(buf,count,type,dest,tag,comm,3));
5294 int AMPI_Type_contiguous(int count, MPI_Datatype oldtype,
5295 MPI_Datatype *newtype)
5297 AMPIAPI("AMPI_Type_contiguous");
5298 getDDT()->newContiguous(count, oldtype, newtype);
5303 int AMPI_Type_vector(int count, int blocklength, int stride,
5304 MPI_Datatype oldtype, MPI_Datatype* newtype)
5306 AMPIAPI("AMPI_Type_vector");
5307 getDDT()->newVector(count, blocklength, stride, oldtype, newtype);
5312 int AMPI_Type_create_hvector(int count, int blocklength, MPI_Aint stride,
5313 MPI_Datatype oldtype, MPI_Datatype* newtype)
5315 AMPIAPI("AMPI_Type_create_hvector");
5316 getDDT()->newHVector(count, blocklength, stride, oldtype, newtype);
5321 int AMPI_Type_hvector(int count, int blocklength, MPI_Aint stride,
5322 MPI_Datatype oldtype, MPI_Datatype* newtype)
5324 AMPIAPI("AMPI_Type_hvector");
5325 return AMPI_Type_create_hvector(count, blocklength, stride, oldtype, newtype);
5329 int AMPI_Type_indexed(int count, int* arrBlength, int* arrDisp,
5330 MPI_Datatype oldtype, MPI_Datatype* newtype)
5332 AMPIAPI("AMPI_Type_indexed");
5333 /*CkDDT_Indexed's arrDisp has type MPI_Aint* (not int*). */
5334 vector<MPI_Aint> arrDispAint(count);
5335 for(int i=0; i<count; i++)
5336 arrDispAint[i] = (MPI_Aint)(arrDisp[i]);
5337 getDDT()->newIndexed(count, arrBlength, &arrDispAint[0], oldtype, newtype);
5342 int AMPI_Type_create_hindexed(int count, int* arrBlength, MPI_Aint* arrDisp,
5343 MPI_Datatype oldtype, MPI_Datatype* newtype)
5345 AMPIAPI("AMPI_Type_create_hindexed");
5346 getDDT()->newHIndexed(count, arrBlength, arrDisp, oldtype, newtype);
5351 int AMPI_Type_hindexed(int count, int* arrBlength, MPI_Aint* arrDisp,
5352 MPI_Datatype oldtype, MPI_Datatype* newtype)
5354 AMPIAPI("AMPI_Type_hindexed");
5355 return AMPI_Type_create_hindexed(count, arrBlength, arrDisp, oldtype, newtype);
5359 int AMPI_Type_create_indexed_block(int count, int Blength, MPI_Aint *arr,
5360 MPI_Datatype oldtype, MPI_Datatype *newtype)
5362 AMPIAPI("AMPI_Type_create_indexed_block");
5363 getDDT()->newIndexedBlock(count,Blength, arr, oldtype, newtype);
5368 int AMPI_Type_create_hindexed_block(int count, int Blength, MPI_Aint *arr,
5369 MPI_Datatype oldtype, MPI_Datatype *newtype)
5371 AMPIAPI("AMPI_Type_create_hindexed_block");
5372 getDDT()->newHIndexedBlock(count,Blength, arr, oldtype, newtype);
5377 int AMPI_Type_create_struct(int count, int* arrBlength, MPI_Aint* arrDisp,
5378 MPI_Datatype* oldtype, MPI_Datatype* newtype)
5380 AMPIAPI("AMPI_Type_create_struct");
5381 getDDT()->newStruct(count, arrBlength, arrDisp, oldtype, newtype);
5386 int AMPI_Type_struct(int count, int* arrBlength, MPI_Aint* arrDisp,
5387 MPI_Datatype* oldtype, MPI_Datatype* newtype)
5389 AMPIAPI("AMPI_Type_struct");
5390 return AMPI_Type_create_struct(count, arrBlength, arrDisp, oldtype, newtype);
5394 int AMPI_Type_commit(MPI_Datatype *datatype)
5396 AMPIAPI("AMPI_Type_commit");
5401 int AMPI_Type_free(MPI_Datatype *datatype)
5403 AMPIAPI("AMPI_Type_free");
5404 getDDT()->freeType(datatype);
5409 int AMPI_Type_get_extent(MPI_Datatype datatype, MPI_Aint *lb, MPI_Aint *extent)
5411 AMPIAPI("AMPI_Type_get_extent");
5412 *lb = getDDT()->getLB(datatype);
5413 *extent = getDDT()->getExtent(datatype);
5418 int AMPI_Type_extent(MPI_Datatype datatype, MPI_Aint *extent)
5420 AMPIAPI("AMPI_Type_extent");
5422 return AMPI_Type_get_extent(datatype, &tmpLB, extent);
5426 int AMPI_Type_get_true_extent(MPI_Datatype datatype, MPI_Aint *true_lb, MPI_Aint *true_extent)
5428 AMPIAPI("AMPI_Type_get_true_extent");
5429 *true_lb = getDDT()->getTrueLB(datatype);
5430 *true_extent = getDDT()->getTrueExtent(datatype);
5435 int AMPI_Type_size(MPI_Datatype datatype, int *size)
5437 AMPIAPI("AMPI_Type_size");
5438 *size=getDDT()->getSize(datatype);
5443 int AMPI_Type_set_name(MPI_Datatype datatype, const char *name)
5445 AMPIAPI("AMPI_Type_set_name");
5446 getDDT()->setName(datatype, name);
5451 int AMPI_Type_get_name(MPI_Datatype datatype, char *name, int *resultlen)
5453 AMPIAPI("AMPI_Type_get_name");
5454 getDDT()->getName(datatype, name, resultlen);
5459 int AMPI_Type_create_resized(MPI_Datatype oldtype, MPI_Aint lb, MPI_Aint extent, MPI_Datatype *newtype)
5461 AMPIAPI("AMPI_Type_create_resized");
5462 getDDT()->createResized(oldtype, lb, extent, newtype);
5467 int AMPI_Type_dup(MPI_Datatype oldtype, MPI_Datatype *newtype)
5469 AMPIAPI("AMPI_Type_dup");
5470 getDDT()->createDup(oldtype, newtype);
5474 int AMPI_Type_set_attr(MPI_Datatype datatype, int type_keyval, void *attribute_val)
5476 AMPIAPI("AMPI_Type_set_attr");
5477 /* no-op implementation */
5482 int AMPI_Type_get_attr(MPI_Datatype datatype, int type_keyval, void *attribute_val, int *flag)
5484 AMPIAPI("AMPI_Type_get_attr");
5485 /* no-op implementation */
5490 int AMPI_Type_delete_attr(MPI_Datatype datatype, int type_keyval)
5492 AMPIAPI("AMPI_Type_delete_attr");
5493 /* no-op implementation */
5498 int AMPI_Type_create_keyval(MPI_Type_copy_attr_function *type_copy_attr_fn,
5499 MPI_Type_delete_attr_function *type_delete_attr_fn,
5500 int *type_keyval, void *extra_state)
5502 AMPIAPI("AMPI_Type_create_keyval");
5503 /* no-op implementation */
5508 int AMPI_Type_free_keyval(int *type_keyval)
5510 AMPIAPI("AMPI_Type_free_keyval");
5511 /* no-op implementation */
5516 int AMPI_Isend(void *buf, int count, MPI_Datatype type, int dest,
5517 int tag, MPI_Comm comm, MPI_Request *request)
5519 AMPIAPI("AMPI_Isend");
5521 handle_MPI_BOTTOM(buf, type);
5523 #if AMPI_ERROR_CHECKING
5524 int ret = errorCheck("AMPI_Isend", comm, 1, count, 1, type, 1, tag, 1, dest, 1, buf, 1);
5525 if(ret != MPI_SUCCESS){
5526 *request = MPI_REQUEST_NULL;
5532 ampiParent* pptr = getAmpiParent();
5534 PUParray(*(pptr->fromPUPer), (char *)request, sizeof(MPI_Request));
5539 USER_CALL_DEBUG("AMPI_Isend("<<type<<","<<dest<<","<<tag<<","<<comm<<")");
5540 ampi *ptr = getAmpiInstance(comm);
5541 ptr->send(tag, ptr->getRank(comm), buf, count, type, dest, comm);
5542 *request = ptr->postReq(new SendReq(comm, AMPI_REQ_COMPLETED));
5545 if(msgLogWrite && record_msglog(pptr->thisIndex)){
5546 PUParray(*(pptr->toPUPer), (char *)request, sizeof(MPI_Request));
5553 void ampi::irecv(void *buf, int count, MPI_Datatype type, int src,
5554 int tag, MPI_Comm comm, MPI_Request *request)
5556 if (src==MPI_PROC_NULL) {
5557 *request = MPI_REQUEST_NULL;
5560 AmpiRequestList* reqs = getReqs();
5561 IReq *newreq = new IReq(buf, count, type, src, tag, comm);
5562 *request = reqs->insert(newreq);
5565 ampiParent* pptr = getAmpiParent();
5567 PUParray(*(pptr->fromPUPer), (char *)request, sizeof(MPI_Request));
5572 AmpiMsg *msg = NULL;
5573 msg = getMessage(tag, src, comm, &newreq->tag);
5574 // if msg has already arrived, do the receive right away
5576 newreq->receive(this, msg);
5578 // ... otherwise post the receive
5580 int tags[2] = { tag, src };
5582 //just insert the index of the newreq in the ampiParent::ampiReqs
5583 //to posted_ireqs. Such change is due to the need for Out-of-core Emulation
5584 //in BigSim. Before this change, posted_ireqs and ampiReqs both hold pointers to
5585 //AmpiRequest instances. After going through the Pupping routines, both will have
5586 //pointers to different AmpiRequest instances and no longer refer to the same AmpiRequest
5587 //instance. Therefore, to keep both always accessing the same AmpiRequest instance,
5588 //posted_ireqs stores the index (an integer) to ampiReqs.
5589 //The index is 1-based rather 0-based because when pulling entries from posted_ireqs,
5590 //if not found, a "0" (i.e. NULL) is returned, this confuses the indexing of ampiReqs.
5591 AmmPut(posted_ireqs, tags, (void *)(CmiIntPtr)((*request)+1));
5595 if(msgLogWrite && record_msglog(pptr->thisIndex)){
5596 PUParray(*(pptr->toPUPer), (char *)request, sizeof(MPI_Request));
5602 int AMPI_Irecv(void *buf, int count, MPI_Datatype type, int src,
5603 int tag, MPI_Comm comm, MPI_Request *request)
5605 AMPIAPI("AMPI_Irecv");
5607 handle_MPI_BOTTOM(buf, type);
5609 #if AMPI_ERROR_CHECKING
5610 int ret = errorCheck("AMPI_Irecv", comm, 1, count, 1, type, 1, tag, 1, src, 1, buf, 1);
5611 if(ret != MPI_SUCCESS){
5612 *request = MPI_REQUEST_NULL;
5617 USER_CALL_DEBUG("AMPI_Irecv("<<type<<","<<src<<","<<tag<<","<<comm<<")");
5618 ampi *ptr = getAmpiInstance(comm);
5620 ptr->irecv(buf, count, type, src, tag, comm, request);
5626 int AMPI_Ireduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype type, MPI_Op op,
5627 int root, MPI_Comm comm, MPI_Request *request)
5629 AMPIAPI("AMPI_Ireduce");
5631 handle_MPI_BOTTOM(sendbuf, type, recvbuf, type);
5632 handle_MPI_IN_PLACE(sendbuf, recvbuf);
5634 #if AMPI_ERROR_CHECKING
5635 if(op == MPI_OP_NULL)
5636 return ampiErrhandler("AMPI_Ireduce", MPI_ERR_OP);
5637 int ret = errorCheck("AMPI_Ireduce", comm, 1, count, 1, type, 1, 0, 0, root, 1, sendbuf, 1,
5638 recvbuf, getAmpiInstance(comm)->getRank(comm) == root);
5639 if(ret != MPI_SUCCESS){
5640 *request = MPI_REQUEST_NULL;
5645 ampi *ptr = getAmpiInstance(comm);
5647 if(comm==MPI_COMM_SELF){
5648 *request = ptr->postReq(new RednReq(recvbuf, count, type, comm, op, AMPI_REQ_COMPLETED));
5649 return copyDatatype(comm,type,count,sendbuf,recvbuf);
5651 if(getAmpiParent()->isInter(comm))
5652 CkAbort("AMPI does not implement MPI_Ireduce for Inter-communicators!");
5654 CkReductionMsg *msg=makeRednMsg(ptr->getDDT()->getType(type),sendbuf,count,type,ptr->getRank(comm),op);
5655 int rootIdx=ptr->comm2CommStruct(comm).getIndexForRank(root);
5657 CkCallback reduceCB(CkIndex_ampi::irednResult(0),CkArrayIndex1D(rootIdx),ptr->getProxy());
5658 msg->setCallback(reduceCB);
5659 ptr->contribute(msg);
5661 if (ptr->thisIndex == rootIdx){
5662 // use a RednReq to non-block the caller and get a request ptr
5663 *request = ptr->postReq(new RednReq(recvbuf,count,type,comm,op));
5669 static CkReductionMsg *makeGatherMsg(const void *inbuf, int count, MPI_Datatype type, int rank)
5671 CkDDT_DataType* ddt = getDDT()->getType(type);
5672 int szdata = ddt->getSize(count);
5673 const int tupleSize = 2;
5674 CkReduction::tupleElement tupleRedn[tupleSize];
5675 tupleRedn[0] = CkReduction::tupleElement(sizeof(int), &rank, CkReduction::set);
5677 if (ddt->isContig()) {
5678 tupleRedn[1] = CkReduction::tupleElement(szdata, (void*)inbuf, CkReduction::set);
5680 vector<char> sbuf(szdata);
5681 ddt->serialize((char*)inbuf, &sbuf[0], count, 1);
5682 tupleRedn[1] = CkReduction::tupleElement(szdata, &sbuf[0], CkReduction::set);
5685 return CkReductionMsg::buildFromTuple(tupleRedn, tupleSize);
5689 int AMPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
5690 void *recvbuf, int recvcount, MPI_Datatype recvtype,
5693 AMPIAPI("AMPI_Allgather");
5695 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
5696 handle_MPI_IN_PLACE(sendbuf,recvbuf);
5698 #if AMPI_ERROR_CHECKING
5700 ret = errorCheck("AMPI_Allgather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
5701 if(ret != MPI_SUCCESS)
5703 ret = errorCheck("AMPI_Allgather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
5704 if(ret != MPI_SUCCESS)
5708 if(comm==MPI_COMM_SELF)
5709 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
5710 if(getAmpiParent()->isInter(comm))
5711 CkAbort("AMPI does not implement MPI_Allgather for Inter-communicators!");
5713 ampi *ptr = getAmpiInstance(comm);
5714 int rank = ptr->getRank(comm);
5715 int sendSize = ptr->getDDT()->getType(sendtype)->getSize(sendcount);
5717 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
5718 CkCallback allgatherCB(CkIndex_ampi::rednResult(0), ptr->getProxy());
5719 msg->setCallback(allgatherCB);
5720 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Allgather called on comm %d\n", ptr->thisIndex, comm));
5721 ptr->contribute(msg);
5723 ptr->blockOnRedn(new GatherReq(recvbuf, recvcount, recvtype, comm));
5729 int AMPI_Iallgather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
5730 void *recvbuf, int recvcount, MPI_Datatype recvtype,
5731 MPI_Comm comm, MPI_Request* request)
5733 AMPIAPI("AMPI_Iallgather");
5735 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
5736 handle_MPI_IN_PLACE(sendbuf,recvbuf);
5738 #if AMPI_ERROR_CHECKING
5740 ret = errorCheck("AMPI_Iallgather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
5741 if(ret != MPI_SUCCESS){
5742 *request = MPI_REQUEST_NULL;
5745 ret = errorCheck("AMPI_Iallgather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
5746 if(ret != MPI_SUCCESS){
5747 *request = MPI_REQUEST_NULL;
5752 ampi *ptr = getAmpiInstance(comm);
5754 if(comm==MPI_COMM_SELF){
5755 *request = ptr->postReq(new GatherReq(recvbuf, recvcount, recvtype, comm, AMPI_REQ_COMPLETED));
5756 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
5758 if(getAmpiParent()->isInter(comm))
5759 CkAbort("AMPI does not implement MPI_Iallgather for Inter-communicators!");
5761 int rank = ptr->getRank(comm);
5763 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
5764 CkCallback allgatherCB(CkIndex_ampi::irednResult(0), ptr->getProxy());
5765 msg->setCallback(allgatherCB);
5766 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Iallgather called on comm %d\n", ptr->thisIndex, comm));
5767 ptr->contribute(msg);
5769 // use a RednReq to non-block the caller and get a request ptr
5770 *request = ptr->postReq(new GatherReq(recvbuf, recvcount, recvtype, comm));
5776 int AMPI_Allgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
5777 void *recvbuf, int *recvcounts, int *displs,
5778 MPI_Datatype recvtype, MPI_Comm comm)
5780 AMPIAPI("AMPI_Allgatherv");
5782 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
5783 handle_MPI_IN_PLACE(sendbuf,recvbuf);
5785 #if AMPI_ERROR_CHECKING
5787 ret = errorCheck("AMPI_Allgatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
5788 if(ret != MPI_SUCCESS)
5790 ret = errorCheck("AMPI_Allgatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
5791 if(ret != MPI_SUCCESS)
5795 if(comm==MPI_COMM_SELF)
5796 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
5797 if(getAmpiParent()->isInter(comm))
5798 CkAbort("AMPI does not implement MPI_Allgatherv for Inter-communicators!");
5800 ampi *ptr = getAmpiInstance(comm);
5801 int rank = ptr->getRank(comm);
5803 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
5804 CkCallback allgathervCB(CkIndex_ampi::rednResult(0), ptr->getProxy());
5805 msg->setCallback(allgathervCB);
5806 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Allgatherv called on comm %d\n", ptr->thisIndex, comm));
5807 ptr->contribute(msg);
5809 ptr->blockOnRedn(new GathervReq(recvbuf, ptr->getSize(comm), recvtype, comm, recvcounts, displs));
5815 int AMPI_Iallgatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
5816 void *recvbuf, int *recvcounts, int *displs,
5817 MPI_Datatype recvtype, MPI_Comm comm, MPI_Request *request)
5819 AMPIAPI("AMPI_Iallgatherv");
5821 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
5822 handle_MPI_IN_PLACE(sendbuf,recvbuf);
5824 #if AMPI_ERROR_CHECKING
5826 ret = errorCheck("AMPI_Iallgatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
5827 if(ret != MPI_SUCCESS){
5828 *request = MPI_REQUEST_NULL;
5831 ret = errorCheck("AMPI_Iallgatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
5832 if(ret != MPI_SUCCESS){
5833 *request = MPI_REQUEST_NULL;
5838 ampi *ptr = getAmpiInstance(comm);
5839 int rank = ptr->getRank(comm);
5841 if(comm==MPI_COMM_SELF){
5842 *request = ptr->postReq(new GathervReq(recvbuf, rank, recvtype, comm, recvcounts, displs,
5843 AMPI_REQ_COMPLETED));
5844 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
5846 if(getAmpiParent()->isInter(comm))
5847 CkAbort("AMPI does not implement MPI_Iallgatherv for Inter-communicators!");
5849 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
5850 CkCallback allgathervCB(CkIndex_ampi::irednResult(0), ptr->getProxy());
5851 msg->setCallback(allgathervCB);
5852 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Iallgatherv called on comm %d\n", ptr->thisIndex, comm));
5853 ptr->contribute(msg);
5855 // use a GathervReq to non-block the caller and get a request ptr
5856 *request = ptr->postReq(new GathervReq(recvbuf, ptr->getSize(comm), recvtype,
5857 comm, recvcounts, displs));
5863 int AMPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
5864 void *recvbuf, int recvcount, MPI_Datatype recvtype,
5865 int root, MPI_Comm comm)
5867 AMPIAPI("AMPI_Gather");
5869 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
5870 handle_MPI_IN_PLACE(sendbuf,recvbuf);
5872 #if AMPI_ERROR_CHECKING
5874 ret = errorCheck("AMPI_Gather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
5875 if(ret != MPI_SUCCESS)
5877 if (getAmpiInstance(comm)->getRank(comm) == root) {
5878 ret = errorCheck("AMPI_Gather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
5879 if(ret != MPI_SUCCESS)
5884 if(comm==MPI_COMM_SELF)
5885 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
5886 if(getAmpiParent()->isInter(comm))
5887 CkAbort("AMPI does not implement MPI_Gather for Inter-communicators!");
5890 ampiParent* pptr = getAmpiParent();
5892 (*(pptr->fromPUPer))|(pptr->pupBytes);
5893 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
5898 ampi *ptr = getAmpiInstance(comm);
5899 int rootIdx = ptr->comm2CommStruct(comm).getIndexForRank(root);
5900 int rank = ptr->getRank(comm);
5902 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
5903 CkCallback gatherCB(CkIndex_ampi::rednResult(0), CkArrayIndex1D(rootIdx), ptr->getProxy());
5904 msg->setCallback(gatherCB);
5905 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Gather called on comm %d root %d \n", ptr->thisIndex, comm, rootIdx));
5906 ptr->contribute(msg);
5909 ptr->blockOnRedn(new GatherReq(recvbuf, recvcount, recvtype, comm));
5913 if(msgLogWrite && record_msglog(pptr->thisIndex)){
5914 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount * size;
5915 (*(pptr->toPUPer))|(pptr->pupBytes);
5916 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
5924 int AMPI_Igather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
5925 void *recvbuf, int recvcount, MPI_Datatype recvtype,
5926 int root, MPI_Comm comm, MPI_Request *request)
5928 AMPIAPI("AMPI_Igather");
5930 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
5931 handle_MPI_IN_PLACE(sendbuf,recvbuf);
5933 #if AMPI_ERROR_CHECKING
5935 ret = errorCheck("AMPI_Igather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
5936 if(ret != MPI_SUCCESS){
5937 *request = MPI_REQUEST_NULL;
5940 if (getAmpiInstance(comm)->getRank(comm) == root) {
5941 ret = errorCheck("AMPI_Igather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
5942 if(ret != MPI_SUCCESS){
5943 *request = MPI_REQUEST_NULL;
5949 ampi *ptr = getAmpiInstance(comm);
5951 if(comm==MPI_COMM_SELF){
5952 *request = ptr->postReq(new GatherReq(recvbuf, recvcount, recvtype, comm, AMPI_REQ_COMPLETED));
5953 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
5955 if(getAmpiParent()->isInter(comm))
5956 CkAbort("AMPI does not implement MPI_Igather for Inter-communicators!");
5959 ampiParent* pptr = getAmpiParent();
5961 (*(pptr->fromPUPer))|(pptr->pupBytes);
5962 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
5967 int rootIdx = ptr->comm2CommStruct(comm).getIndexForRank(root);
5968 int rank = ptr->getRank(comm);
5970 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
5971 CkCallback gatherCB(CkIndex_ampi::irednResult(0), CkArrayIndex1D(rootIdx), ptr->getProxy());
5972 msg->setCallback(gatherCB);
5973 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Igather called on comm %d root %d \n", ptr->thisIndex, comm, rootIdx));
5974 ptr->contribute(msg);
5977 // use a GatherReq to non-block the caller and get a request ptr
5978 *request = ptr->postReq(new GatherReq(recvbuf, recvcount, recvtype, comm));
5981 *request = MPI_REQUEST_NULL;
5985 if(msgLogWrite && record_msglog(pptr->thisIndex)){
5986 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount * size;
5987 (*(pptr->toPUPer))|(pptr->pupBytes);
5988 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
5996 int AMPI_Gatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
5997 void *recvbuf, int *recvcounts, int *displs,
5998 MPI_Datatype recvtype, int root, MPI_Comm comm)
6000 AMPIAPI("AMPI_Gatherv");
6002 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6003 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6005 #if AMPI_ERROR_CHECKING
6007 ret = errorCheck("AMPI_Gatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6008 if(ret != MPI_SUCCESS)
6010 if (getAmpiInstance(comm)->getRank(comm) == root) {
6011 ret = errorCheck("AMPI_Gatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6012 if(ret != MPI_SUCCESS)
6017 if(comm==MPI_COMM_SELF)
6018 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
6019 if(getAmpiParent()->isInter(comm))
6020 CkAbort("AMPI does not implement MPI_Gatherv for Inter-communicators!");
6023 ampiParent* pptr = getAmpiParent();
6026 int itemsize = getDDT()->getSize(recvtype);
6027 (*(pptr->fromPUPer))|commsize;
6028 for(int i=0;i<commsize;i++){
6029 (*(pptr->fromPUPer))|(pptr->pupBytes);
6030 PUParray(*(pptr->fromPUPer), (char *)(((char*)recvbuf)+(itemsize*displs[i])), (pptr->pupBytes));
6036 ampi *ptr = getAmpiInstance(comm);
6037 int rootIdx = ptr->comm2CommStruct(comm).getIndexForRank(root);
6038 int rank = ptr->getRank(comm);
6040 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6041 CkCallback gathervCB(CkIndex_ampi::rednResult(0), CkArrayIndex1D(rootIdx), ptr->getProxy());
6042 msg->setCallback(gathervCB);
6043 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Gatherv called on comm %d root %d \n", ptr->thisIndex, comm, rootIdx));
6044 ptr->contribute(msg);
6047 ptr->blockOnRedn(new GathervReq(recvbuf, ptr->getSize(comm), recvtype, comm, recvcounts, displs));
6051 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6052 for(int i=0;i<size;i++){
6053 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcounts[i];
6054 (*(pptr->toPUPer))|(pptr->pupBytes);
6055 PUParray(*(pptr->toPUPer), (char *)(((char*)recvbuf)+(itemsize*displs[i])), (pptr->pupBytes));
6064 int AMPI_Igatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype,
6065 void *recvbuf, int *recvcounts, int *displs,
6066 MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request *request)
6068 AMPIAPI("AMPI_Igatherv");
6070 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6071 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6073 #if AMPI_ERROR_CHECKING
6075 ret = errorCheck("AMPI_Igatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6076 if(ret != MPI_SUCCESS){
6077 *request = MPI_REQUEST_NULL;
6080 if (getAmpiInstance(comm)->getRank(comm) == root) {
6081 ret = errorCheck("AMPI_Igatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6082 if(ret != MPI_SUCCESS){
6083 *request = MPI_REQUEST_NULL;
6089 ampi *ptr = getAmpiInstance(comm);
6090 int rank = ptr->getRank(comm);
6092 if(comm==MPI_COMM_SELF){
6093 *request = ptr->postReq(new GathervReq(recvbuf, rank, recvtype, comm, recvcounts, displs,
6094 AMPI_REQ_COMPLETED));
6095 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
6097 if(getAmpiParent()->isInter(comm))
6098 CkAbort("AMPI does not implement MPI_Igatherv for Inter-communicators!");
6101 ampiParent* pptr = getAmpiParent();
6104 int itemsize = getDDT()->getSize(recvtype);
6105 (*(pptr->fromPUPer))|commsize;
6106 for(int i=0;i<commsize;i++){
6107 (*(pptr->fromPUPer))|(pptr->pupBytes);
6108 PUParray(*(pptr->fromPUPer), (char *)(((char*)recvbuf)+(itemsize*displs[i])), (pptr->pupBytes));
6114 int rootIdx = ptr->comm2CommStruct(comm).getIndexForRank(root);
6116 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6117 CkCallback gathervCB(CkIndex_ampi::irednResult(0), CkArrayIndex1D(rootIdx), ptr->getProxy());
6118 msg->setCallback(gathervCB);
6119 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Igatherv called on comm %d root %d \n", ptr->thisIndex, comm, rootIdx));
6120 ptr->contribute(msg);
6123 // use a GathervReq to non-block the caller and get a request ptr
6124 *request = ptr->postReq(new GathervReq(recvbuf, ptr->getSize(comm), recvtype,
6125 comm, recvcounts, displs));
6128 *request = MPI_REQUEST_NULL;
6132 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6133 for(int i=0;i<size;i++){
6134 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcounts[i];
6135 (*(pptr->toPUPer))|(pptr->pupBytes);
6136 PUParray(*(pptr->toPUPer), (char *)(((char*)recvbuf)+(itemsize*displs[i])), (pptr->pupBytes));
6145 int AMPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype,
6146 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6147 int root, MPI_Comm comm)
6149 AMPIAPI("AMPI_Scatter");
6151 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6152 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6154 #if AMPI_ERROR_CHECKING
6156 if (getAmpiInstance(comm)->getRank(comm) == root) {
6157 ret = errorCheck("AMPI_Scatter", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6158 if(ret != MPI_SUCCESS)
6161 ret = errorCheck("AMPI_Scatter", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6162 if(ret != MPI_SUCCESS)
6166 if(comm==MPI_COMM_SELF)
6167 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
6168 if(getAmpiParent()->isInter(comm))
6169 CkAbort("AMPI does not implement MPI_Scatter for Inter-communicators!");
6172 ampiParent* pptr = getAmpiParent();
6174 (*(pptr->fromPUPer))|(pptr->pupBytes);
6175 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6180 ampi *ptr = getAmpiInstance(comm);
6181 int size = ptr->getSize(comm);
6184 if(ptr->getRank(comm)==root) {
6185 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6186 int itemsize = dttype->getSize(sendcount) ;
6187 for(i=0;i<size;i++) {
6188 ptr->send(MPI_SCATTER_TAG, ptr->getRank(comm), ((char*)sendbuf)+(itemsize*i),
6189 sendcount, sendtype, i, comm);
6193 if(-1==ptr->recv(MPI_SCATTER_TAG, root, recvbuf, recvcount, recvtype, comm))
6194 CkAbort("AMPI> Error in MPI_Scatter recv");
6197 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6198 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount;
6199 (*(pptr->toPUPer))|(pptr->pupBytes);
6200 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
6208 int AMPI_Iscatter(void *sendbuf, int sendcount, MPI_Datatype sendtype,
6209 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6210 int root, MPI_Comm comm, MPI_Request *request)
6212 AMPIAPI("AMPI_Iscatter");
6214 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6215 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6217 #if AMPI_ERROR_CHECKING
6219 if (getAmpiInstance(comm)->getRank(comm) == root) {
6220 ret = errorCheck("AMPI_Iscatter", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6221 if(ret != MPI_SUCCESS){
6222 *request = MPI_REQUEST_NULL;
6226 ret = errorCheck("AMPI_Iscatter", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6227 if(ret != MPI_SUCCESS){
6228 *request = MPI_REQUEST_NULL;
6233 ampi *ptr = getAmpiInstance(comm);
6235 if(comm==MPI_COMM_SELF){
6236 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,
6237 AMPI_REQ_COMPLETED));
6238 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
6240 if(getAmpiParent()->isInter(comm))
6241 CkAbort("AMPI does not implement MPI_Iscatter for Inter-communicators!");
6244 ampiParent* pptr = getAmpiParent();
6246 (*(pptr->fromPUPer))|(pptr->pupBytes);
6247 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6252 int size = ptr->getSize(comm);
6255 if(ptr->getRank(comm)==root) {
6256 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6257 int itemsize = dttype->getSize(sendcount) ;
6258 for(i=0;i<size;i++) {
6259 ptr->send(MPI_SCATTER_TAG, ptr->getRank(comm), ((char*)sendbuf)+(itemsize*i),
6260 sendcount, sendtype, i, comm);
6264 // call irecv to post an IReq and process any pending messages
6265 ptr->irecv(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,request);
6268 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6269 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount;
6270 (*(pptr->toPUPer))|(pptr->pupBytes);
6271 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
6279 int AMPI_Scatterv(void *sendbuf, int *sendcounts, int *displs, MPI_Datatype sendtype,
6280 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6281 int root, MPI_Comm comm)
6283 AMPIAPI("AMPI_Scatterv");
6285 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6286 handle_MPI_IN_PLACE(sendbuf, recvbuf);
6288 #if AMPI_ERROR_CHECKING
6290 if (getAmpiInstance(comm)->getRank(comm) == root) {
6291 ret = errorCheck("AMPI_Scatterv", comm, 1, 0, 0, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6292 if(ret != MPI_SUCCESS)
6295 ret = errorCheck("AMPI_Scatterv", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6296 if(ret != MPI_SUCCESS)
6300 if(comm==MPI_COMM_SELF)
6301 return copyDatatype(comm,sendtype,sendcounts[0],sendbuf,recvbuf);
6302 if(getAmpiParent()->isInter(comm))
6303 CkAbort("AMPI does not implement MPI_Scatterv for Inter-communicators!");
6306 ampiParent* pptr = getAmpiParent();
6308 (*(pptr->fromPUPer))|(pptr->pupBytes);
6309 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6314 ampi *ptr = getAmpiInstance(comm);
6315 int size = ptr->getSize(comm);
6318 if(ptr->getRank(comm) == root) {
6319 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6320 int itemsize = dttype->getSize() ;
6321 for(i=0;i<size;i++) {
6322 ptr->send(MPI_SCATTER_TAG, ptr->getRank(comm), ((char*)sendbuf)+(itemsize*displs[i]),
6323 sendcounts[i], sendtype, i, comm);
6327 if(-1==ptr->recv(MPI_SCATTER_TAG, root, recvbuf, recvcount, recvtype, comm))
6328 CkAbort("AMPI> Error in MPI_Scatterv recv");
6331 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6332 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount;
6333 (*(pptr->toPUPer))|(pptr->pupBytes);
6334 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
6342 int AMPI_Iscatterv(void *sendbuf, int *sendcounts, int *displs, MPI_Datatype sendtype,
6343 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6344 int root, MPI_Comm comm, MPI_Request *request)
6346 AMPIAPI("AMPI_Iscatterv");
6348 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6349 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6351 #if AMPI_ERROR_CHECKING
6353 if (getAmpiInstance(comm)->getRank(comm) == root) {
6354 ret = errorCheck("AMPI_Iscatterv", comm, 1, 0, 0, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6355 if(ret != MPI_SUCCESS){
6356 *request = MPI_REQUEST_NULL;
6360 ret = errorCheck("AMPI_Iscatterv", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6361 if(ret != MPI_SUCCESS){
6362 *request = MPI_REQUEST_NULL;
6367 ampi *ptr = getAmpiInstance(comm);
6369 if(comm==MPI_COMM_SELF){
6370 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,
6371 AMPI_REQ_COMPLETED));
6372 return copyDatatype(comm,sendtype,sendcounts[0],sendbuf,recvbuf);
6374 if(getAmpiParent()->isInter(comm))
6375 CkAbort("AMPI does not implement MPI_Iscatterv for Inter-communicators!");
6378 ampiParent* pptr = getAmpiParent();
6380 (*(pptr->fromPUPer))|(pptr->pupBytes);
6381 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6386 int size = ptr->getSize(comm);
6389 if(ptr->getRank(comm) == root) {
6390 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6391 int itemsize = dttype->getSize() ;
6392 for(i=0;i<size;i++) {
6393 ptr->send(MPI_SCATTER_TAG, ptr->getRank(comm), ((char*)sendbuf)+(itemsize*displs[i]),
6394 sendcounts[i], sendtype, i, comm);
6398 // call irecv to post an IReq and process any pending messages
6399 ptr->irecv(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,request);
6402 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6403 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount;
6404 (*(pptr->toPUPer))|(pptr->pupBytes);
6405 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
6413 int AMPI_Alltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype,
6414 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6417 AMPIAPI("AMPI_Alltoall");
6419 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6421 #if AMPI_ERROR_CHECKING
6423 ret = errorCheck("AMPI_Alltoall", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6424 if(ret != MPI_SUCCESS)
6426 ret = errorCheck("AMPI_Alltoall", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6427 if(ret != MPI_SUCCESS)
6431 if(comm==MPI_COMM_SELF)
6432 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
6433 if(sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
6434 CkAbort("AMPI does not implement MPI_IN_PLACE for MPI_Alltoall!");
6435 if(getAmpiParent()->isInter(comm))
6436 CkAbort("AMPI does not implement MPI_Alltoall for Inter-communicators!");
6438 ampi *ptr = getAmpiInstance(comm);
6439 int size = ptr->getSize(comm);
6440 CkDDT_DataType *dttype;
6444 dttype = ptr->getDDT()->getType(sendtype) ;
6445 itemsize = dttype->getSize(sendcount) ;
6446 int rank = ptr->getRank(comm);
6447 int comm_size = size;
6450 #if CMK_BIGSIM_CHARM
6451 TRACE_BG_AMPI_LOG(MPI_ALLTOALL, itemsize);
6454 if( itemsize <= AMPI_ALLTOALL_SHORT_MSG ){
6455 /* Short message. Use recursive doubling. Each process sends all
6456 its data at each step along with all data it received in
6459 /* need to allocate temporary buffer of size
6460 sendbuf_extent*comm_size */
6462 int sendtype_extent = getDDT()->getExtent(sendtype);
6463 int recvtype_extent = getDDT()->getExtent(recvtype);
6464 int sendbuf_extent = sendcount * comm_size * sendtype_extent;
6466 vector<char> tmp_buf(sendbuf_extent*comm_size);
6468 /* copy local sendbuf into tmp_buf at location indexed by rank */
6469 int curr_cnt = sendcount*comm_size;
6470 copyDatatype(comm, sendtype, curr_cnt, sendbuf,
6471 (&tmp_buf[0] + rank*sendbuf_extent));
6474 int dst,tree_root,dst_tree_root,my_tree_root;
6475 int last_recv_cnt,nprocs_completed;
6478 while (mask < comm_size) {
6481 dst_tree_root = dst >> i;
6482 dst_tree_root <<= i;
6484 my_tree_root = rank >> i;
6487 if (dst < comm_size) {
6488 ptr->sendrecv((&tmp_buf[0] + my_tree_root*sendbuf_extent),
6489 curr_cnt, sendtype, dst, MPI_ATA_SEQ_TAG,
6490 (&tmp_buf[0] + dst_tree_root*sendbuf_extent),
6491 sendcount*comm_size*mask, sendtype, dst,
6492 MPI_ATA_SEQ_TAG, comm, &status);
6494 /* in case of non-power-of-two nodes, less data may be
6495 received than specified */
6496 AMPI_Get_count(&status, sendtype, &last_recv_cnt);
6497 curr_cnt += last_recv_cnt;
6500 /* if some processes in this process's subtree in this step
6501 did not have any destination process to communicate with
6502 because of non-power-of-two, we need to send them the
6503 result. We use a logarithmic recursive-halfing algorithm
6506 if (dst_tree_root + mask > comm_size) {
6507 nprocs_completed = comm_size - my_tree_root - mask;
6508 /* nprocs_completed is the number of processes in this
6509 subtree that have all the data. Send data to others
6510 in a tree fashion. First find root of current tree
6511 that is being divided into two. k is the number of
6512 least-significant bits in this process's rank that
6513 must be zeroed out to find the rank of the root */
6522 tmp_mask = mask >> 1;
6524 dst = rank ^ tmp_mask;
6526 tree_root = rank >> k;
6529 /* send only if this proc has data and destination
6530 doesn't have data. at any step, multiple processes
6531 can send if they have the data */
6533 (rank < tree_root + nprocs_completed)
6534 && (dst >= tree_root + nprocs_completed)) {
6535 /* send the data received in this step above */
6536 ptr->send(MPI_ATA_SEQ_TAG, ptr->getRank(comm),
6537 (&tmp_buf[0] + dst_tree_root * sendbuf_extent),
6538 last_recv_cnt, sendtype, dst, comm);
6540 /* recv only if this proc. doesn't have data and sender
6542 else if ((dst < rank) &&
6543 (dst < tree_root + nprocs_completed) &&
6544 (rank >= tree_root + nprocs_completed)) {
6545 if(-1==ptr->recv(MPI_ATA_SEQ_TAG, dst, &tmp_buf[0] + dst_tree_root*sendbuf_extent,
6546 sendcount*comm_size*mask, sendtype, comm, &status))
6547 CkAbort("AMPI> Error in MPI_Alltoall");
6548 AMPI_Get_count(&status, sendtype, &last_recv_cnt);
6549 curr_cnt += last_recv_cnt;
6560 /* now copy everyone's contribution from tmp_buf to recvbuf */
6561 for (int p=0; p<comm_size; p++) {
6562 copyDatatype(comm,sendtype,sendcount,
6563 (&tmp_buf[0] + p*sendbuf_extent + rank*sendcount*sendtype_extent),
6564 ((char*)recvbuf + p*recvcount*recvtype_extent));
6567 }else if ( itemsize <= AMPI_ALLTOALL_MEDIUM_MSG ) {
6568 for(i=0;i<size;i++) {
6569 int dst = (rank+i) % size;
6570 ptr->send(MPI_ATA_TAG, rank, ((char*)sendbuf)+(itemsize*dst), sendcount,
6571 sendtype, dst, comm);
6573 dttype = ptr->getDDT()->getType(recvtype) ;
6574 itemsize = dttype->getSize(recvcount) ;
6575 for(i=0;i<size;i++) {
6576 int dst = (rank+i) % size;
6577 if(-1==ptr->recv(MPI_ATA_TAG, dst, ((char*)recvbuf)+(itemsize*dst), recvcount,
6579 CkAbort("AMPI> Error in MPI_Alltoall");
6581 } else { // large messages
6582 /* Long message. Use pairwise exchange. If comm_size is a
6583 power-of-two, use exclusive-or to create pairs. Else send
6584 to rank+i, receive from rank-i. */
6588 /* Is comm_size a power-of-two? */
6597 /* The i=0 case takes care of moving local data into recvbuf */
6598 for (i=0; i<size; i++) {
6600 /* use exclusive-or algorithm */
6601 src = dst = rank ^ i;
6604 src = (rank - i + size) % size;
6605 dst = (rank + i) % size;
6609 ptr->sendrecv(((char *)sendbuf + dst*itemsize), sendcount, sendtype, dst, MPI_ATA_TAG,
6610 ((char *)recvbuf + src*itemsize), recvcount, recvtype, src, MPI_ATA_TAG,
6612 } // end of large message
6619 int AMPI_Alltoall_iget(void *sendbuf, int sendcount, MPI_Datatype sendtype,
6620 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6623 AMPIAPI("AMPI_Alltoall_iget");
6625 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6627 #if AMPI_ERROR_CHECKING
6629 ret = errorCheck("AMPI_Alltoall_iget", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6630 if(ret != MPI_SUCCESS)
6632 ret = errorCheck("AMPI_Alltoall_iget", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6633 if(ret != MPI_SUCCESS)
6637 if(comm==MPI_COMM_SELF)
6638 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
6639 if(sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
6640 CkAbort("AMPI does not implement MPI_IN_PLACE for MPI_Alltoall_iget!");
6641 if(getAmpiParent()->isInter(comm))
6642 CkAbort("AMPI does not implement MPI_Alltoall_iget for Inter-communicators!");
6644 ampi *ptr = getAmpiInstance(comm);
6645 CProxy_ampi pa(ptr->ckGetArrayID());
6646 int size = ptr->getSize(comm);
6647 CkDDT_DataType *dttype;
6652 // Set flags for others to get
6653 ptr->setA2AIgetFlag((void*)sendbuf);
6654 MPI_Comm_rank(comm,&myrank);
6655 recvdisp = myrank*recvcount;
6659 vector<MPI_Request> reqs(size);
6660 for(i=0;i<size;i++) {
6661 reqs[i] = pa[i].Alltoall_RemoteIget(recvdisp, recvcount, recvtype, MPI_ATA_TAG);
6664 dttype = ptr->getDDT()->getType(recvtype) ;
6665 itemsize = dttype->getSize(recvcount) ;
6667 for(i=0;i<size;i++) {
6668 msg = (AmpiMsg*)CkWaitReleaseFuture(reqs[i]);
6669 memcpy((char*)recvbuf+(itemsize*i), msg->getData(),itemsize);
6676 ptr->resetA2AIgetFlag();
6682 int AMPI_Ialltoall(void *sendbuf, int sendcount, MPI_Datatype sendtype,
6683 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6684 MPI_Comm comm, MPI_Request *request)
6686 AMPIAPI("AMPI_Ialltoall");
6688 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6689 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6691 #if AMPI_ERROR_CHECKING
6693 ret = errorCheck("AMPI_Ialltoall", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6694 if(ret != MPI_SUCCESS){
6695 *request = MPI_REQUEST_NULL;
6698 ret = errorCheck("AMPI_Ialltoall", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6699 if(ret != MPI_SUCCESS){
6700 *request = MPI_REQUEST_NULL;
6705 ampi *ptr = getAmpiInstance(comm);
6707 if(comm==MPI_COMM_SELF){
6708 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,ptr->getRank(comm),MPI_ATA_TAG,comm,
6709 AMPI_REQ_COMPLETED));
6710 return copyDatatype(comm,sendtype,sendcount,sendbuf,recvbuf);
6712 if(getAmpiParent()->isInter(comm))
6713 CkAbort("AMPI does not implement MPI_Ialltoall for Inter-communicators!");
6715 int size = ptr->getSize(comm);
6716 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype);
6717 int itemsize = dttype->getSize(sendcount);
6719 for(i=0;i<size;i++) {
6720 ptr->send(MPI_ATA_TAG, ptr->getRank(comm), ((char*)sendbuf)+(itemsize*i), sendcount,
6724 // use an IATAReq to non-block the caller and get a request ptr
6725 AmpiRequestList* reqs = getReqs();
6726 IATAReq *newreq = new IATAReq(size);
6727 for(i=0;i<size;i++){
6728 if(newreq->addReq(((char*)recvbuf)+(itemsize*i),recvcount,recvtype,i,MPI_ATA_TAG,comm)!=(i+1))
6729 CkAbort("MPI_Ialltoall: Error adding requests into IATAReq!");
6731 *request = ptr->postReq(newreq);
6732 AMPI_DEBUG("MPI_Ialltoall: request=%d, reqs.size=%d, &reqs=%d\n",*request,reqs->size(),reqs);
6737 int AMPI_Alltoallv(void *sendbuf, int *sendcounts, int *sdispls,
6738 MPI_Datatype sendtype, void *recvbuf, int *recvcounts,
6739 int *rdispls, MPI_Datatype recvtype, MPI_Comm comm)
6741 AMPIAPI("AMPI_Alltoallv");
6743 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6744 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6746 #if AMPI_ERROR_CHECKING
6748 ret = errorCheck("AMPI_Alltoallv", comm, 1, 0, 0, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6749 if(ret != MPI_SUCCESS)
6751 ret = errorCheck("AMPI_Alltoallv", comm, 1, 0, 0, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6752 if(ret != MPI_SUCCESS)
6756 if(comm==MPI_COMM_SELF)
6757 return copyDatatype(comm,sendtype,sendcounts[0],sendbuf,recvbuf);
6758 if(getAmpiParent()->isInter(comm))
6759 CkAbort("AMPI does not implement MPI_Alltoallv for Inter-communicators!");
6761 ampi *ptr = getAmpiInstance(comm);
6762 int size = ptr->getSize(comm);
6763 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6764 int itemsize = dttype->getSize() ;
6766 for(i=0;i<size;i++) {
6767 ptr->send(MPI_ATA_TAG,ptr->getRank(comm),((char*)sendbuf)+(itemsize*sdispls[i]),sendcounts[i],
6770 dttype = ptr->getDDT()->getType(recvtype) ;
6771 itemsize = dttype->getSize() ;
6773 for(i=0;i<size;i++) {
6774 if(-1==ptr->recv(MPI_ATA_TAG,i,((char*)recvbuf)+(itemsize*rdispls[i]),recvcounts[i],recvtype, comm))
6775 CkAbort("AMPI> Error in MPI_Alltoallv");
6782 int AMPI_Ialltoallv(void *sendbuf, int *sendcounts, int *sdispls, MPI_Datatype sendtype,
6783 void *recvbuf, int *recvcounts, int *rdispls, MPI_Datatype recvtype,
6784 MPI_Comm comm, MPI_Request *request)
6786 AMPIAPI("AMPI_Ialltoallv");
6788 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6789 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6791 #if AMPI_ERROR_CHECKING
6793 ret = errorCheck("AMPI_Ialltoallv", comm, 1, 0, 0, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6794 if(ret != MPI_SUCCESS){
6795 *request = MPI_REQUEST_NULL;
6798 ret = errorCheck("AMPI_Ialltoallv", comm, 1, 0, 0, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6799 if(ret != MPI_SUCCESS){
6800 *request = MPI_REQUEST_NULL;
6805 ampi *ptr = getAmpiInstance(comm);
6807 if(comm==MPI_COMM_SELF){
6808 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtype,ptr->getRank(comm),MPI_ATA_TAG,comm,
6809 AMPI_REQ_COMPLETED));
6810 return copyDatatype(comm,sendtype,sendcounts[0],sendbuf,recvbuf);
6812 if(getAmpiParent()->isInter(comm))
6813 CkAbort("AMPI does not implement MPI_Ialltoallv for Inter-communicators!");
6815 int size = ptr->getSize(comm);
6816 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6817 int itemsize = dttype->getSize() ;
6819 for(i=0;i<size;i++) {
6820 ptr->send(MPI_ATA_TAG,ptr->getRank(comm),((char*)sendbuf)+(itemsize*sdispls[i]),sendcounts[i],
6824 dttype = ptr->getDDT()->getType(recvtype) ;
6825 itemsize = dttype->getSize() ;
6827 // use an IATAReq to non-block the caller and get a request ptr
6828 AmpiRequestList* reqs = getReqs();
6829 IATAReq *newreq = new IATAReq(size);
6830 for(i=0;i<size;i++){
6831 if(newreq->addReq((void*)(((char*)recvbuf)+(itemsize*rdispls[i])),recvcounts[i],recvtype,i,MPI_ATA_TAG,comm)!=(i+1))
6832 CkAbort("MPI_Ialltoallv: Error adding requests into IATAReq!");
6834 *request = ptr->postReq(newreq);
6835 AMPI_DEBUG("MPI_Ialltoallv: request=%d, reqs.size=%d, &reqs=%d\n",*request,reqs->size(),reqs);
6841 int AMPI_Alltoallw(void *sendbuf, int *sendcounts, int *sdispls,
6842 MPI_Datatype *sendtypes, void *recvbuf, int *recvcounts,
6843 int *rdispls, MPI_Datatype *recvtypes, MPI_Comm comm)
6845 AMPIAPI("AMPI_Alltoallw");
6847 handle_MPI_BOTTOM(sendbuf, sendtypes[0], recvbuf, recvtypes[0]);
6848 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6850 #if AMPI_ERROR_CHECKING
6852 ret = errorCheck("AMPI_Alltoallw", comm, 1, 0, 0, sendtypes[0], 1, 0, 0, 0, 0, sendbuf, 1);
6853 if(ret != MPI_SUCCESS)
6855 ret = errorCheck("AMPI_Alltoallw", comm, 1, 0, 0, recvtypes[0], 1, 0, 0, 0, 0, recvbuf, 1);
6856 if(ret != MPI_SUCCESS)
6860 if(comm==MPI_COMM_SELF)
6861 return copyDatatype(comm,sendtypes[0],sendcounts[0],sendbuf,recvbuf);
6862 if(getAmpiParent()->isInter(comm))
6863 CkAbort("AMPI does not implement MPI_Alltoallw for Inter-communicators!");
6865 /* displs are in terms of bytes for Alltoallw (unlike Alltoallv) */
6866 ampi *ptr = getAmpiInstance(comm);
6867 int i, size = ptr->getSize(comm);
6868 for(i=0;i<size;i++){
6869 ptr->send(MPI_ATA_TAG, ptr->getRank(comm), ((char*)sendbuf)+sdispls[i],
6870 sendcounts[i], sendtypes[i], i, comm);
6873 for(i=0;i<size;i++){
6874 if(-1==ptr->recv(MPI_ATA_TAG, i, ((char*)recvbuf)+rdispls[i], recvcounts[i],
6875 recvtypes[i], comm))
6876 CkAbort("MPI_Alltoallw failed in recv\n");
6883 int AMPI_Ialltoallw(void *sendbuf, int *sendcounts, int *sdispls,
6884 MPI_Datatype *sendtypes, void *recvbuf, int *recvcounts,
6885 int *rdispls, MPI_Datatype *recvtypes, MPI_Comm comm,
6886 MPI_Request *request)
6888 AMPIAPI("AMPI_Ialltoallw");
6890 handle_MPI_BOTTOM(sendbuf, sendtypes[0], recvbuf, recvtypes[0]);
6891 handle_MPI_IN_PLACE(sendbuf,recvbuf);
6893 #if AMPI_ERROR_CHECKING
6895 ret = errorCheck("AMPI_Ialltoallw", comm, 1, 0, 0, sendtypes[0], 1, 0, 0, 0, 0, sendbuf, 1);
6896 if(ret != MPI_SUCCESS){
6897 *request = MPI_REQUEST_NULL;
6900 ret = errorCheck("AMPI_Ialltoallw", comm, 1, 0, 0, recvtypes[0], 1, 0, 0, 0, 0, recvbuf, 1);
6901 if(ret != MPI_SUCCESS){
6902 *request = MPI_REQUEST_NULL;
6907 ampi *ptr = getAmpiInstance(comm);
6909 if(comm==MPI_COMM_SELF){
6910 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtypes[0],ptr->getRank(comm),MPI_ATA_TAG,comm,
6911 AMPI_REQ_COMPLETED));
6912 return copyDatatype(comm,sendtypes[0],sendcounts[0],sendbuf,recvbuf);
6914 if(getAmpiParent()->isInter(comm))
6915 CkAbort("AMPI does not implement MPI_Ialltoallw for Inter-communicators!");
6917 /* displs are in terms of bytes for Alltoallw (unlike Alltoallv) */
6918 int i, size = ptr->getSize(comm);
6919 for(i=0;i<size;i++){
6920 ptr->send(MPI_ATA_TAG, ptr->getRank(comm), ((char*)sendbuf)+sdispls[i],
6921 sendcounts[i], sendtypes[i], i, comm);
6924 // use an IATAReq to non-block the caller and get a request ptr
6925 AmpiRequestList* reqs = getReqs();
6926 IATAReq *newreq = new IATAReq(size);
6927 for(i=0;i<size;i++){
6928 if(newreq->addReq((void*)(((char*)recvbuf)+rdispls[i]), recvcounts[i],
6929 recvtypes[i], i, MPI_ATA_TAG, comm) != (i+1))
6930 CkAbort("MPI_Ialltoallw: Error adding requests into IATAReq!");
6932 *request = ptr->postReq(newreq);
6938 int AMPI_Neighbor_alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype,
6939 void* recvbuf, int recvcount, MPI_Datatype recvtype,
6942 AMPIAPI("AMPI_Neighbor_alltoall");
6944 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6946 #if AMPI_ERROR_CHECKING
6947 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
6948 CkAbort("MPI_Neighbor_alltoall does not accept MPI_IN_PLACE!");
6949 if (getAmpiParent()->isInter(comm))
6950 CkAbort("MPI_Neighbor_alltoall is not defined for Inter-communicators!");
6952 ret = errorCheck("AMPI_Neighbor_alltoall", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6953 if(ret != MPI_SUCCESS)
6955 ret = errorCheck("AMPI_Neighbor_alltoall", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6956 if(ret != MPI_SUCCESS)
6960 if (comm == MPI_COMM_SELF)
6961 return copyDatatype(comm, sendtype, sendcount, sendbuf, recvbuf);
6963 ampi *ptr = getAmpiInstance(comm);
6964 int rank_in_comm = ptr->getRank(comm);
6966 const vector<int>& neighbors = ptr->getNeighbors();
6967 int num_neighbors = neighbors.size();
6969 int itemsize = getDDT()->getType(sendtype)->getSize(sendcount);
6970 for (int i=0; i<num_neighbors; i++) {
6971 ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+(itemsize*i)),
6972 sendcount, sendtype, neighbors[i], comm);
6974 for (int j=0; j<num_neighbors; j++) {
6975 if (-1==ptr->recv(MPI_NBOR_TAG, neighbors[j], (void*)(((char*)recvbuf)+(itemsize*j)),
6976 recvcount, recvtype, comm))
6977 CkAbort("AMPI> Error in MPI_Neighbor_alltoall recv");
6984 int AMPI_Ineighbor_alltoall(void* sendbuf, int sendcount, MPI_Datatype sendtype,
6985 void* recvbuf, int recvcount, MPI_Datatype recvtype,
6986 MPI_Comm comm, MPI_Request *request)
6988 AMPIAPI("AMPI_Ineighbor_alltoall");
6990 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
6992 #if AMPI_ERROR_CHECKING
6993 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
6994 CkAbort("MPI_Ineighbor_alltoall does not accept MPI_IN_PLACE!");
6995 if (getAmpiParent()->isInter(comm))
6996 CkAbort("MPI_Ineighbor_alltoall is not defined for Inter-communicators!");
6998 ret = errorCheck("AMPI_Ineighbor_alltoall", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6999 if(ret != MPI_SUCCESS){
7000 *request = MPI_REQUEST_NULL;
7003 ret = errorCheck("AMPI_Ineighbor_alltoall", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7004 if(ret != MPI_SUCCESS){
7005 *request = MPI_REQUEST_NULL;
7010 ampi *ptr = getAmpiInstance(comm);
7011 int rank_in_comm = ptr->getRank(comm);
7013 if (comm == MPI_COMM_SELF) {
7014 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,rank_in_comm,MPI_NBOR_TAG,comm,
7015 AMPI_REQ_COMPLETED));
7016 return copyDatatype(comm, sendtype, sendcount, sendbuf, recvbuf);
7019 const vector<int>& neighbors = ptr->getNeighbors();
7020 int num_neighbors = neighbors.size();
7022 int itemsize = getDDT()->getType(sendtype)->getSize(sendcount);
7023 for (int i=0; i<num_neighbors; i++) {
7024 ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+(itemsize*i)),
7025 sendcount, sendtype, neighbors[i], comm);
7028 // use an IATAReq to non-block the caller and get a request ptr
7029 AmpiRequestList* reqs = getReqs();
7030 IATAReq *newreq = new IATAReq(num_neighbors);
7031 for (int j=0; j<num_neighbors; j++) {
7032 if(newreq->addReq(((char*)recvbuf)+(itemsize*j), recvcount, recvtype,
7033 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7034 CkAbort("MPI_Ineighbor_alltoall: Error adding requests into IATAReq!");
7036 *request = ptr->postReq(newreq);
7042 int AMPI_Neighbor_alltoallv(void* sendbuf, int *sendcounts, int *sdispls,
7043 MPI_Datatype sendtype, void* recvbuf, int *recvcounts,
7044 int *rdispls, MPI_Datatype recvtype, MPI_Comm comm)
7046 AMPIAPI("AMPI_Neighbor_alltoallv");
7048 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
7050 #if AMPI_ERROR_CHECKING
7051 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7052 CkAbort("MPI_Neighbor_alltoallv does not accept MPI_IN_PLACE!");
7053 if (getAmpiParent()->isInter(comm))
7054 CkAbort("MPI_Neighbor_alltoallv is not defined for Inter-communicators!");
7056 ret = errorCheck("AMPI_Neighbor_alltoallv", comm, 1, sendcounts[0], 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7057 if(ret != MPI_SUCCESS)
7059 ret = errorCheck("AMPI_Neighbor_alltoallv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7060 if(ret != MPI_SUCCESS)
7064 if (comm == MPI_COMM_SELF)
7065 return copyDatatype(comm, sendtype, sendcounts[0], sendbuf, recvbuf);
7067 ampi *ptr = getAmpiInstance(comm);
7068 int rank_in_comm = ptr->getRank(comm);
7070 const vector<int>& neighbors = ptr->getNeighbors();
7071 int num_neighbors = neighbors.size();
7073 int itemsize = getDDT()->getType(sendtype)->getSize();
7074 for (int i=0; i<num_neighbors; i++) {
7075 ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+(itemsize*sdispls[i])),
7076 sendcounts[i], sendtype, neighbors[i], comm);
7078 for (int j=0; j<num_neighbors; j++) {
7079 if (-1==ptr->recv(MPI_NBOR_TAG, neighbors[j], (void*)(((char*)recvbuf)+(itemsize*rdispls[j])),
7080 recvcounts[j], recvtype, comm))
7081 CkAbort("AMPI> Error in MPI_Neighbor_alltoallv recv");
7088 int AMPI_Ineighbor_alltoallv(void* sendbuf, int *sendcounts, int *sdispls,
7089 MPI_Datatype sendtype, void* recvbuf, int *recvcounts,
7090 int *rdispls, MPI_Datatype recvtype, MPI_Comm comm,
7091 MPI_Request *request)
7093 AMPIAPI("AMPI_Ineighbor_alltoallv");
7095 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
7097 #if AMPI_ERROR_CHECKING
7098 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7099 CkAbort("MPI_Ineighbor_alltoallv does not accept MPI_IN_PLACE!");
7100 if (getAmpiParent()->isInter(comm))
7101 CkAbort("MPI_Ineighbor_alltoallv is not defined for Inter-communicators!");
7103 ret = errorCheck("AMPI_Ineighbor_alltoallv", comm, 1, sendcounts[0], 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7104 if(ret != MPI_SUCCESS){
7105 *request = MPI_REQUEST_NULL;
7108 ret = errorCheck("AMPI_Ineighbor_alltoallv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7109 if(ret != MPI_SUCCESS){
7110 *request = MPI_REQUEST_NULL;
7115 ampi *ptr = getAmpiInstance(comm);
7116 int rank_in_comm = ptr->getRank(comm);
7118 if (comm == MPI_COMM_SELF) {
7119 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtype,rank_in_comm,MPI_NBOR_TAG,comm,
7120 AMPI_REQ_COMPLETED));
7121 return copyDatatype(comm, sendtype, sendcounts[0], sendbuf, recvbuf);
7124 const vector<int>& neighbors = ptr->getNeighbors();
7125 int num_neighbors = neighbors.size();
7127 int itemsize = getDDT()->getType(sendtype)->getSize();
7128 for (int i=0; i<num_neighbors; i++) {
7129 ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+(itemsize*sdispls[i])),
7130 sendcounts[i], sendtype, neighbors[i], comm);
7133 // use an IATAReq to non-block the caller and get a request ptr
7134 AmpiRequestList* reqs = getReqs();
7135 IATAReq *newreq = new IATAReq(num_neighbors);
7136 for (int j=0; j<num_neighbors; j++) {
7137 if(newreq->addReq(((char*)recvbuf)+(itemsize*rdispls[j]), recvcounts[j], recvtype,
7138 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7139 CkAbort("MPI_Ineighbor_alltoallv: Error adding requests into IATAReq!");
7141 *request = ptr->postReq(newreq);
7147 int AMPI_Neighbor_alltoallw(void* sendbuf, int *sendcounts, MPI_Aint *sdispls,
7148 MPI_Datatype *sendtypes, void* recvbuf, int *recvcounts,
7149 MPI_Aint *rdispls, MPI_Datatype *recvtypes, MPI_Comm comm)
7151 AMPIAPI("AMPI_Neighbor_alltoallw");
7153 handle_MPI_BOTTOM(sendbuf, sendtypes[0], recvbuf, recvtypes[0]);
7155 #if AMPI_ERROR_CHECKING
7156 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7157 CkAbort("MPI_Neighbor_alltoallw does not accept MPI_IN_PLACE!");
7158 if (getAmpiParent()->isInter(comm))
7159 CkAbort("MPI_Neighbor_alltoallw is not defined for Inter-communicators!");
7161 ret = errorCheck("AMPI_Neighbor_alltoallw", comm, 1, sendcounts[0], 1, sendtypes[0], 1, 0, 0, 0, 0, sendbuf, 1);
7162 if(ret != MPI_SUCCESS)
7164 ret = errorCheck("AMPI_Neighbor_alltoallw", comm, 1, recvcounts[0], 1, recvtypes[0], 1, 0, 0, 0, 0, recvbuf, 1);
7165 if(ret != MPI_SUCCESS)
7169 if (comm == MPI_COMM_SELF)
7170 return copyDatatype(comm, sendtypes[0], sendcounts[0], sendbuf, recvbuf);
7172 ampi *ptr = getAmpiInstance(comm);
7173 int rank_in_comm = ptr->getRank(comm);
7175 const vector<int>& neighbors = ptr->getNeighbors();
7176 int num_neighbors = neighbors.size();
7178 for (int i=0; i<num_neighbors; i++) {
7179 ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+sdispls[i]),
7180 sendcounts[i], sendtypes[i], neighbors[i], comm);
7182 for (int j=0; j<num_neighbors; j++) {
7183 if (-1==ptr->recv(MPI_NBOR_TAG, neighbors[j], (void*)((char*)recvbuf+rdispls[j]),
7184 recvcounts[j], recvtypes[j], comm))
7185 CkAbort("AMPI> Error in MPI_Neighbor_alltoallv recv");
7192 int AMPI_Ineighbor_alltoallw(void* sendbuf, int *sendcounts, MPI_Aint *sdispls,
7193 MPI_Datatype *sendtypes, void* recvbuf, int *recvcounts,
7194 MPI_Aint *rdispls, MPI_Datatype *recvtypes, MPI_Comm comm,
7195 MPI_Request *request)
7197 AMPIAPI("AMPI_Ineighbor_alltoallw");
7199 handle_MPI_BOTTOM(sendbuf, sendtypes[0], recvbuf, recvtypes[0]);
7201 #if AMPI_ERROR_CHECKING
7202 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7203 CkAbort("MPI_Ineighbor_alltoallw does not accept MPI_IN_PLACE!");
7204 if (getAmpiParent()->isInter(comm))
7205 CkAbort("MPI_Ineighbor_alltoallw is not defined for Inter-communicators!");
7207 ret = errorCheck("AMPI_Ineighbor_alltoallw", comm, 1, sendcounts[0], 1, sendtypes[0], 1, 0, 0, 0, 0, sendbuf, 1);
7208 if(ret != MPI_SUCCESS){
7209 *request = MPI_REQUEST_NULL;
7212 ret = errorCheck("AMPI_Ineighbor_alltoallw", comm, 1, recvcounts[0], 1, recvtypes[0], 1, 0, 0, 0, 0, recvbuf, 1);
7213 if(ret != MPI_SUCCESS){
7214 *request = MPI_REQUEST_NULL;
7219 ampi *ptr = getAmpiInstance(comm);
7220 int rank_in_comm = ptr->getRank(comm);
7222 if (comm == MPI_COMM_SELF) {
7223 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtypes[0],rank_in_comm,MPI_NBOR_TAG,comm,
7224 AMPI_REQ_COMPLETED));
7225 return copyDatatype(comm, sendtypes[0], sendcounts[0], sendbuf, recvbuf);
7228 const vector<int>& neighbors = ptr->getNeighbors();
7229 int num_neighbors = neighbors.size();
7231 for (int i=0; i<num_neighbors; i++) {
7232 ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+sdispls[i]),
7233 sendcounts[i], sendtypes[i], neighbors[i], comm);
7236 // use an IATAReq to non-block the caller and get a request ptr
7237 AmpiRequestList* reqs = getReqs();
7238 IATAReq *newreq = new IATAReq(num_neighbors);
7239 for (int j=0; j<num_neighbors; j++) {
7240 if(newreq->addReq((char*)recvbuf+rdispls[j], recvcounts[j], recvtypes[j],
7241 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7242 CkAbort("MPI_Ineighbor_alltoallw: Error adding requests into IATAReq!");
7244 *request = ptr->postReq(newreq);
7250 int AMPI_Neighbor_allgather(void* sendbuf, int sendcount, MPI_Datatype sendtype,
7251 void* recvbuf, int recvcount, MPI_Datatype recvtype,
7254 AMPIAPI("AMPI_Neighbor_allgather");
7256 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
7258 #if AMPI_ERROR_CHECKING
7259 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7260 CkAbort("MPI_Neighbor_allgather does not accept MPI_IN_PLACE!");
7261 if (getAmpiParent()->isInter(comm))
7262 CkAbort("MPI_Neighbor_allgather is not defined for Inter-communicators!");
7264 ret = errorCheck("AMPI_Neighbor_allgather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7265 if(ret != MPI_SUCCESS)
7267 ret = errorCheck("AMPI_Neighbor_allgather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7268 if(ret != MPI_SUCCESS)
7272 if (comm == MPI_COMM_SELF)
7273 return copyDatatype(comm, sendtype, sendcount, sendbuf, recvbuf);
7275 ampi *ptr = getAmpiInstance(comm);
7276 int rank_in_comm = ptr->getRank(comm);
7278 const vector<int>& neighbors = ptr->getNeighbors();
7279 int num_neighbors = neighbors.size();
7281 for (int i=0; i<num_neighbors; i++) {
7282 ptr->send(MPI_NBOR_TAG, rank_in_comm, sendbuf, sendcount, sendtype, neighbors[i], comm);
7284 int itemsize = getDDT()->getType(recvtype)->getSize(recvcount);
7285 for (int j=0; j<num_neighbors; j++) {
7286 if (-1==ptr->recv(MPI_NBOR_TAG, neighbors[j], (void*)(((char*)recvbuf)+(itemsize*j)),
7287 recvcount, recvtype, comm))
7288 CkAbort("AMPI> Error in MPI_Neighbor_allgather recv");
7295 int AMPI_Ineighbor_allgather(void* sendbuf, int sendcount, MPI_Datatype sendtype,
7296 void* recvbuf, int recvcount, MPI_Datatype recvtype,
7297 MPI_Comm comm, MPI_Request *request)
7299 AMPIAPI("AMPI_Ineighbor_allgather");
7301 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
7303 #if AMPI_ERROR_CHECKING
7304 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7305 CkAbort("MPI_Ineighbor_allgather does not accept MPI_IN_PLACE!");
7306 if (getAmpiParent()->isInter(comm))
7307 CkAbort("MPI_Ineighbor_allgather is not defined for Inter-communicators!");
7309 ret = errorCheck("AMPI_Ineighbor_allgather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7310 if(ret != MPI_SUCCESS){
7311 *request = MPI_REQUEST_NULL;
7314 ret = errorCheck("AMPI_Ineighbor_allgather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7315 if(ret != MPI_SUCCESS){
7316 *request = MPI_REQUEST_NULL;
7321 ampi *ptr = getAmpiInstance(comm);
7322 int rank_in_comm = ptr->getRank(comm);
7324 if (comm == MPI_COMM_SELF) {
7325 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,rank_in_comm,MPI_NBOR_TAG,comm,
7326 AMPI_REQ_COMPLETED));
7327 return copyDatatype(comm, sendtype, sendcount, sendbuf, recvbuf);
7330 const vector<int>& neighbors = ptr->getNeighbors();
7331 int num_neighbors = neighbors.size();
7333 for (int i=0; i<num_neighbors; i++) {
7334 ptr->send(MPI_NBOR_TAG, rank_in_comm, sendbuf, sendcount, sendtype, neighbors[i], comm);
7337 // use an IATAReq to non-block the caller and get a request ptr
7338 AmpiRequestList* reqs = getReqs();
7339 IATAReq *newreq = new IATAReq(num_neighbors);
7340 int itemsize = getDDT()->getType(recvtype)->getSize(recvcount);
7341 for (int j=0; j<num_neighbors; j++) {
7342 if(newreq->addReq(((char*)recvbuf)+(itemsize*j), recvcount, recvtype,
7343 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7344 CkAbort("MPI_Ineighbor_allgather: Error adding requests into IATAReq!");
7346 *request = ptr->postReq(newreq);
7352 int AMPI_Neighbor_allgatherv(void* sendbuf, int sendcount, MPI_Datatype sendtype,
7353 void* recvbuf, int *recvcounts, int *displs,
7354 MPI_Datatype recvtype, MPI_Comm comm)
7356 AMPIAPI("AMPI_Neighbor_allgatherv");
7358 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
7360 #if AMPI_ERROR_CHECKING
7361 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7362 CkAbort("MPI_Neighbor_allgatherv does not accept MPI_IN_PLACE!");
7363 if (getAmpiParent()->isInter(comm))
7364 CkAbort("MPI_Neighbor_allgatherv is not defined for Inter-communicators!");
7366 ret = errorCheck("AMPI_Neighbor_allgatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7367 if(ret != MPI_SUCCESS)
7369 ret = errorCheck("AMPI_Neighbor_allgatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7370 if(ret != MPI_SUCCESS)
7374 if (comm == MPI_COMM_SELF)
7375 return copyDatatype(comm, sendtype, sendcount, sendbuf, recvbuf);
7377 ampi *ptr = getAmpiInstance(comm);
7378 int rank_in_comm = ptr->getRank(comm);
7380 const vector<int>& neighbors = ptr->getNeighbors();
7381 int num_neighbors = neighbors.size();
7383 for (int i=0; i<num_neighbors; i++) {
7384 ptr->send(MPI_NBOR_TAG, rank_in_comm, sendbuf, sendcount, sendtype, neighbors[i], comm);
7386 int itemsize = getDDT()->getType(recvtype)->getSize();
7387 for (int j=0; j<num_neighbors; j++) {
7388 if (-1==ptr->recv(MPI_NBOR_TAG, neighbors[j], (void*)(((char*)recvbuf)+(itemsize*displs[j])),
7389 recvcounts[j], recvtype, comm))
7390 CkAbort("AMPI> Error in MPI_Neighbor_allgatherv recv");
7397 int AMPI_Ineighbor_allgatherv(void* sendbuf, int sendcount, MPI_Datatype sendtype,
7398 void* recvbuf, int* recvcounts, int* displs,
7399 MPI_Datatype recvtype, MPI_Comm comm, MPI_Request *request)
7401 AMPIAPI("AMPI_Ineighbor_allgatherv");
7403 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
7405 #if AMPI_ERROR_CHECKING
7406 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7407 CkAbort("MPI_Ineighbor_allgatherv does not accept MPI_IN_PLACE!");
7408 if (getAmpiParent()->isInter(comm))
7409 CkAbort("MPI_Ineighbor_allgatherv is not defined for Inter-communicators!");
7411 ret = errorCheck("AMPI_Ineighbor_allgatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7412 if(ret != MPI_SUCCESS){
7413 *request = MPI_REQUEST_NULL;
7416 ret = errorCheck("AMPI_Ineighbor_allgatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7417 if(ret != MPI_SUCCESS){
7418 *request = MPI_REQUEST_NULL;
7423 ampi *ptr = getAmpiInstance(comm);
7424 int rank_in_comm = ptr->getRank(comm);
7426 if (comm == MPI_COMM_SELF) {
7427 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtype,rank_in_comm,MPI_NBOR_TAG,comm,
7428 AMPI_REQ_COMPLETED));
7429 return copyDatatype(comm, sendtype, sendcount, sendbuf, recvbuf);
7432 const vector<int>& neighbors = ptr->getNeighbors();
7433 int num_neighbors = neighbors.size();
7435 for (int i=0; i<num_neighbors; i++) {
7436 ptr->send(MPI_NBOR_TAG, rank_in_comm, sendbuf, sendcount, sendtype, neighbors[i], comm);
7439 // use an IATAReq to non-block the caller and get a request ptr
7440 AmpiRequestList* reqs = getReqs();
7441 IATAReq *newreq = new IATAReq(num_neighbors);
7442 int itemsize = getDDT()->getType(recvtype)->getSize();
7443 for (int j=0; j<num_neighbors; j++) {
7444 if(newreq->addReq(((char*)recvbuf)+(itemsize*displs[j]), recvcounts[j], recvtype,
7445 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7446 CkAbort("MPI_Ineighbor_allgatherv: Error adding requests into IATAReq!");
7448 *request = ptr->postReq(newreq);
7454 int AMPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm)
7456 AMPIAPI("AMPI_Comm_dup");
7458 ampi *ptr = getAmpiInstance(comm);
7459 int rank = ptr->getRank(comm);
7461 AMPI_Topo_test(comm, &topol);
7462 if (topol == MPI_CART) {
7463 ptr->split(0, rank, newcomm, MPI_CART);
7465 // duplicate cartesian topology info
7466 ampiCommStruct &c = getAmpiParent()->getCart(comm);
7467 ampiCommStruct &newc = getAmpiParent()->getCart(*newcomm);
7468 newc.setndims(c.getndims());
7469 newc.setdims(c.getdims());
7470 newc.setperiods(c.getperiods());
7471 newc.setnbors(c.getnbors());
7474 if (getAmpiParent()->isInter(comm)) {
7475 ptr->split(0,rank,newcomm, MPI_INTER);
7478 ptr->split(0, rank, newcomm, MPI_UNDEFINED /*not MPI_CART*/);
7482 getAmpiInstance(comm)->barrier();
7485 ampiParent* pptr = getAmpiParent();
7487 PUParray(*(pptr->fromPUPer), (char *)newcomm, sizeof(int));
7490 else if(msgLogWrite && record_msglog(pptr->thisIndex)){
7491 PUParray(*(pptr->toPUPer), (char *)newcomm, sizeof(int));
7499 int AMPI_Comm_dup_with_info(MPI_Comm comm, MPI_Info info, MPI_Comm *dest)
7501 AMPIAPI("AMPI_Comm_dup_with_info");
7502 AMPI_Comm_dup(comm, dest);
7503 AMPI_Comm_set_info(*dest, info);
7508 int AMPI_Comm_split(MPI_Comm src, int color, int key, MPI_Comm *dest)
7510 AMPIAPI("AMPI_Comm_split");
7512 ampi *ptr = getAmpiInstance(src);
7513 if (getAmpiParent()->isInter(src)) {
7514 ptr->split(color, key, dest, MPI_INTER);
7516 else if (getAmpiParent()->isCart(src)) {
7517 ptr->split(color, key, dest, MPI_CART);
7520 ptr->split(color, key, dest, MPI_UNDEFINED);
7523 if (color == MPI_UNDEFINED) *dest = MPI_COMM_NULL;
7526 ampiParent* pptr = getAmpiParent();
7528 PUParray(*(pptr->fromPUPer), (char *)dest, sizeof(int));
7531 else if(msgLogWrite && record_msglog(pptr->thisIndex)){
7532 PUParray(*(pptr->toPUPer), (char *)dest, sizeof(int));
7540 int AMPI_Comm_split_type(MPI_Comm src, int split_type, int key, MPI_Info info, MPI_Comm *dest)
7542 AMPIAPI("AMPI_Comm_split_type");
7544 if (src == MPI_COMM_SELF && split_type == MPI_UNDEFINED) {
7545 *dest = MPI_COMM_NULL;
7549 int color = MPI_UNDEFINED;
7551 if (split_type == MPI_COMM_TYPE_SHARED || split_type == AMPI_COMM_TYPE_HOST) {
7552 color = CmiPhysicalNodeID(CkMyPe());
7554 else if (split_type == AMPI_COMM_TYPE_PROCESS) {
7557 else if (split_type == AMPI_COMM_TYPE_WTH) {
7561 if (color == MPI_UNDEFINED) {
7562 *dest = MPI_COMM_NULL;
7563 return ampiErrhandler("MPI_Comm_split_type", MPI_ERR_ARG);
7566 return AMPI_Comm_split(src, color, key, dest);
7570 int AMPI_Comm_free(MPI_Comm *comm)
7572 AMPIAPI("AMPI_Comm_free");
7577 int AMPI_Comm_test_inter(MPI_Comm comm, int *flag){
7578 AMPIAPI("AMPI_Comm_test_inter");
7579 *flag = getAmpiParent()->isInter(comm);
7584 int AMPI_Comm_remote_size(MPI_Comm comm, int *size){
7585 AMPIAPI("AMPI_Comm_remote_size");
7586 *size = getAmpiParent()->getRemoteSize(comm);
7591 int AMPI_Comm_remote_group(MPI_Comm comm, MPI_Group *group){
7592 AMPIAPI("AMPI_Comm_remote_group");
7593 *group = getAmpiParent()->getRemoteGroup(comm);
7598 int AMPI_Intercomm_create(MPI_Comm localComm, int localLeader, MPI_Comm peerComm, int remoteLeader,
7599 int tag, MPI_Comm *newintercomm)
7601 AMPIAPI("AMPI_Intercomm_create");
7603 #if AMPI_ERROR_CHECKING
7604 if (getAmpiParent()->isInter(localComm) || getAmpiParent()->isInter(peerComm))
7605 return ampiErrhandler("AMPI_Intercomm_create", MPI_ERR_COMM);
7608 ampi *localPtr = getAmpiInstance(localComm);
7609 ampi *peerPtr = getAmpiInstance(peerComm);
7610 int rootIndex = localPtr->getIndexForRank(localLeader);
7611 int localSize, localRank;
7613 if (localComm == MPI_COMM_SELF) {
7616 rootIndex = 0; // Note: there is no explicit ampi class instance for MPI_COMM_SELF
7619 localSize = localPtr->getSize(localComm);
7620 localRank = localPtr->getRank(localComm);
7623 vector<int> remoteVec;
7625 if (localRank == localLeader) {
7628 vector<int> localVec;
7629 if (localComm == MPI_COMM_SELF) {
7630 localVec.push_back(0);
7633 localVec = localPtr->getIndices();
7635 // local leader exchanges groupStruct with remote leader
7636 peerPtr->send(tag, peerPtr->getRank(peerComm), &localVec[0], localVec.size(), MPI_INT, remoteLeader, peerComm);
7637 peerPtr->probe(tag, remoteLeader, peerComm, &sts);
7638 AMPI_Get_count(&sts, MPI_INT, &remoteSize);
7639 remoteVec.resize(remoteSize);
7640 if (-1==peerPtr->recv(tag, remoteLeader, &remoteVec[0], remoteSize, MPI_INT, peerComm))
7641 CkAbort("AMPI> Error in MPI_Intercomm_create");
7643 if (remoteSize==0) {
7644 AMPI_DEBUG("AMPI> In MPI_Intercomm_create, creating an empty communicator\n");
7645 *newintercomm = MPI_COMM_NULL;
7650 /* Note: if localComm == MPI_COMM_SELF, then localPtr represents MPI_COMM_WORLD.
7651 * Extra care needs to be taken in ampi::intercommCreate. */
7652 localPtr->intercommCreate(remoteVec,rootIndex,localComm,newintercomm);
7658 int AMPI_Intercomm_merge(MPI_Comm intercomm, int high, MPI_Comm *newintracomm){
7659 AMPIAPI("AMPI_Intercomm_merge");
7661 #if AMPI_ERROR_CHECKING
7662 if (!getAmpiParent()->isInter(intercomm))
7663 return ampiErrhandler("AMPI_Intercomm_merge", MPI_ERR_COMM);
7666 ampi *ptr = getAmpiInstance(intercomm);
7667 int lroot, rroot, lrank, lhigh, rhigh, first;
7668 lroot = ptr->getIndexForRank(0);
7669 rroot = ptr->getIndexForRemoteRank(0);
7671 lrank = ptr->getRank(intercomm);
7675 ptr->send(MPI_ATA_TAG, ptr->getRank(intercomm), &lhigh, 1, MPI_INT, 0, intercomm);
7676 if(-1==ptr->recv(MPI_ATA_TAG,0,&rhigh,1,MPI_INT,intercomm))
7677 CkAbort("AMPI> Error in MPI_Intercomm_create");
7679 if((lhigh && rhigh) || (!lhigh && !rhigh)){ // same value: smaller root goes first (first=1 if local goes first)
7680 first = (lroot < rroot);
7681 }else{ // different values, then high=false goes first
7682 first = (lhigh == false);
7686 ptr->intercommMerge(first, newintracomm);
7691 int AMPI_Abort(MPI_Comm comm, int errorcode)
7693 AMPIAPI("AMPI_Abort");
7694 CkAbort("AMPI: User called MPI_Abort!\n");
7699 int AMPI_Get_count(MPI_Status *sts, MPI_Datatype dtype, int *count){
7700 AMPIAPI("AMPI_Get_count");
7701 CkDDT_DataType* dttype = getDDT()->getType(dtype);
7702 int itemsize = dttype->getSize() ;
7703 if (itemsize == 0) {
7706 *count = sts->MPI_LENGTH/itemsize;
7712 int AMPI_Type_lb(MPI_Datatype dtype, MPI_Aint* displacement){
7713 AMPIAPI("AMPI_Type_lb");
7714 *displacement = getDDT()->getLB(dtype);
7719 int AMPI_Type_ub(MPI_Datatype dtype, MPI_Aint* displacement){
7720 AMPIAPI("AMPI_Type_ub");
7721 *displacement = getDDT()->getUB(dtype);
7726 int AMPI_Get_address(const void* location, MPI_Aint *address){
7727 AMPIAPI("AMPI_Get_address");
7728 *address = (MPI_Aint)location;
7733 int AMPI_Address(void* location, MPI_Aint *address){
7734 AMPIAPI("AMPI_Address");
7735 return AMPI_Get_address(location, address);
7739 int AMPI_Status_set_elements(MPI_Status *sts, MPI_Datatype dtype, int count){
7740 AMPIAPI("AMPI_Status_set_elements");
7741 if(sts == MPI_STATUS_IGNORE || sts == MPI_STATUSES_IGNORE)
7743 CkDDT_DataType* dttype = getDDT()->getType(dtype);
7744 int basesize = dttype->getBaseSize();
7745 if(basesize==0) basesize = dttype->getSize();
7746 sts->MPI_LENGTH = basesize * count;
7751 int AMPI_Get_elements(MPI_Status *sts, MPI_Datatype dtype, int *count){
7752 AMPIAPI("AMPI_Get_elements");
7753 CkDDT_DataType* dttype = getDDT()->getType(dtype) ;
7754 *count = dttype->getNumElements();
7759 int AMPI_Pack(void *inbuf, int incount, MPI_Datatype dtype, void *outbuf,
7760 int outsize, int *position, MPI_Comm comm)
7762 AMPIAPI("AMPI_Pack");
7763 CkDDT_DataType* dttype = getDDT()->getType(dtype) ;
7764 int itemsize = dttype->getSize();
7765 dttype->serialize((char*)inbuf, ((char*)outbuf)+(*position), incount, 1);
7766 *position += (itemsize*incount);
7771 int AMPI_Unpack(void *inbuf, int insize, int *position, void *outbuf,
7772 int outcount, MPI_Datatype dtype, MPI_Comm comm)
7774 AMPIAPI("AMPI_Unpack");
7775 CkDDT_DataType* dttype = getDDT()->getType(dtype) ;
7776 int itemsize = dttype->getSize();
7777 dttype->serialize((char*)outbuf, ((char*)inbuf+(*position)), outcount, -1);
7778 *position += (itemsize*outcount);
7783 int AMPI_Pack_size(int incount,MPI_Datatype datatype,MPI_Comm comm,int *sz)
7785 AMPIAPI("AMPI_Pack_size");
7786 CkDDT_DataType* dttype = getDDT()->getType(datatype) ;
7787 *sz = incount*dttype->getSize() ;
7792 int AMPI_Get_version(int *version, int *subversion){
7793 AMPIAPI("AMPI_Get_version");
7794 *version = MPI_VERSION;
7795 *subversion = MPI_SUBVERSION;
7800 int AMPI_Get_library_version(char *version, int *resultlen){
7801 AMPIAPI("AMPI_Get_library_version");
7802 const char *ampiNameStr = "Adaptive MPI ";
7803 strncpy(version, ampiNameStr, MPI_MAX_LIBRARY_VERSION_STRING);
7804 strncat(version, CmiCommitID, MPI_MAX_LIBRARY_VERSION_STRING - strlen(version));
7805 *resultlen = strlen(version);
7810 int AMPI_Get_processor_name(char *name, int *resultlen){
7811 AMPIAPI("AMPI_Get_processor_name");
7812 ampiParent *ptr = getAmpiParent();
7813 sprintf(name,"AMPI_RANK[%d]_WTH[%d]",ptr->thisIndex,ptr->getMyPe());
7814 *resultlen = strlen(name);
7818 /* Error handling */
7819 #if defined(USE_STDARG)
7820 void error_handler(MPI_Comm *, int *, ...);
7822 void error_handler ( MPI_Comm *, int * );
7826 int AMPI_Comm_call_errhandler(MPI_Comm comm, int errorcode){
7827 AMPIAPI("AMPI_Comm_call_errhandler");
7832 int AMPI_Comm_create_errhandler(MPI_Comm_errhandler_fn *function, MPI_Errhandler *errhandler){
7833 AMPIAPI("AMPI_Comm_create_errhandler");
7838 int AMPI_Comm_set_errhandler(MPI_Comm comm, MPI_Errhandler errhandler){
7839 AMPIAPI("AMPI_Comm_set_errhandler");
7844 int AMPI_Comm_get_errhandler(MPI_Comm comm, MPI_Errhandler *errhandler){
7845 AMPIAPI("AMPI_Comm_get_errhandler");
7850 int AMPI_Comm_free_errhandler(MPI_Errhandler *errhandler){
7851 AMPIAPI("AMPI_Comm_free_errhandler");
7856 int AMPI_Errhandler_create(MPI_Handler_function *function, MPI_Errhandler *errhandler){
7857 AMPIAPI("AMPI_Errhandler_create");
7858 return AMPI_Comm_create_errhandler(function, errhandler);
7862 int AMPI_Errhandler_set(MPI_Comm comm, MPI_Errhandler errhandler){
7863 AMPIAPI("AMPI_Errhandler_set");
7864 return AMPI_Comm_set_errhandler(comm, errhandler);
7868 int AMPI_Errhandler_get(MPI_Comm comm, MPI_Errhandler *errhandler){
7869 AMPIAPI("AMPI_Errhandler_get");
7870 return AMPI_Comm_get_errhandler(comm, errhandler);
7874 int AMPI_Errhandler_free(MPI_Errhandler *errhandler){
7875 AMPIAPI("AMPI_Errhandler_free");
7876 return AMPI_Comm_free_errhandler(errhandler);
7880 int AMPI_Add_error_code(int errorclass, int *errorcode){
7881 AMPIAPI("AMPI_Add_error_code");
7886 int AMPI_Add_error_class(int *errorclass){
7887 AMPIAPI("AMPI_Add_error_class");
7892 int AMPI_Add_error_string(int errorcode, const char *errorstring){
7893 AMPIAPI("AMPI_Add_error_string");
7898 int AMPI_Error_class(int errorcode, int *errorclass){
7899 AMPIAPI("AMPI_Error_class");
7900 *errorclass = errorcode;
7905 int AMPI_Error_string(int errorcode, char *errorstring, int *resultlen)
7907 AMPIAPI("AMPI_Error_string");
7911 r="MPI_SUCCESS: no errors"; break;
7912 case MPI_ERR_BUFFER:
7913 r="MPI_ERR_BUFFER: invalid buffer pointer"; break;
7915 r="MPI_ERR_COUNT: invalid count argument"; break;
7917 r="MPI_ERR_TYPE: invalid datatype"; break;
7919 r="MPI_ERR_TAG: invalid tag"; break;
7921 r="MPI_ERR_COMM: invalid communicator"; break;
7923 r="MPI_ERR_RANK: invalid rank"; break;
7924 case MPI_ERR_REQUEST:
7925 r="MPI_ERR_REQUEST: invalid request (handle)"; break;
7927 r="MPI_ERR_ROOT: invalid root"; break;
7929 r="MPI_ERR_GROUP: invalid group"; break;
7931 r="MPI_ERR_OP: invalid operation"; break;
7932 case MPI_ERR_TOPOLOGY:
7933 r="MPI_ERR_TOPOLOGY: invalid communicator topology"; break;
7935 r="MPI_ERR_DIMS: invalid dimension argument"; break;
7937 r="MPI_ERR_ARG: invalid argument of some other kind"; break;
7938 case MPI_ERR_TRUNCATE:
7939 r="MPI_ERR_TRUNCATE: message truncated in recieve"; break;
7941 r="MPI_ERR_OTHER: known error not in this list"; break;
7942 case MPI_ERR_INTERN:
7943 r="MPI_ERR_INTERN: internal MPI (implementation) error"; break;
7944 case MPI_ERR_IN_STATUS:
7945 r="MPI_ERR_IN_STATUS: error code in status"; break;
7946 case MPI_ERR_PENDING:
7947 r="MPI_ERR_PENDING: pending request"; break;
7948 case MPI_ERR_ACCESS:
7949 r="MPI_ERR_ACCESS: invalid access mode"; break;
7951 r="MPI_ERR_AMODE: invalid amode argument"; break;
7952 case MPI_ERR_ASSERT:
7953 r="MPI_ERR_ASSERT: invalid assert argument"; break;
7954 case MPI_ERR_BAD_FILE:
7955 r="MPI_ERR_BAD_FILE: bad file"; break;
7957 r="MPI_ERR_BASE: invalid base"; break;
7958 case MPI_ERR_CONVERSION:
7959 r="MPI_ERR_CONVERSION: error in data conversion"; break;
7961 r="MPI_ERR_DISP: invalid displacement"; break;
7962 case MPI_ERR_DUP_DATAREP:
7963 r="MPI_ERR_DUP_DATAREP: error duplicating data representation"; break;
7964 case MPI_ERR_FILE_EXISTS:
7965 r="MPI_ERR_FILE_EXISTS: file exists already"; break;
7966 case MPI_ERR_FILE_IN_USE:
7967 r="MPI_ERR_FILE_IN_USE: file in use already"; break;
7969 r="MPI_ERR_FILE: invalid file"; break;
7970 case MPI_ERR_INFO_KEY:
7971 r="MPI_ERR_INFO_KEY: invalid key argument for info object"; break;
7972 case MPI_ERR_INFO_NOKEY:
7973 r="MPI_ERR_INFO_NOKEY: unknown key for info object"; break;
7974 case MPI_ERR_INFO_VALUE:
7975 r="MPI_ERR_INFO_VALUE: invalid value argument for info object"; break;
7977 r="MPI_ERR_INFO: invalid info object"; break;
7979 r="MPI_ERR_IO: input/output error"; break;
7980 case MPI_ERR_KEYVAL:
7981 r="MPI_ERR_KEYVAL: invalid keyval"; break;
7982 case MPI_ERR_LOCKTYPE:
7983 r="MPI_ERR_LOCKTYPE: invalid locktype argument"; break;
7985 r="MPI_ERR_NAME: invalid name argument"; break;
7986 case MPI_ERR_NO_MEM:
7987 r="MPI_ERR_NO_MEM: out of memory"; break;
7988 case MPI_ERR_NOT_SAME:
7989 r="MPI_ERR_NOT_SAME: objects are not identical"; break;
7990 case MPI_ERR_NO_SPACE:
7991 r="MPI_ERR_NO_SPACE: no space left on device"; break;
7992 case MPI_ERR_NO_SUCH_FILE:
7993 r="MPI_ERR_NO_SUCH_FILE: no such file or directory"; break;
7995 r="MPI_ERR_PORT: invalid port"; break;
7997 r="MPI_ERR_QUOTA: out of quota"; break;
7998 case MPI_ERR_READ_ONLY:
7999 r="MPI_ERR_READ_ONLY: file is read only"; break;
8000 case MPI_ERR_RMA_CONFLICT:
8001 r="MPI_ERR_RMA_CONFLICT: rma conflict during operation"; break;
8002 case MPI_ERR_RMA_SYNC:
8003 r="MPI_ERR_RMA_SYNC: error executing rma sync"; break;
8004 case MPI_ERR_SERVICE:
8005 r="MPI_ERR_SERVICE: unknown service name"; break;
8007 r="MPI_ERR_SIZE: invalid size argument"; break;
8009 r="MPI_ERR_SPAWN: error in spawning processes"; break;
8010 case MPI_ERR_UNSUPPORTED_DATAREP:
8011 r="MPI_ERR_UNSUPPORTED_DATAREP: data representation not supported"; break;
8012 case MPI_ERR_UNSUPPORTED_OPERATION:
8013 r="MPI_ERR_UNSUPPORTED_OPERATION: operation not supported"; break;
8015 r="MPI_ERR_WIN: invalid win argument"; break;
8018 *resultlen=strlen(r);
8019 strcpy(errorstring,r);
8020 return MPI_ERR_UNKNOWN;
8022 *resultlen=strlen(r);
8023 strcpy(errorstring,r);
8027 /* Group operations */
8029 int AMPI_Comm_group(MPI_Comm comm, MPI_Group *group)
8031 AMPIAPI("AMPI_Comm_Group");
8032 *group = getAmpiParent()->comm2group(comm);
8037 int AMPI_Group_union(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
8039 AMPIAPI("AMPI_Group_union");
8040 groupStruct vec1, vec2, newvec;
8041 ampiParent *ptr = getAmpiParent();
8042 vec1 = ptr->group2vec(group1);
8043 vec2 = ptr->group2vec(group2);
8044 newvec = unionOp(vec1,vec2);
8045 *newgroup = ptr->saveGroupStruct(newvec);
8050 int AMPI_Group_intersection(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
8052 AMPIAPI("AMPI_Group_intersection");
8053 groupStruct vec1, vec2, newvec;
8054 ampiParent *ptr = getAmpiParent();
8055 vec1 = ptr->group2vec(group1);
8056 vec2 = ptr->group2vec(group2);
8057 newvec = intersectOp(vec1,vec2);
8058 *newgroup = ptr->saveGroupStruct(newvec);
8063 int AMPI_Group_difference(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
8065 AMPIAPI("AMPI_Group_difference");
8066 groupStruct vec1, vec2, newvec;
8067 ampiParent *ptr = getAmpiParent();
8068 vec1 = ptr->group2vec(group1);
8069 vec2 = ptr->group2vec(group2);
8070 newvec = diffOp(vec1,vec2);
8071 *newgroup = ptr->saveGroupStruct(newvec);
8076 int AMPI_Group_size(MPI_Group group, int *size)
8078 AMPIAPI("AMPI_Group_size");
8079 *size = (getAmpiParent()->group2vec(group)).size();
8084 int AMPI_Group_rank(MPI_Group group, int *rank)
8086 AMPIAPI("AMPI_Group_rank");
8087 *rank = getAmpiParent()->getRank(group);
8092 int AMPI_Group_translate_ranks (MPI_Group group1, int n, int *ranks1, MPI_Group group2, int *ranks2)
8094 AMPIAPI("AMPI_Group_translate_ranks");
8095 ampiParent *ptr = getAmpiParent();
8096 groupStruct vec1, vec2;
8097 vec1 = ptr->group2vec(group1);
8098 vec2 = ptr->group2vec(group2);
8099 translateRanksOp(n, vec1, ranks1, vec2, ranks2);
8104 int AMPI_Group_compare(MPI_Group group1,MPI_Group group2, int *result)
8106 AMPIAPI("AMPI_Group_compare");
8107 ampiParent *ptr = getAmpiParent();
8108 groupStruct vec1, vec2;
8109 vec1 = ptr->group2vec(group1);
8110 vec2 = ptr->group2vec(group2);
8111 *result = compareVecOp(vec1, vec2);
8116 int AMPI_Group_incl(MPI_Group group, int n, int *ranks, MPI_Group *newgroup)
8118 AMPIAPI("AMPI_Group_incl");
8119 groupStruct vec, newvec;
8120 ampiParent *ptr = getAmpiParent();
8121 vec = ptr->group2vec(group);
8122 newvec = inclOp(n,ranks,vec);
8123 *newgroup = ptr->saveGroupStruct(newvec);
8128 int AMPI_Group_excl(MPI_Group group, int n, int *ranks, MPI_Group *newgroup)
8130 AMPIAPI("AMPI_Group_excl");
8131 groupStruct vec, newvec;
8132 ampiParent *ptr = getAmpiParent();
8133 vec = ptr->group2vec(group);
8134 newvec = exclOp(n,ranks,vec);
8135 *newgroup = ptr->saveGroupStruct(newvec);
8140 int AMPI_Group_range_incl(MPI_Group group, int n, int ranges[][3], MPI_Group *newgroup)
8142 AMPIAPI("AMPI_Group_range_incl");
8143 groupStruct vec, newvec;
8145 ampiParent *ptr = getAmpiParent();
8146 vec = ptr->group2vec(group);
8147 newvec = rangeInclOp(n,ranges,vec,&ret);
8148 if(ret != MPI_SUCCESS){
8149 *newgroup = MPI_GROUP_EMPTY;
8150 return ampiErrhandler("AMPI_Group_range_incl", ret);
8152 *newgroup = ptr->saveGroupStruct(newvec);
8158 int AMPI_Group_range_excl(MPI_Group group, int n, int ranges[][3], MPI_Group *newgroup)
8160 AMPIAPI("AMPI_Group_range_excl");
8161 groupStruct vec, newvec;
8163 ampiParent *ptr = getAmpiParent();
8164 vec = ptr->group2vec(group);
8165 newvec = rangeExclOp(n,ranges,vec,&ret);
8166 if(ret != MPI_SUCCESS){
8167 *newgroup = MPI_GROUP_EMPTY;
8168 return ampiErrhandler("AMPI_Group_range_excl", ret);
8170 *newgroup = ptr->saveGroupStruct(newvec);
8176 int AMPI_Group_free(MPI_Group *group)
8178 AMPIAPI("AMPI_Group_free");
8183 int AMPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm* newcomm)
8185 AMPIAPI("AMPI_Comm_create");
8186 int rank_in_group, key, color, zero;
8187 MPI_Group group_of_comm;
8189 groupStruct vec = getAmpiParent()->group2vec(group);
8191 AMPI_DEBUG("AMPI> In MPI_Comm_create, creating an empty communicator");
8192 *newcomm = MPI_COMM_NULL;
8196 if(getAmpiParent()->isInter(comm)){
8197 /* inter-communicator: create a single new comm. */
8198 ampi *ptr = getAmpiInstance(comm);
8199 ptr->commCreate(vec, newcomm);
8203 /* intra-communicator: create comm's for disjoint subgroups,
8204 * by calculating (color, key) and splitting comm. */
8205 AMPI_Group_rank(group, &rank_in_group);
8206 if(rank_in_group == MPI_UNDEFINED){
8207 color = MPI_UNDEFINED;
8211 /* use rank in 'comm' of the 0th rank in 'group'
8212 * as identical 'color' of all ranks in 'group' */
8213 AMPI_Comm_group(comm, &group_of_comm);
8215 AMPI_Group_translate_ranks(group, 1, &zero, group_of_comm, &color);
8216 key = rank_in_group;
8218 return AMPI_Comm_split(comm, color, key, newcomm);
8224 int AMPI_Comm_set_name(MPI_Comm comm, const char *comm_name){
8225 AMPIAPI("AMPI_Comm_set_name");
8226 getAmpiInstance(comm)->setCommName(comm_name);
8231 int AMPI_Comm_get_name(MPI_Comm comm, char *comm_name, int *resultlen){
8232 AMPIAPI("AMPI_Comm_get_name");
8233 getAmpiInstance(comm)->getCommName(comm_name, resultlen);
8238 int AMPI_Comm_set_info(MPI_Comm comm, MPI_Info info){
8239 AMPIAPI("AMPI_Comm_set_info");
8240 /* FIXME: no-op implementation */
8245 int AMPI_Comm_get_info(MPI_Comm comm, MPI_Info *info){
8246 AMPIAPI("AMPI_Comm_get_info");
8247 /* FIXME: no-op implementation */
8248 *info = MPI_INFO_NULL;
8253 int AMPI_Comm_create_keyval(MPI_Comm_copy_attr_function *copy_fn,
8254 MPI_Comm_delete_attr_function *delete_fn,
8255 int *keyval, void* extra_state){
8256 AMPIAPI("AMPI_Comm_create_keyval");
8257 int ret = getAmpiParent()->createKeyval(copy_fn,delete_fn,keyval,extra_state);
8258 return ampiErrhandler("AMPI_Comm_create_keyval", ret);
8262 int AMPI_Comm_free_keyval(int *keyval){
8263 AMPIAPI("AMPI_Comm_free_keyval");
8264 int ret = getAmpiParent()->freeKeyval(keyval);
8265 return ampiErrhandler("AMPI_Comm_free_keyval", ret);
8269 int AMPI_Comm_set_attr(MPI_Comm comm, int keyval, void* attribute_val){
8270 AMPIAPI("AMPI_Comm_set_attr");
8271 int ret = getAmpiParent()->setCommAttr(comm,keyval,attribute_val);
8272 return ampiErrhandler("AMPI_Comm_set_attr", ret);
8276 int AMPI_Comm_get_attr(MPI_Comm comm, int keyval, void *attribute_val, int *flag){
8277 AMPIAPI("AMPI_Comm_get_attr");
8278 int ret = getAmpiParent()->getCommAttr(comm,keyval,attribute_val,flag);
8279 return ampiErrhandler("AMPI_Comm_get_attr", ret);
8283 int AMPI_Comm_delete_attr(MPI_Comm comm, int keyval){
8284 AMPIAPI("AMPI_Comm_delete_attr");
8285 int ret = getAmpiParent()->deleteCommAttr(comm,keyval);
8286 return ampiErrhandler("AMPI_Comm_delete_attr", ret);
8290 int AMPI_Keyval_create(MPI_Copy_function *copy_fn, MPI_Delete_function *delete_fn,
8291 int *keyval, void* extra_state){
8292 AMPIAPI("AMPI_Keyval_create");
8293 return AMPI_Comm_create_keyval(copy_fn, delete_fn, keyval, extra_state);
8297 int AMPI_Keyval_free(int *keyval){
8298 AMPIAPI("AMPI_Keyval_free");
8299 return AMPI_Comm_free_keyval(keyval);
8303 int AMPI_Attr_put(MPI_Comm comm, int keyval, void* attribute_val){
8304 AMPIAPI("AMPI_Attr_put");
8305 return AMPI_Comm_set_attr(comm, keyval, attribute_val);
8309 int AMPI_Attr_get(MPI_Comm comm, int keyval, void *attribute_val, int *flag){
8310 AMPIAPI("AMPI_Attr_get");
8311 return AMPI_Comm_get_attr(comm, keyval, attribute_val, flag);
8315 int AMPI_Attr_delete(MPI_Comm comm, int keyval){
8316 AMPIAPI("AMPI_Attr_delete");
8317 return AMPI_Comm_delete_attr(comm, keyval);
8321 int AMPI_Cart_map(MPI_Comm comm, int ndims, int *dims, int *periods, int *newrank) {
8322 AMPIAPI("AMPI_Cart_map");
8323 return AMPI_Comm_rank(comm, newrank);
8327 int AMPI_Graph_map(MPI_Comm comm, int nnodes, int *index, int *edges, int *newrank) {
8328 AMPIAPI("AMPI_Graph_map");
8329 return AMPI_Comm_rank(comm, newrank);
8333 int AMPI_Cart_create(MPI_Comm comm_old, int ndims, int *dims, int *periods,
8334 int reorder, MPI_Comm *comm_cart) {
8336 AMPIAPI("AMPI_Cart_create");
8338 /* Create new cartesian communicator. No attention is being paid to mapping
8339 virtual processes to processors, which ideally should be handled by the
8340 load balancer with input from virtual topology information.
8342 No reorder done here. reorder input is ignored, but still stored in the
8343 communicator with other VT info.
8347 AMPI_Cart_map(comm_old, ndims, dims, periods, &newrank);//no change in rank
8349 ampiParent *ptr = getAmpiParent();
8350 groupStruct vec = ptr->group2vec(ptr->comm2group(comm_old));
8351 getAmpiInstance(comm_old)->cartCreate(vec, comm_cart);
8352 ampiCommStruct &c = ptr->getCart(*comm_cart);
8356 vector<int> periodsv;
8358 for (int i = 0; i < ndims; i++) {
8359 dimsv.push_back(dims[i]);
8360 periodsv.push_back(periods[i]);
8364 c.setperiods(periodsv);
8367 getAmpiInstance(*comm_cart)->findNeighbors(*comm_cart, newrank, nborsv);
8374 int AMPI_Graph_create(MPI_Comm comm_old, int nnodes, int *index, int *edges,
8375 int reorder, MPI_Comm *comm_graph) {
8376 AMPIAPI("AMPI_Graph_create");
8378 /* No mapping done */
8380 AMPI_Graph_map(comm_old, nnodes, index, edges, &newrank);
8382 ampiParent *ptr = getAmpiParent();
8383 groupStruct vec = ptr->group2vec(ptr->comm2group(comm_old));
8384 getAmpiInstance(comm_old)->graphCreate(vec, comm_graph);
8386 ampiCommStruct &c = ptr->getGraph(*comm_graph);
8387 c.setnvertices(nnodes);
8393 for (i = 0; i < nnodes; i++)
8394 index_.push_back(index[i]);
8398 for (i = 0; i < index[nnodes - 1]; i++)
8399 edges_.push_back(edges[i]);
8404 getAmpiInstance(*comm_graph)->findNeighbors(*comm_graph, newrank, nborsv);
8411 int AMPI_Topo_test(MPI_Comm comm, int *status) {
8412 AMPIAPI("AMPI_Topo_test");
8414 ampiParent *ptr = getAmpiParent();
8416 if (ptr->isCart(comm))
8418 else if (ptr->isGraph(comm))
8419 *status = MPI_GRAPH;
8420 else *status = MPI_UNDEFINED;
8426 int AMPI_Cartdim_get(MPI_Comm comm, int *ndims) {
8427 AMPIAPI("AMPI_Cartdim_get");
8429 #if AMPI_ERROR_CHECKING
8430 if (!getAmpiParent()->isCart(comm))
8431 return ampiErrhandler("AMPI_Cartdim_get", MPI_ERR_TOPOLOGY);
8434 *ndims = getAmpiParent()->getCart(comm).getndims();
8440 int AMPI_Cart_get(MPI_Comm comm, int maxdims, int *dims, int *periods, int *coords){
8443 AMPIAPI("AMPI_Cart_get");
8445 #if AMPI_ERROR_CHECKING
8446 if (!getAmpiParent()->isCart(comm))
8447 return ampiErrhandler("AMPI_Cart_get", MPI_ERR_TOPOLOGY);
8450 ampiCommStruct &c = getAmpiParent()->getCart(comm);
8451 ndims = c.getndims();
8452 int rank = getAmpiInstance(comm)->getRank(comm);
8454 const vector<int> &dims_ = c.getdims();
8455 const vector<int> &periods_ = c.getperiods();
8457 for (i = 0; i < maxdims; i++) {
8459 periods[i] = periods_[i];
8462 for (i = ndims - 1; i >= 0; i--) {
8464 coords[i] = rank % dims_[i];
8465 rank = (int) (rank / dims_[i]);
8472 int AMPI_Cart_rank(MPI_Comm comm, int *coords, int *rank) {
8473 AMPIAPI("AMPI_Cart_rank");
8475 #if AMPI_ERROR_CHECKING
8476 if (!getAmpiParent()->isCart(comm))
8477 return ampiErrhandler("AMPI_Cart_rank", MPI_ERR_TOPOLOGY);
8480 ampiCommStruct &c = getAmpiParent()->getCart(comm);
8481 int ndims = c.getndims();
8482 const vector<int> &dims = c.getdims();
8483 const vector<int> &periods = c.getperiods();
8488 for (int i = ndims - 1; i >= 0; i--) {
8489 if ((coords[i] < 0) || (coords[i] >= dims[i])) {
8490 if (periods[i] != 0) {
8491 if (coords[i] > 0) {
8492 coords[i] %= dims[i];
8494 while (coords[i] < 0) coords[i]+=dims[i];
8498 r += prod * coords[i];
8508 int AMPI_Cart_coords(MPI_Comm comm, int rank, int maxdims, int *coords) {
8509 AMPIAPI("AMPI_Cart_coords");
8511 #if AMPI_ERROR_CHECKING
8512 if (!getAmpiParent()->isCart(comm))
8513 return ampiErrhandler("AMPI_Cart_coorts", MPI_ERR_TOPOLOGY);
8516 ampiCommStruct &c = getAmpiParent()->getCart(comm);
8517 int ndims = c.getndims();
8518 const vector<int> &dims = c.getdims();
8520 for (int i = ndims - 1; i >= 0; i--) {
8522 coords[i] = rank % dims[i];
8523 rank = (int) (rank / dims[i]);
8529 // Offset coords[direction] by displacement, and set the rank that
8531 static void cart_clamp_coord(MPI_Comm comm, const vector<int> &dims,
8532 const vector<int> &periodicity, int *coords,
8533 int direction, int displacement, int *rank_out)
8535 int base_coord = coords[direction];
8536 coords[direction] += displacement;
8538 if (periodicity[direction] != 0) {
8539 while (coords[direction] < 0)
8540 coords[direction] += dims[direction];
8541 while (coords[direction] >= dims[direction])
8542 coords[direction] -= dims[direction];
8545 if (coords[direction]<0 || coords[direction]>= dims[direction])
8546 *rank_out = MPI_PROC_NULL;
8548 AMPI_Cart_rank(comm, coords, rank_out);
8550 coords[direction] = base_coord;
8554 int AMPI_Cart_shift(MPI_Comm comm, int direction, int disp,
8555 int *rank_source, int *rank_dest) {
8556 AMPIAPI("AMPI_Cart_shift");
8558 #if AMPI_ERROR_CHECKING
8559 if (!getAmpiParent()->isCart(comm))
8560 return ampiErrhandler("AMPI_Cart_shift", MPI_ERR_TOPOLOGY);
8563 ampiCommStruct &c = getAmpiParent()->getCart(comm);
8564 int ndims = c.getndims();
8566 #if AMPI_ERROR_CHECKING
8567 if ((direction < 0) || (direction >= ndims))
8568 return ampiErrhandler("AMPI_Cart_shift", MPI_ERR_DIMS);
8571 const vector<int> &dims = c.getdims();
8572 const vector<int> &periods = c.getperiods();
8573 vector<int> coords(ndims);
8575 int mype = getAmpiInstance(comm)->getRank(comm);
8576 AMPI_Cart_coords(comm, mype, ndims, &coords[0]);
8578 cart_clamp_coord(comm, dims, periods, &coords[0], direction, disp, rank_dest);
8579 cart_clamp_coord(comm, dims, periods, &coords[0], direction, -disp, rank_source);
8585 int AMPI_Graphdims_get(MPI_Comm comm, int *nnodes, int *nedges) {
8586 AMPIAPI("AMPI_Graphdim_get");
8588 ampiCommStruct &c = getAmpiParent()->getGraph(comm);
8589 *nnodes = c.getnvertices();
8590 const vector<int> &index = c.getindex();
8591 *nedges = index[(*nnodes) - 1];
8597 int AMPI_Graph_get(MPI_Comm comm, int maxindex, int maxedges, int *index, int *edges) {
8598 AMPIAPI("AMPI_Graph_get");
8600 #if AMPI_ERROR_CHECKING
8601 if (!getAmpiParent()->isGraph(comm))
8602 return ampiErrhandler("AMPI_Graph_get", MPI_ERR_TOPOLOGY);
8605 ampiCommStruct &c = getAmpiParent()->getGraph(comm);
8606 const vector<int> &index_ = c.getindex();
8607 const vector<int> &edges_ = c.getedges();
8609 if (maxindex > index_.size())
8610 maxindex = index_.size();
8613 for (i = 0; i < maxindex; i++)
8614 index[i] = index_[i];
8616 for (i = 0; i < maxedges; i++)
8617 edges[i] = edges_[i];
8623 int AMPI_Graph_neighbors_count(MPI_Comm comm, int rank, int *nneighbors) {
8624 AMPIAPI("AMPI_Graph_neighbors_count");
8626 #if AMPI_ERROR_CHECKING
8627 if (!getAmpiParent()->isGraph(comm))
8628 return ampiErrhandler("AMPI_Graph_neighbors_count", MPI_ERR_TOPOLOGY);
8631 ampiCommStruct &c = getAmpiParent()->getGraph(comm);
8632 const vector<int> &index = c.getindex();
8634 #if AMPI_ERROR_CHECKING
8635 if ((rank >= index.size()) || (rank < 0))
8636 return ampiErrhandler("AMPI_Graph_neighbors_count", MPI_ERR_RANK);
8640 *nneighbors = index[rank];
8642 *nneighbors = index[rank] - index[rank - 1];
8648 int AMPI_Graph_neighbors(MPI_Comm comm, int rank, int maxneighbors, int *neighbors) {
8649 AMPIAPI("AMPI_Graph_neighbors");
8651 #if AMPI_ERROR_CHECKING
8652 if (!getAmpiParent()->isGraph(comm))
8653 return ampiErrhandler("AMPI_Graph_neighbors", MPI_ERR_TOPOLOGY);
8656 ampiCommStruct &c = getAmpiParent()->getGraph(comm);
8657 const vector<int> &index = c.getindex();
8658 const vector<int> &edges = c.getedges();
8660 int numneighbors = (rank == 0) ? index[rank] : index[rank] - index[rank - 1];
8661 if (maxneighbors > numneighbors)
8662 maxneighbors = numneighbors;
8664 #if AMPI_ERROR_CHECKING
8665 if (maxneighbors < 0)
8666 return ampiErrhandler("AMPI_Graph_neighbors", MPI_ERR_ARG);
8667 if ((rank >= index.size()) || (rank < 0))
8668 return ampiErrhandler("AMPI_Graph_neighbors", MPI_ERR_RANK);
8672 for (int i = 0; i < maxneighbors; i++)
8673 neighbors[i] = edges[i];
8675 for (int i = 0; i < maxneighbors; i++)
8676 neighbors[i] = edges[index[rank - 1] + i];
8681 /* Used by MPI_Cart_create & MPI_Graph_create */
8682 void ampi::findNeighbors(MPI_Comm comm, int rank, vector<int>& neighbors) const {
8683 int max_neighbors = 0;
8684 ampiParent *ptr = getAmpiParent();
8685 if (ptr->isGraph(comm)) {
8686 AMPI_Graph_neighbors_count(comm, rank, &max_neighbors);
8687 neighbors.resize(max_neighbors);
8688 AMPI_Graph_neighbors(comm, rank, max_neighbors, &neighbors[0]);
8690 else if (ptr->isCart(comm)) {
8692 AMPI_Cartdim_get(comm, &num_dims);
8693 max_neighbors = 2*num_dims;
8694 for (int i=0; i<max_neighbors; i++) {
8696 AMPI_Cart_shift(comm, i/2, (i%2==0)?1:-1, &src, &dest);
8697 if (dest != MPI_PROC_NULL)
8698 neighbors.push_back(dest);
8703 /* Factorization code by Orion. Idea thrashed out by Orion and Prakash */
8706 Return the integer "d'th root of n"-- the largest
8710 int integerRoot(int n,int d) {
8711 double epsilon=0.001; /* prevents roundoff in "floor" */
8712 return (int)floor(pow(n+epsilon,1.0/d));
8716 Factorize "n" into "d" factors, stored in "dims[0..d-1]".
8717 All the factors must be greater than or equal to m.
8718 The factors are chosen so that they are all as near together
8719 as possible (technically, chosen so that the increasing-size
8720 ordering is lexicagraphically as large as possible).
8723 bool factors(int n, int d, int *dims, int m) {
8726 if (n>=m) { /* n is an acceptable factor */
8731 else { /* induction case */
8732 int k_up=integerRoot(n,d);
8733 for (int k=k_up;k>=m;k--) {
8734 if (n%k==0) { /* k divides n-- try it as a factor */
8736 if (factors(n/k,d-1,&dims[1],k))
8741 /* If we fall out here, there were no factors available */
8746 int AMPI_Dims_create(int nnodes, int ndims, int *dims) {
8747 AMPIAPI("AMPI_Dims_create");
8754 for (i = 0; i < ndims; i++) {
8756 if (n % dims[i] != 0) {
8757 return ampiErrhandler("AMPI_Dims_create", MPI_ERR_DIMS);
8766 vector<int> pdims(d);
8768 if (!factors(n, d, &pdims[0], 1))
8769 CkAbort("MPI_Dims_create: factorization failed!\n");
8772 for (i = 0; i < ndims; i++) {
8783 /* Implemented with call to MPI_Comm_Split. Color and key are single integer
8784 encodings of the lost and preserved dimensions, respectively,
8788 int AMPI_Cart_sub(MPI_Comm comm, int *remain_dims, MPI_Comm *newcomm) {
8789 AMPIAPI("AMPI_Cart_sub");
8792 int color = 1, key = 1;
8794 #if AMPI_ERROR_CHECKING
8795 if (!getAmpiParent()->isCart(comm))
8796 return ampiErrhandler("AMPI_Cart_sub", MPI_ERR_TOPOLOGY);
8799 int rank = getAmpiInstance(comm)->getRank(comm);
8800 ampiCommStruct &c = getAmpiParent()->getCart(comm);
8801 ndims = c.getndims();
8802 const vector<int> &dims = c.getdims();
8803 int num_remain_dims = 0;
8805 vector<int> coords(ndims);
8806 AMPI_Cart_coords(comm, rank, ndims, &coords[0]);
8808 for (i = 0; i < ndims; i++) {
8809 if (remain_dims[i]) {
8810 /* key single integer encoding*/
8811 key = key * dims[i] + coords[i];
8816 color = color * dims[i] + coords[i];
8820 getAmpiInstance(comm)->split(color, key, newcomm, MPI_CART);
8822 ampiCommStruct &newc = getAmpiParent()->getCart(*newcomm);
8823 newc.setndims(num_remain_dims);
8825 const vector<int> &periods = c.getperiods();
8826 vector<int> periodsv;
8828 for (i = 0; i < ndims; i++) {
8829 if (remain_dims[i]) {
8830 dimsv.push_back(dims[i]);
8831 periodsv.push_back(periods[i]);
8834 newc.setdims(dimsv);
8835 newc.setperiods(periodsv);
8838 getAmpiInstance(*newcomm)->findNeighbors(*newcomm, getAmpiParent()->getRank(*newcomm), nborsv);
8839 newc.setnbors(nborsv);
8845 int AMPI_Type_get_envelope(MPI_Datatype datatype, int *ni, int *na, int *nd, int *combiner){
8846 AMPIAPI("AMPI_Type_get_envelope");
8847 return getDDT()->getEnvelope(datatype,ni,na,nd,combiner);
8851 int AMPI_Type_get_contents(MPI_Datatype datatype, int ni, int na, int nd, int i[],
8852 MPI_Aint a[], MPI_Datatype d[]){
8853 AMPIAPI("AMPI_Type_get_contents");
8854 return getDDT()->getContents(datatype,ni,na,nd,i,a,d);
8858 int AMPI_Pcontrol(const int level, ...) {
8859 //AMPIAPI("AMPI_Pcontrol");
8863 /******** AMPI Extensions to the MPI standard *********/
8866 int AMPI_Migrate(MPI_Info hints)
8868 AMPIAPI("AMPI_Migrate");
8870 char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
8872 AMPI_Info_get_nkeys(hints, &nkeys);
8874 for (int i=0; i<nkeys; i++) {
8875 AMPI_Info_get_nthkey(hints, i, key);
8876 AMPI_Info_get(hints, key, MPI_MAX_INFO_VAL, value, &exists);
8880 else if (strncmp(key, "ampi_load_balance", MPI_MAX_INFO_KEY) == 0) {
8882 if (strncmp(value, "sync", MPI_MAX_INFO_VAL) == 0) {
8885 else if (strncmp(value, "async", MPI_MAX_INFO_VAL) == 0) {
8886 TCHARM_Async_Migrate();
8888 else if (strncmp(value, "false", MPI_MAX_INFO_VAL) == 0) {
8892 CkPrintf("WARNING: Unknown MPI_Info value (%s) given to AMPI_Migrate for key: %s\n", value, key);
8895 else if (strncmp(key, "ampi_checkpoint", MPI_MAX_INFO_KEY) == 0) {
8897 if (strncmp(value, "true", MPI_MAX_INFO_VAL) == 0) {
8898 CkAbort("AMPI> Error: Value \"true\" is not supported for AMPI_Migrate key \"ampi_checkpoint\"!\n");
8900 else if (strncmp(value, "to_file=", strlen("to_file=")) == 0) {
8901 int offset = strlen("to_file=");
8902 int restart_dir_name_len = 0;
8903 AMPI_Info_get_valuelen(hints, key, &restart_dir_name_len, &exists);
8904 if (restart_dir_name_len > offset) {
8905 value[restart_dir_name_len] = '\0';
8908 CkAbort("AMPI> Error: No checkpoint directory name given to AMPI_Migrate\n");
8910 getAmpiInstance(MPI_COMM_WORLD)->barrier();
8911 getAmpiParent()->startCheckpoint(&value[offset]);
8913 else if (strncmp(value, "in_memory", MPI_MAX_INFO_VAL) == 0) {
8914 #if CMK_MEM_CHECKPOINT
8915 getAmpiInstance(MPI_COMM_WORLD)->barrier();
8916 getAmpiParent()->startCheckpoint("");
8918 CkPrintf("AMPI> Error: In-memory checkpoint/restart is not enabled!\n");
8919 CkAbort("AMPI> Error: Recompile Charm++/AMPI with CMK_MEM_CHECKPOINT.\n");
8922 else if (strncmp(value, "message_logging", MPI_MAX_INFO_VAL) == 0) {
8923 #if CMK_MESSAGE_LOGGING
8926 CkPrintf("AMPI> Error: Message logging is not enabled!\n");
8927 CkAbort("AMPI> Error: Recompile Charm++/AMPI with CMK_MESSAGE_LOGGING.\n");
8930 else if (strncmp(value, "false", MPI_MAX_INFO_VAL) == 0) {
8934 CkPrintf("WARNING: Unknown MPI_Info value (%s) given to AMPI_Migrate for key: %s\n", value, key);
8938 CkPrintf("WARNING: Unknown MPI_Info key given to AMPI_Migrate: %s\n", key);
8942 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
8943 ampi *currentAmpi = getAmpiInstance(MPI_COMM_WORLD);
8944 CpvAccess(_currentObj) = currentAmpi;
8947 #if CMK_BIGSIM_CHARM
8948 TRACE_BG_ADD_TAG("AMPI_MIGRATE");
8954 int AMPI_Evacuate(void)
8956 //AMPIAPI("AMPI_Evacuate");
8962 int AMPI_Migrate_to_pe(int dest)
8964 AMPIAPI("AMPI_Migrate_to_pe");
8965 TCHARM_Migrate_to(dest);
8966 #if CMK_BIGSIM_CHARM
8967 TRACE_BG_ADD_TAG("AMPI_MIGRATE_TO_PE");
8973 int AMPI_Set_migratable(int mig)
8975 AMPIAPI("AMPI_Set_migratable");
8977 getAmpiParent()->setMigratable((mig!=0));
8979 CkPrintf("WARNING: MPI_Set_migratable is not supported in this build of Charm++/AMPI.\n");
8985 int AMPI_Load_start_measure(void)
8987 AMPIAPI("AMPI_Load_start_measure");
8988 LBTurnInstrumentOn();
8993 int AMPI_Load_stop_measure(void)
8995 AMPIAPI("AMPI_Load_stop_measure");
8996 LBTurnInstrumentOff();
9001 int AMPI_Load_set_value(double value)
9003 AMPIAPI("AMPI_Load_set_value");
9004 ampiParent *ptr = getAmpiParent();
9005 ptr->setObjTime(value);
9009 void _registerampif(void) {
9014 int AMPI_Register_main(MPI_MainFn mainFn,const char *name)
9016 AMPIAPI("AMPI_Register_main");
9017 if (TCHARM_Element()==0)
9018 { // I'm responsible for building the TCHARM threads:
9019 ampiCreateMain(mainFn,name,strlen(name));
9025 void FTN_NAME(MPI_REGISTER_MAIN,mpi_register_main)
9026 (MPI_MainFn mainFn,const char *name,int nameLen)
9028 AMPIAPI("AMPI_register_main");
9029 if (TCHARM_Element()==0)
9030 { // I'm responsible for building the TCHARM threads:
9031 ampiCreateMain(mainFn,name,nameLen);
9036 int AMPI_Register_pup(MPI_PupFn fn, void *data, int *idx)
9038 AMPIAPI("AMPI_Register_pup");
9039 *idx = TCHARM_Register(data, fn);
9044 int AMPI_Register_about_to_migrate(MPI_MigrateFn fn)
9046 AMPIAPI("AMPI_Register_about_to_migrate");
9047 ampiParent *thisParent = getAmpiParent();
9048 thisParent->setUserAboutToMigrateFn(fn);
9053 int AMPI_Register_just_migrated(MPI_MigrateFn fn)
9055 AMPIAPI("AMPI_Register_just_migrated");
9056 ampiParent *thisParent = getAmpiParent();
9057 thisParent->setUserJustMigratedFn(fn);
9062 int AMPI_Get_pup_data(int idx, void *data)
9064 AMPIAPI("AMPI_Get_pup_data");
9065 data = TCHARM_Get_userdata(idx);
9070 int AMPI_Type_is_contiguous(MPI_Datatype datatype, int *flag)
9072 AMPIAPI("AMPI_Type_is_contiguous");
9073 *flag = getDDT()->isContig(datatype);
9078 int AMPI_Print(const char *str)
9080 AMPIAPI("AMPI_Print");
9081 ampiParent *ptr = getAmpiParent();
9082 CkPrintf("[%d] %s\n", ptr->thisIndex, str);
9087 int AMPI_Suspend(void)
9089 AMPIAPI("AMPI_Suspend");
9090 getAmpiParent()->block();
9095 int AMPI_Yield(void)
9097 AMPIAPI("AMPI_Yield");
9098 getAmpiParent()->yield();
9103 int AMPI_Resume(int dest, MPI_Comm comm)
9105 AMPIAPI("AMPI_Resume");
9106 getAmpiInstance(comm)->getProxy()[dest].unblock();
9111 int AMPI_System(const char *cmd)
9113 return TCHARM_System(cmd);
9117 int AMPI_Trace_begin(void)
9124 int AMPI_Trace_end(void)
9130 int AMPI_Install_idle_timer(void)
9133 beginHandle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)BeginIdle,NULL);
9134 endHandle = CcdCallOnConditionKeep(CcdPROCESSOR_END_IDLE,(CcdVoidFn)EndIdle,NULL);
9139 int AMPI_Uninstall_idle_timer(void)
9142 CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,beginHandle);
9143 CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY,endHandle);
9148 #if CMK_BIGSIM_CHARM
9149 extern "C" void startCFnCall(void *param,void *msg)
9152 ampi *ptr = (ampi*)param;
9153 ampi::bcastraw(NULL, 0, ptr->getProxy());
9154 delete (CkReductionMsg*)msg;
9158 int AMPI_Set_start_event(MPI_Comm comm)
9160 AMPIAPI("AMPI_Set_start_event");
9161 CkAssert(comm == MPI_COMM_WORLD);
9163 ampi *ptr = getAmpiInstance(comm);
9165 CkDDT_DataType *ddt_type = ptr->getDDT()->getType(MPI_INT);
9167 CkReductionMsg *msg=makeRednMsg(ddt_type, NULL, 0, MPI_INT, ptr->getRank(comm), MPI_SUM);
9168 if (CkMyPe() == 0) {
9169 CkCallback allreduceCB(startCFnCall, ptr);
9170 msg->setCallback(allreduceCB);
9172 ptr->contribute(msg);
9174 /*HACK: Use recv() to block until the reduction data comes back*/
9175 if(-1==ptr->recv(MPI_BCAST_TAG, -1, NULL, 0, MPI_INT, MPI_COMM_WORLD))
9176 CkAbort("AMPI> MPI_Allreduce called with different values on different processors!");
9182 int AMPI_Set_end_event(void)
9184 AMPIAPI("AMPI_Set_end_event");
9187 #endif // CMK_BIGSIM_CHARM
9192 comm = MPI_COMM_SELF;
9194 AMPI_Comm_rank(comm, &src);
9195 buf = getAmpiInstance(comm);
9198 bool GPUReq::test(MPI_Status *sts)
9203 bool GPUReq::itest(MPI_Status *sts)
9208 void GPUReq::complete(MPI_Status *sts)
9213 int GPUReq::wait(MPI_Status *sts)
9216 while (!statusIreq) {
9217 getAmpiParent()->block();
9222 void GPUReq::receive(ampi *ptr, AmpiMsg *msg)
9224 CkAbort("GPUReq::receive should never be called");
9227 void GPUReq::setComplete()
9232 class workRequestQueue;
9233 extern workRequestQueue *wrQueue;
9234 void enqueue(workRequestQueue *q, workRequest *wr);
9235 extern "C++" void setWRCallback(workRequest *wr, void *cb);
9237 void AMPI_GPU_complete(void *request, void* dummy)
9239 GPUReq *req = static_cast<GPUReq *>(request);
9241 ampi *ptr = static_cast<ampi *>(req->buf);
9246 int AMPI_GPU_Iinvoke(workRequest *to_call, MPI_Request *request)
9248 AMPIAPI("AMPI_GPU_Iinvoke");
9250 *request = ptr->postReq(new GPUReq());
9252 // A callback that completes the corresponding request
9253 CkCallback *cb = new CkCallback(&I_GPU_complete, newreq);
9254 setWRCallback(to_call, cb);
9256 enqueue(wrQueue, to_call);
9260 int AMPI_GPU_Invoke(workRequest *to_call)
9262 AMPIAPI("AMPI_GPU_Invoke");
9265 AMPI_GPU_Iinvoke(to_call, &req);
9266 AMPI_Wait(&req, MPI_STATUS_IGNORE);
9272 #include "ampi.def.h"