1 #ifndef AMPI_PRINT_MSG_SIZES
2 #define AMPI_PRINT_MSG_SIZES 0 // Record and print comm routines used & message sizes
6 #define AMPI_PRINT_IDLE 0
10 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
11 #include "ampiEvents.h" /*** for trace generation for projector *****/
12 #include "ampiProjections.h"
16 #include "bigsim_logs.h"
20 #include "register.h" // for _chareTable, _entryTable
23 /* change this to MPI_ERRORS_RETURN to not abort on errors */
24 #define AMPI_ERRHANDLER MPI_ERRORS_ARE_FATAL
26 /* change this define to "x" to trace all send/recv's */
27 #define MSG_ORDER_DEBUG(x) //x /* empty */
28 /* change this define to "x" to trace user calls */
29 #define USER_CALL_DEBUG(x) // ckout<<"vp "<<TCHARM_Element()<<": "<<x<<endl;
30 #define STARTUP_DEBUG(x) //ckout<<"ampi[pe "<<CkMyPe()<<"] "<< x <<endl;
31 #define FUNCCALL_DEBUG(x) //x /* empty */
33 /* For MPI_Get_library_version */
34 extern "C" const char * const CmiCommitID;
36 static CkDDT *getDDT(void) {
37 return getAmpiParent()->myDDT;
40 /* if error checking is disabled, ampiErrhandler is defined as a macro in ampiimpl.h */
41 #if AMPI_ERROR_CHECKING
42 inline int ampiErrhandler(const char* func, int errcode) {
43 if (AMPI_ERRHANDLER == MPI_ERRORS_ARE_FATAL && errcode != MPI_SUCCESS) {
44 // Abort with a nice message of the form: 'func' failed with error code 'errstr'.
45 // where 'func' is the name of the failed AMPI_ function and 'errstr'
46 // is the string returned by AMPI_Error_string for errcode.
47 int funclen = strlen(func);
48 const char* filler = " failed with error code ";
49 int fillerlen = strlen(filler);
51 char errstr[MPI_MAX_ERROR_STRING];
52 AMPI_Error_string(errcode, errstr, &errstrlen);
53 vector<char> str(funclen + fillerlen + errstrlen);
54 strcpy(&str[0], func);
55 strcat(&str[0], filler);
56 strcat(&str[0], errstr);
63 #if AMPI_PRINT_MSG_SIZES
64 #if !AMPI_ERROR_CHECKING
65 #error "AMPI_PRINT_MSG_SIZES requires AMPI error checking to be enabled!\n"
69 #include "ckliststring.h"
70 CkpvDeclare(CkListString, msgSizesRanks);
72 bool ampiParent::isRankRecordingMsgSizes(void) {
73 return (!CkpvAccess(msgSizesRanks).isEmpty() && CkpvAccess(msgSizesRanks).includes(thisIndex));
76 void ampiParent::recordMsgSize(const char* func, int msgSize) {
77 if (isRankRecordingMsgSizes()) {
78 msgSizes[func][msgSize]++;
83 #include <tr1/unordered_map>
84 typedef std::tr1::unordered_map<std::string, std::map<int, int> >::iterator outer_itr_t;
86 typedef std::unordered_map<std::string, std::map<int, int> >::iterator outer_itr_t;
88 typedef std::map<int, int>::iterator inner_itr_t;
90 void ampiParent::printMsgSizes(void) {
91 if (isRankRecordingMsgSizes()) {
92 // Prints msgSizes in the form: "AMPI_Routine: [ (num_msgs: msg_size) ... ]".
93 // Each routine has its messages sorted by size, smallest to largest.
95 ss << std::endl << "Rank " << thisIndex << ":" << std::endl;
96 for (outer_itr_t i = msgSizes.begin(); i != msgSizes.end(); ++i) {
97 ss << i->first << ": [ ";
98 for (inner_itr_t j = i->second.begin(); j != i->second.end(); ++j) {
99 ss << "(" << j->second << ": " << j->first << " B) ";
101 ss << "]" << std::endl;
103 CkPrintf("%s", ss.str().c_str());
106 #endif //AMPI_PRINT_MSG_SIZES
108 inline int checkCommunicator(const char* func, MPI_Comm comm) {
109 if (comm == MPI_COMM_NULL)
110 return ampiErrhandler(func, MPI_ERR_COMM);
114 inline int checkCount(const char* func, int count) {
116 return ampiErrhandler(func, MPI_ERR_COUNT);
120 inline int checkData(const char* func, MPI_Datatype data) {
121 if (data == MPI_DATATYPE_NULL)
122 return ampiErrhandler(func, MPI_ERR_TYPE);
126 inline int checkTag(const char* func, int tag) {
127 if (tag != MPI_ANY_TAG && (tag < 0 || tag > MPI_TAG_UB_VALUE))
128 return ampiErrhandler(func, MPI_ERR_TAG);
132 inline int checkRank(const char* func, int rank, MPI_Comm comm) {
134 AMPI_Comm_size(comm, &size);
135 if (((rank >= 0) && (rank < size)) ||
136 (rank == MPI_ANY_SOURCE) ||
137 (rank == MPI_PROC_NULL) ||
140 return ampiErrhandler(func, MPI_ERR_RANK);
143 inline int checkBuf(const char* func, const void *buf, int count) {
144 if ((count != 0 && buf == NULL) || buf == MPI_IN_PLACE)
145 return ampiErrhandler(func, MPI_ERR_BUFFER);
149 inline int errorCheck(const char* func, MPI_Comm comm, int ifComm, int count,
150 int ifCount, MPI_Datatype data, int ifData, int tag,
151 int ifTag, int rank, int ifRank, const void *buf1, int ifBuf1,
152 const void *buf2=0, int ifBuf2=0) {
155 ret = checkCommunicator(func, comm);
156 if (ret != MPI_SUCCESS)
157 return ampiErrhandler(func, ret);
160 ret = checkCount(func, count);
161 if (ret != MPI_SUCCESS)
162 return ampiErrhandler(func, ret);
165 ret = checkData(func, data);
166 if (ret != MPI_SUCCESS)
167 return ampiErrhandler(func, ret);
170 ret = checkTag(func, tag);
171 if (ret != MPI_SUCCESS)
172 return ampiErrhandler(func, ret);
175 ret = checkRank(func, rank, comm);
176 if (ret != MPI_SUCCESS)
177 return ampiErrhandler(func, ret);
180 ret = checkBuf(func, buf1, count);
181 if (ret != MPI_SUCCESS)
182 return ampiErrhandler(func, ret);
185 ret = checkBuf(func, buf2, count);
186 if (ret != MPI_SUCCESS)
187 return ampiErrhandler(func, ret);
189 #if AMPI_PRINT_MSG_SIZES
190 getAmpiParent()->recordMsgSize(func, getDDT()->getSize(data) * count);
195 //------------- startup -------------
196 static mpi_comm_worlds mpi_worlds;
198 int _mpi_nworlds; /*Accessed by ampif*/
199 int MPI_COMM_UNIVERSE[MPI_MAX_COMM_WORLDS]; /*Accessed by user code*/
204 void operator+=(const AmpiComplex &a) {
208 void operator*=(const AmpiComplex &a) {
209 float nu_re=re*a.re-im*a.im;
213 int operator>(const AmpiComplex &a) {
214 CkAbort("AMPI> Cannot compare complex numbers with MPI_MAX\n");
217 int operator<(const AmpiComplex &a) {
218 CkAbort("AMPI> Cannot compare complex numbers with MPI_MIN\n");
223 class AmpiDoubleComplex {
226 void operator+=(const AmpiDoubleComplex &a) {
230 void operator*=(const AmpiDoubleComplex &a) {
231 double nu_re=re*a.re-im*a.im;
235 int operator>(const AmpiDoubleComplex &a) {
236 CkAbort("AMPI> Cannot compare double complex numbers with MPI_MAX\n");
239 int operator<(const AmpiDoubleComplex &a) {
240 CkAbort("AMPI> Cannot compare double complex numbers with MPI_MIN\n");
245 class AmpiLongDoubleComplex {
248 void operator+=(const AmpiLongDoubleComplex &a) {
252 void operator*=(const AmpiLongDoubleComplex &a) {
253 long double nu_re=re*a.re-im*a.im;
257 int operator>(const AmpiLongDoubleComplex &a) {
258 CkAbort("AMPI> Cannot compare long double complex numbers with MPI_MAX\n");
261 int operator<(const AmpiLongDoubleComplex &a) {
262 CkAbort("AMPI> Cannot compare long double complex numbers with MPI_MIN\n");
267 typedef struct { float val; int idx; } FloatInt;
268 typedef struct { double val; int idx; } DoubleInt;
269 typedef struct { long val; int idx; } LongInt;
270 typedef struct { int val; int idx; } IntInt;
271 typedef struct { short val; int idx; } ShortInt;
272 typedef struct { long double val; int idx; } LongdoubleInt;
273 typedef struct { float val; float idx; } FloatFloat;
274 typedef struct { double val; double idx; } DoubleDouble;
276 /* For MPI_MAX, MPI_MIN, MPI_SUM, and MPI_PROD: */
277 #define MPI_OP_SWITCH(OPNAME) \
279 switch (*datatype) { \
280 case MPI_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(char); } break; \
281 case MPI_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed short int); } break; \
282 case MPI_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed int); } break; \
283 case MPI_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long); } break; \
284 case MPI_UNSIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned char); } break; \
285 case MPI_UNSIGNED_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned short); } break; \
286 case MPI_UNSIGNED: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned int); } break; \
287 case MPI_UNSIGNED_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long); } break; \
288 case MPI_FLOAT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(float); } break; \
289 case MPI_DOUBLE: for(i=0;i<(*len);i++) { MPI_OP_IMPL(double); } break; \
290 case MPI_COMPLEX: for(i=0;i<(*len);i++) { MPI_OP_IMPL(AmpiComplex); } break; \
291 case MPI_DOUBLE_COMPLEX: for(i=0;i<(*len);i++) { MPI_OP_IMPL(AmpiDoubleComplex); } break; \
292 case MPI_LONG_LONG_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long long); } break; \
293 case MPI_SIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed char); } break; \
294 case MPI_UNSIGNED_LONG_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long long); } break; \
295 case MPI_WCHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(wchar_t); } break; \
296 case MPI_INT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int8_t); } break; \
297 case MPI_INT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int16_t); } break; \
298 case MPI_INT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int32_t); } break; \
299 case MPI_INT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int64_t); } break; \
300 case MPI_UINT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint8_t); } break; \
301 case MPI_UINT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint16_t); } break; \
302 case MPI_UINT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint32_t); } break; \
303 case MPI_UINT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint64_t); } break; \
304 case MPI_FLOAT_COMPLEX: for(i=0;i<(*len);i++) { MPI_OP_IMPL(AmpiComplex); } break; \
305 case MPI_LONG_DOUBLE_COMPLEX: for(i=0;i<(*len);i++) { MPI_OP_IMPL(AmpiLongDoubleComplex); } break; \
306 case MPI_AINT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(MPI_Aint); } break; \
308 ckerr << "Type " << *datatype << " with Op "#OPNAME" not supported." << endl; \
309 CkAbort("Unsupported MPI datatype for MPI Op"); \
312 /* For MPI_LAND, MPI_LOR, and MPI_LXOR: */
313 #define MPI_LOGICAL_OP_SWITCH(OPNAME) \
315 switch (*datatype) { \
316 case MPI_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed short int); } break; \
317 case MPI_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed int); } break; \
318 case MPI_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long); } break; \
319 case MPI_UNSIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned char); } break; \
320 case MPI_UNSIGNED_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned short); } break; \
321 case MPI_UNSIGNED: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned int); } break; \
322 case MPI_UNSIGNED_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long); } break; \
323 case MPI_LONG_LONG_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long long); } break; \
324 case MPI_SIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed char); } break; \
325 case MPI_UNSIGNED_LONG_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long long); } break; \
326 case MPI_INT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int8_t); } break; \
327 case MPI_INT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int16_t); } break; \
328 case MPI_INT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int32_t); } break; \
329 case MPI_INT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int64_t); } break; \
330 case MPI_UINT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint8_t); } break; \
331 case MPI_UINT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint16_t); } break; \
332 case MPI_UINT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint32_t); } break; \
333 case MPI_UINT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint64_t); } break; \
334 case MPI_LOGICAL: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int); } break; \
335 case MPI_C_BOOL: for(i=0;i<(*len);i++) { MPI_OP_IMPL(bool); } break; \
337 ckerr << "Type " << *datatype << " with Op "#OPNAME" not supported." << endl; \
338 CkAbort("Unsupported MPI datatype for MPI Op"); \
341 /* For MPI_BAND, MPI_BOR, and MPI_BXOR: */
342 #define MPI_BITWISE_OP_SWITCH(OPNAME) \
344 switch (*datatype) { \
345 case MPI_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed short int); } break; \
346 case MPI_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed int); } break; \
347 case MPI_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long); } break; \
348 case MPI_UNSIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned char); } break; \
349 case MPI_UNSIGNED_SHORT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned short); } break; \
350 case MPI_UNSIGNED: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned int); } break; \
351 case MPI_UNSIGNED_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long); } break; \
352 case MPI_LONG_LONG_INT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed long long); } break; \
353 case MPI_SIGNED_CHAR: for(i=0;i<(*len);i++) { MPI_OP_IMPL(signed char); } break; \
354 case MPI_UNSIGNED_LONG_LONG: for(i=0;i<(*len);i++) { MPI_OP_IMPL(unsigned long long); } break; \
355 case MPI_INT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int8_t); } break; \
356 case MPI_INT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int16_t); } break; \
357 case MPI_INT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int32_t); } break; \
358 case MPI_INT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(int64_t); } break; \
359 case MPI_UINT8_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint8_t); } break; \
360 case MPI_UINT16_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint16_t); } break; \
361 case MPI_UINT32_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint32_t); } break; \
362 case MPI_UINT64_T: for(i=0;i<(*len);i++) { MPI_OP_IMPL(uint64_t); } break; \
363 case MPI_BYTE: for(i=0;i<(*len);i++) { MPI_OP_IMPL(char); } break; \
364 case MPI_AINT: for(i=0;i<(*len);i++) { MPI_OP_IMPL(MPI_Aint); } break; \
366 ckerr << "Type " << *datatype << " with Op "#OPNAME" not supported." << endl; \
367 CkAbort("Unsupported MPI datatype for MPI Op"); \
370 void MPI_MAX_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
371 #define MPI_OP_IMPL(type) \
372 if(((type *)invec)[i] > ((type *)inoutvec)[i]) ((type *)inoutvec)[i] = ((type *)invec)[i];
373 MPI_OP_SWITCH(MPI_MAX)
377 void MPI_MIN_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
378 #define MPI_OP_IMPL(type) \
379 if(((type *)invec)[i] < ((type *)inoutvec)[i]) ((type *)inoutvec)[i] = ((type *)invec)[i];
380 MPI_OP_SWITCH(MPI_MIN)
384 void MPI_SUM_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
385 #define MPI_OP_IMPL(type) \
386 ((type *)inoutvec)[i] += ((type *)invec)[i];
387 MPI_OP_SWITCH(MPI_SUM)
391 void MPI_PROD_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
392 #define MPI_OP_IMPL(type) \
393 ((type *)inoutvec)[i] *= ((type *)invec)[i];
394 MPI_OP_SWITCH(MPI_PROD)
398 void MPI_REPLACE_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
399 #define MPI_OP_IMPL(type) \
400 ((type *)inoutvec)[i] = ((type *)invec)[i];
401 MPI_OP_SWITCH(MPI_REPLACE)
405 void MPI_NO_OP_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
409 void MPI_LAND_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
410 #define MPI_OP_IMPL(type) \
411 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] && ((type *)invec)[i];
412 MPI_LOGICAL_OP_SWITCH(MPI_LAND)
416 void MPI_BAND_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
417 #define MPI_OP_IMPL(type) \
418 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] & ((type *)invec)[i];
419 MPI_BITWISE_OP_SWITCH(MPI_BAND)
423 void MPI_LOR_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
424 #define MPI_OP_IMPL(type) \
425 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] || ((type *)invec)[i];
426 MPI_LOGICAL_OP_SWITCH(MPI_LOR)
430 void MPI_BOR_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
431 #define MPI_OP_IMPL(type) \
432 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] | ((type *)invec)[i];
433 MPI_BITWISE_OP_SWITCH(MPI_BOR)
437 void MPI_LXOR_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
438 #define MPI_OP_IMPL(type) \
439 ((type *)inoutvec)[i] = (((type *)inoutvec)[i]&&(!((type *)invec)[i]))||(!(((type *)inoutvec)[i])&&((type *)invec)[i]);
440 MPI_LOGICAL_OP_SWITCH(MPI_LXOR)
444 void MPI_BXOR_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
445 #define MPI_OP_IMPL(type) \
446 ((type *)inoutvec)[i] = ((type *)inoutvec)[i] ^ ((type *)invec)[i];
447 MPI_BITWISE_OP_SWITCH(MPI_BXOR)
452 #define MIN(a,b) (a < b ? a : b)
455 void MPI_MAXLOC_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
460 for(i=0;i<(*len);i++){
461 if(((FloatInt *)invec)[i].val > ((FloatInt *)inoutvec)[i].val)
462 ((FloatInt *)inoutvec)[i] = ((FloatInt *)invec)[i];
463 else if(((FloatInt *)invec)[i].val == ((FloatInt *)inoutvec)[i].val)
464 ((FloatInt *)inoutvec)[i].idx = MIN(((FloatInt *)inoutvec)[i].idx, ((FloatInt *)invec)[i].idx);
468 for(i=0;i<(*len);i++){
469 if(((DoubleInt *)invec)[i].val > ((DoubleInt *)inoutvec)[i].val)
470 ((DoubleInt *)inoutvec)[i] = ((DoubleInt *)invec)[i];
471 else if(((DoubleInt *)invec)[i].val == ((DoubleInt *)inoutvec)[i].val)
472 ((DoubleInt *)inoutvec)[i].idx = MIN(((DoubleInt *)inoutvec)[i].idx, ((DoubleInt *)invec)[i].idx);
476 for(i=0;i<(*len);i++){
477 if(((LongInt *)invec)[i].val > ((LongInt *)inoutvec)[i].val)
478 ((LongInt *)inoutvec)[i] = ((LongInt *)invec)[i];
479 else if(((LongInt *)invec)[i].val == ((LongInt *)inoutvec)[i].val)
480 ((LongInt *)inoutvec)[i].idx = MIN(((LongInt *)inoutvec)[i].idx, ((LongInt *)invec)[i].idx);
484 for(i=0;i<(*len);i++){
485 if(((IntInt *)invec)[i].val > ((IntInt *)inoutvec)[i].val)
486 ((IntInt *)inoutvec)[i] = ((IntInt *)invec)[i];
487 else if(((IntInt *)invec)[i].val == ((IntInt *)inoutvec)[i].val)
488 ((IntInt *)inoutvec)[i].idx = MIN(((IntInt *)inoutvec)[i].idx, ((IntInt *)invec)[i].idx);
492 for(i=0;i<(*len);i++){
493 if(((ShortInt *)invec)[i].val > ((ShortInt *)inoutvec)[i].val)
494 ((ShortInt *)inoutvec)[i] = ((ShortInt *)invec)[i];
495 else if(((ShortInt *)invec)[i].val == ((ShortInt *)inoutvec)[i].val)
496 ((ShortInt *)inoutvec)[i].idx = MIN(((ShortInt *)inoutvec)[i].idx, ((ShortInt *)invec)[i].idx);
499 case MPI_LONG_DOUBLE_INT:
500 for(i=0;i<(*len);i++){
501 if(((LongdoubleInt *)invec)[i].val > ((LongdoubleInt *)inoutvec)[i].val)
502 ((LongdoubleInt *)inoutvec)[i] = ((LongdoubleInt *)invec)[i];
503 else if(((LongdoubleInt *)invec)[i].val == ((LongdoubleInt *)inoutvec)[i].val)
504 ((LongdoubleInt *)inoutvec)[i].idx = MIN(((LongdoubleInt *)inoutvec)[i].idx, ((LongdoubleInt *)invec)[i].idx);
508 for(i=0;i<(*len);i++){
509 if(((FloatFloat *)invec)[i].val > ((FloatFloat *)inoutvec)[i].val)
510 ((FloatFloat *)inoutvec)[i] = ((FloatFloat *)invec)[i];
511 else if(((FloatFloat *)invec)[i].val == ((FloatFloat *)inoutvec)[i].val)
512 ((FloatFloat *)inoutvec)[i].idx = MIN(((FloatFloat *)inoutvec)[i].idx, ((FloatFloat *)invec)[i].idx);
516 for(i=0;i<(*len);i++){
517 if(((DoubleDouble *)invec)[i].val > ((DoubleDouble *)inoutvec)[i].val)
518 ((DoubleDouble *)inoutvec)[i] = ((DoubleDouble *)invec)[i];
519 else if(((DoubleDouble *)invec)[i].val == ((DoubleDouble *)inoutvec)[i].val)
520 ((DoubleDouble *)inoutvec)[i].idx = MIN(((DoubleDouble *)inoutvec)[i].idx, ((DoubleDouble *)invec)[i].idx);
524 ckerr << "Type " << *datatype << " with Op MPI_MAXLOC not supported." << endl;
529 void MPI_MINLOC_USER_FN( void *invec, void *inoutvec, int *len, MPI_Datatype *datatype){
533 for(i=0;i<(*len);i++){
534 if(((FloatInt *)invec)[i].val < ((FloatInt *)inoutvec)[i].val)
535 ((FloatInt *)inoutvec)[i] = ((FloatInt *)invec)[i];
536 else if(((FloatInt *)invec)[i].val == ((FloatInt *)inoutvec)[i].val)
537 ((FloatInt *)inoutvec)[i].idx = MIN(((FloatInt *)inoutvec)[i].idx, ((FloatInt *)invec)[i].idx);
541 for(i=0;i<(*len);i++){
542 if(((DoubleInt *)invec)[i].val < ((DoubleInt *)inoutvec)[i].val)
543 ((DoubleInt *)inoutvec)[i] = ((DoubleInt *)invec)[i];
544 else if(((DoubleInt *)invec)[i].val == ((DoubleInt *)inoutvec)[i].val)
545 ((DoubleInt *)inoutvec)[i].idx = MIN(((DoubleInt *)inoutvec)[i].idx, ((DoubleInt *)invec)[i].idx);
549 for(i=0;i<(*len);i++){
550 if(((LongInt *)invec)[i].val < ((LongInt *)inoutvec)[i].val)
551 ((LongInt *)inoutvec)[i] = ((LongInt *)invec)[i];
552 else if(((LongInt *)invec)[i].val == ((LongInt *)inoutvec)[i].val)
553 ((LongInt *)inoutvec)[i].idx = MIN(((LongInt *)inoutvec)[i].idx, ((LongInt *)invec)[i].idx);
557 for(i=0;i<(*len);i++){
558 if(((IntInt *)invec)[i].val < ((IntInt *)inoutvec)[i].val)
559 ((IntInt *)inoutvec)[i] = ((IntInt *)invec)[i];
560 else if(((IntInt *)invec)[i].val == ((IntInt *)inoutvec)[i].val)
561 ((IntInt *)inoutvec)[i].idx = MIN(((IntInt *)inoutvec)[i].idx, ((IntInt *)invec)[i].idx);
565 for(i=0;i<(*len);i++){
566 if(((ShortInt *)invec)[i].val < ((ShortInt *)inoutvec)[i].val)
567 ((ShortInt *)inoutvec)[i] = ((ShortInt *)invec)[i];
568 else if(((ShortInt *)invec)[i].val == ((ShortInt *)inoutvec)[i].val)
569 ((ShortInt *)inoutvec)[i].idx = MIN(((ShortInt *)inoutvec)[i].idx, ((ShortInt *)invec)[i].idx);
572 case MPI_LONG_DOUBLE_INT:
573 for(i=0;i<(*len);i++){
574 if(((LongdoubleInt *)invec)[i].val < ((LongdoubleInt *)inoutvec)[i].val)
575 ((LongdoubleInt *)inoutvec)[i] = ((LongdoubleInt *)invec)[i];
576 else if(((LongdoubleInt *)invec)[i].val == ((LongdoubleInt *)inoutvec)[i].val)
577 ((LongdoubleInt *)inoutvec)[i].idx = MIN(((LongdoubleInt *)inoutvec)[i].idx, ((LongdoubleInt *)invec)[i].idx);
581 for(i=0;i<(*len);i++){
582 if(((FloatFloat *)invec)[i].val < ((FloatFloat *)inoutvec)[i].val)
583 ((FloatFloat *)inoutvec)[i] = ((FloatFloat *)invec)[i];
584 else if(((FloatFloat *)invec)[i].val == ((FloatFloat *)inoutvec)[i].val)
585 ((FloatFloat *)inoutvec)[i].idx = MIN(((FloatFloat *)inoutvec)[i].idx, ((FloatFloat *)invec)[i].idx);
589 for(i=0;i<(*len);i++){
590 if(((DoubleDouble *)invec)[i].val < ((DoubleDouble *)inoutvec)[i].val)
591 ((DoubleDouble *)inoutvec)[i] = ((DoubleDouble *)invec)[i];
592 else if(((DoubleDouble *)invec)[i].val == ((DoubleDouble *)inoutvec)[i].val)
593 ((DoubleDouble *)inoutvec)[i].idx = MIN(((DoubleDouble *)inoutvec)[i].idx, ((DoubleDouble *)invec)[i].idx);
597 ckerr << "Type " << *datatype << " with Op MPI_MINLOC not supported." << endl;
603 * AMPI's generic reducer type, AmpiReducer, is used only
604 * for MPI_Op/MPI_Datatype combinations that Charm++ does
605 * not have built-in support for. AmpiReducer reduction
606 * contributions all contain an AmpiOpHeader, that contains
607 * the function pointer to an MPI_User_function* that is
608 * applied to all contributions in AmpiReducerFunc().
610 * If AmpiReducer is used, the final reduction message will
611 * have an additional sizeof(AmpiOpHeader) bytes in the
612 * buffer before any user data. ampi::processRednMsg() strips
615 * If a non-commutative (user-defined) reduction is used,
616 * ampi::processNoncommutativeRednMsg() strips the headers
617 * and applies the op to all contributions in rank order.
619 CkReduction::reducerType AmpiReducer;
621 // every msg contains a AmpiOpHeader structure before user data
622 CkReductionMsg *AmpiReducerFunc(int nMsg, CkReductionMsg **msgs){
623 AmpiOpHeader *hdr = (AmpiOpHeader *)msgs[0]->getData();
625 int szhdr, szdata, len;
626 MPI_User_function* func;
629 szdata = hdr->szdata;
631 szhdr = sizeof(AmpiOpHeader);
633 CkReductionMsg *retmsg = CkReductionMsg::buildNew(szhdr+szdata,NULL,AmpiReducer,msgs[0]);
634 void *retPtr = (char *)retmsg->getData() + szhdr;
635 for(int i=1;i<nMsg;i++){
636 (*func)((void *)((char *)msgs[i]->getData()+szhdr),retPtr,&len,&dtype);
641 static CkReduction::reducerType getBuiltinReducerType(MPI_Datatype type, MPI_Op op)
645 if (getDDT()->getSize(MPI_INT32_T) != getDDT()->getSize(MPI_INT)) break;
646 // else: fall thru to MPI_INT
649 case MPI_MAX: return CkReduction::max_int;
650 case MPI_MIN: return CkReduction::min_int;
651 case MPI_SUM: return CkReduction::sum_int;
652 case MPI_PROD: return CkReduction::product_int;
653 case MPI_LAND: return CkReduction::logical_and_int;
654 case MPI_LOR: return CkReduction::logical_or_int;
655 case MPI_LXOR: return CkReduction::logical_xor_int;
656 case MPI_BAND: return CkReduction::bitvec_and_int;
657 case MPI_BOR: return CkReduction::bitvec_or_int;
658 case MPI_BXOR: return CkReduction::bitvec_xor_int;
663 case MPI_MAX: return CkReduction::max_float;
664 case MPI_MIN: return CkReduction::min_float;
665 case MPI_SUM: return CkReduction::sum_float;
666 case MPI_PROD: return CkReduction::product_float;
671 case MPI_MAX: return CkReduction::max_double;
672 case MPI_MIN: return CkReduction::min_double;
673 case MPI_SUM: return CkReduction::sum_double;
674 case MPI_PROD: return CkReduction::product_double;
678 if (getDDT()->getSize(MPI_INT8_T) != getDDT()->getSize(MPI_CHAR)) break;
679 // else: fall thru to MPI_CHAR
682 case MPI_MAX: return CkReduction::max_char;
683 case MPI_MIN: return CkReduction::min_char;
684 case MPI_SUM: return CkReduction::sum_char;
685 case MPI_PROD: return CkReduction::product_char;
689 if (getDDT()->getSize(MPI_INT16_T) != getDDT()->getSize(MPI_SHORT)) break;
690 // else: fall thru to MPI_SHORT
693 case MPI_MAX: return CkReduction::max_short;
694 case MPI_MIN: return CkReduction::min_short;
695 case MPI_SUM: return CkReduction::sum_short;
696 case MPI_PROD: return CkReduction::product_short;
701 case MPI_MAX: return CkReduction::max_long;
702 case MPI_MIN: return CkReduction::min_long;
703 case MPI_SUM: return CkReduction::sum_long;
704 case MPI_PROD: return CkReduction::product_long;
708 if (getDDT()->getSize(MPI_INT64_T) != getDDT()->getSize(MPI_LONG_LONG)) break;
709 // else: fall thru to MPI_LONG_LONG
712 case MPI_MAX: return CkReduction::max_long_long;
713 case MPI_MIN: return CkReduction::min_long_long;
714 case MPI_SUM: return CkReduction::sum_long_long;
715 case MPI_PROD: return CkReduction::product_long_long;
719 if (getDDT()->getSize(MPI_UINT8_T) != getDDT()->getSize(MPI_UNSIGNED_CHAR)) break;
720 // else: fall thru to MPI_UNSIGNED_CHAR
721 case MPI_UNSIGNED_CHAR:
723 case MPI_MAX: return CkReduction::max_uchar;
724 case MPI_MIN: return CkReduction::min_uchar;
725 case MPI_SUM: return CkReduction::sum_uchar;
726 case MPI_PROD: return CkReduction::product_uchar;
730 if (getDDT()->getSize(MPI_UINT16_T) != getDDT()->getSize(MPI_UNSIGNED_SHORT)) break;
731 // else: fall thru to MPI_UNSIGNED_SHORT
732 case MPI_UNSIGNED_SHORT:
734 case MPI_MAX: return CkReduction::max_ushort;
735 case MPI_MIN: return CkReduction::min_ushort;
736 case MPI_SUM: return CkReduction::sum_ushort;
737 case MPI_PROD: return CkReduction::product_ushort;
741 if (getDDT()->getSize(MPI_UINT32_T) != getDDT()->getSize(MPI_UNSIGNED)) break;
742 // else: fall thru to MPI_UNSIGNED
745 case MPI_MAX: return CkReduction::max_uint;
746 case MPI_MIN: return CkReduction::min_uint;
747 case MPI_SUM: return CkReduction::sum_uint;
748 case MPI_PROD: return CkReduction::product_uint;
751 case MPI_UNSIGNED_LONG:
753 case MPI_MAX: return CkReduction::max_ulong;
754 case MPI_MIN: return CkReduction::min_ulong;
755 case MPI_SUM: return CkReduction::sum_ulong;
756 case MPI_PROD: return CkReduction::product_ulong;
760 if (getDDT()->getSize(MPI_UINT64_T) != getDDT()->getSize(MPI_UNSIGNED_LONG_LONG)) break;
761 // else: fall thru to MPI_UNSIGNED_LONG_LONG
762 case MPI_UNSIGNED_LONG_LONG:
764 case MPI_MAX: return CkReduction::max_ulong_long;
765 case MPI_MIN: return CkReduction::min_ulong_long;
766 case MPI_SUM: return CkReduction::sum_ulong_long;
767 case MPI_PROD: return CkReduction::product_ulong_long;
772 case MPI_LAND: return CkReduction::logical_and_bool;
773 case MPI_LOR: return CkReduction::logical_or_bool;
774 case MPI_LXOR: return CkReduction::logical_xor_bool;
779 case MPI_LAND: return CkReduction::logical_and_int;
780 case MPI_LOR: return CkReduction::logical_or_int;
781 case MPI_LXOR: return CkReduction::logical_xor_int;
786 case MPI_BAND: return CkReduction::bitvec_and_bool;
787 case MPI_BOR: return CkReduction::bitvec_or_bool;
788 case MPI_BXOR: return CkReduction::bitvec_xor_bool;
794 return CkReduction::invalid;
799 int tag_ub,host,io,wtime_is_global,appnum,lastusedcode,universe_size;
801 int win_disp_unit,win_create_flavor,win_model;
805 tag_ub = MPI_TAG_UB_VALUE;
806 host = MPI_PROC_NULL;
810 lastusedcode = MPI_ERR_LASTCODE;
815 win_create_flavor = MPI_WIN_FLAVOR_CREATE;
816 win_model = MPI_WIN_SEPARATE;
821 // ------------ startup support -----------
822 int _ampi_fallback_setup_count;
823 CDECL void AMPI_Setup(void);
824 FDECL void FTN_NAME(AMPI_SETUP,ampi_setup)(void);
826 FDECL void FTN_NAME(MPI_MAIN,mpi_main)(void);
828 /*Main routine used when missing MPI_Setup routine*/
830 void AMPI_Fallback_Main(int argc,char **argv)
833 AMPI_Main_cpp(argc,argv);
834 AMPI_Main_c(argc,argv);
835 FTN_NAME(MPI_MAIN,mpi_main)();
838 void ampiCreateMain(MPI_MainFn mainFn, const char *name,int nameLen);
839 /*Startup routine used if user *doesn't* write
840 a TCHARM_User_setup routine.
843 void AMPI_Setup_Switch(void) {
844 _ampi_fallback_setup_count=0;
845 FTN_NAME(AMPI_SETUP,ampi_setup)();
847 if (_ampi_fallback_setup_count==2)
848 { //Missing AMPI_Setup in both C and Fortran:
849 ampiCreateMain(AMPI_Fallback_Main,"default",strlen("default"));
853 int AMPI_RDMA_THRESHOLD = AMPI_RDMA_THRESHOLD_DEFAULT;
854 int AMPI_SMP_RDMA_THRESHOLD = AMPI_SMP_RDMA_THRESHOLD_DEFAULT;
855 static bool nodeinit_has_been_called=false;
856 CtvDeclare(ampiParent*, ampiPtr);
857 CtvDeclare(bool, ampiInitDone);
858 CtvDeclare(void*,stackBottom);
859 CtvDeclare(bool, ampiFinalized);
860 CkpvDeclare(Builtin_kvs, bikvs);
861 CkpvDeclare(int, ampiThreadLevel);
864 long ampiCurrentStackUsage(void){
867 unsigned long p1 = (unsigned long)((void*)&localVariable);
868 unsigned long p2 = (unsigned long)(CtvAccess(stackBottom));
877 void FTN_NAME(AMPICURRENTSTACKUSAGE, ampicurrentstackusage)(void){
878 long usage = ampiCurrentStackUsage();
879 CkPrintf("[%d] Stack usage is currently %ld\n", CkMyPe(), usage);
883 void AMPI_threadstart(void *data);
884 static int AMPI_threadstart_idx = -1;
886 #if CMK_TRACE_ENABLED
887 CsvExtern(funcmap*, tcharm_funcmap);
890 static void ampiNodeInit(void)
892 #if CMK_TRACE_ENABLED
893 TCharm::nodeInit(); // make sure tcharm_funcmap is set up
894 int funclength = sizeof(funclist)/sizeof(char*);
895 for (int i=0; i<funclength; i++) {
896 int event_id = traceRegisterUserEvent(funclist[i], -1);
897 CsvAccess(tcharm_funcmap)->insert(std::pair<std::string, int>(funclist[i], event_id));
900 // rename chare & function to something reasonable
901 // TODO: find a better way to do this
902 for (int i=0; i<_chareTable.size(); i++){
903 if (strcmp(_chareTable[i]->name, "dummy_thread_chare") == 0)
904 _chareTable[i]->name = "AMPI";
906 for (int i=0; i<_entryTable.size(); i++){
907 if (strcmp(_entryTable[i]->name, "dummy_thread_ep") == 0)
908 _entryTable[i]->name = "rank";
913 for(int i=0;i<MPI_MAX_COMM_WORLDS; i++)
915 MPI_COMM_UNIVERSE[i] = MPI_COMM_WORLD+1+i;
917 TCHARM_Set_fallback_setup(AMPI_Setup_Switch);
919 /* read AMPI environment variables */
921 bool rdmaSet = false;
922 if ((value = getenv("AMPI_RDMA_THRESHOLD"))) {
923 AMPI_RDMA_THRESHOLD = atoi(value);
926 if ((value = getenv("AMPI_SMP_RDMA_THRESHOLD"))) {
927 AMPI_SMP_RDMA_THRESHOLD = atoi(value);
930 if (rdmaSet && CkMyNode() == 0) {
932 CkPrintf("AMPI> RDMA threshold is %d Bytes and SMP RDMA threshold is %d Bytes.\n", AMPI_RDMA_THRESHOLD, AMPI_SMP_RDMA_THRESHOLD);
934 CkPrintf("Warning: AMPI RDMA threshold ignored since AMPI RDMA is disabled.\n");
938 AmpiReducer = CkReduction::addReducer(AmpiReducerFunc, true /*streamable*/);
940 CkAssert(AMPI_threadstart_idx == -1); // only initialize once
941 AMPI_threadstart_idx = TCHARM_Register_thread_function(AMPI_threadstart);
943 nodeinit_has_been_called=true;
945 // ASSUME NO ANYTIME MIGRATION and STATIC INSERTON
946 _isAnytimeMigration = false;
947 _isStaticInsertion = true;
951 static double totalidle=0.0, startT=0.0;
952 static int beginHandle, endHandle;
953 static void BeginIdle(void *dummy,double curWallTime)
955 startT = curWallTime;
957 static void EndIdle(void *dummy,double curWallTime)
959 totalidle += curWallTime - startT;
963 static void ampiProcInit(void){
964 CtvInitialize(ampiParent*, ampiPtr);
965 CtvInitialize(bool,ampiInitDone);
966 CtvInitialize(bool,ampiFinalized);
967 CtvInitialize(void*,stackBottom);
969 CkpvInitialize(int, ampiThreadLevel);
970 CkpvAccess(ampiThreadLevel) = MPI_THREAD_SINGLE;
972 CkpvInitialize(Builtin_kvs, bikvs); // built-in key-values
973 CkpvAccess(bikvs) = Builtin_kvs();
975 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
978 initAmpiProjections();
981 char **argv=CkGetArgv();
982 msgLogWrite = CmiGetArgFlag(argv, "+msgLogWrite");
983 if (CmiGetArgIntDesc(argv,"+msgLogRead", &msgLogRank, "Re-play message processing order for AMPI")) {
987 if (CmiGetArgStringDesc(argv, "+msgLogRanks", &procs, "A list of AMPI processors to record , e.g. 0,10,20-30")) {
988 msgLogRanks.set(procs);
990 CmiGetArgString(argv, "+msgLogFilename", &msgLogFilename);
992 if (msgLogWrite) CkPrintf("Writing AMPI messages of rank %s to log: %s\n", procs?procs:"", msgLogFilename);
993 if (msgLogRead) CkPrintf("Reading AMPI messages of rank %s from log: %s\n", procs?procs:"", msgLogFilename);
997 #if AMPI_PRINT_MSG_SIZES
998 // Only record and print message sizes if this option is given, and only for those ranks.
999 // Running with the '+syncprint' option is recommended if printing from multiple ranks.
1001 CkpvInitialize(CkListString, msgSizesRanks);
1002 if (CmiGetArgStringDesc(CkGetArgv(), "+msgSizesRanks", &ranks,
1003 "A list of AMPI ranks to record and print message sizes on, e.g. 0,10,20-30")) {
1004 CkpvAccess(msgSizesRanks).set(ranks);
1010 static inline int record_msglog(int rank){
1011 return msgLogRanks.includes(rank);
1015 PUPfunctionpointer(MPI_MainFn)
1017 class MPI_threadstart_t {
1020 MPI_threadstart_t() {}
1021 MPI_threadstart_t(MPI_MainFn fn_):fn(fn_) {}
1023 char **argv=CmiCopyArgs(CkGetArgv());
1024 int argc=CkGetArgc();
1026 // Set a pointer to somewhere close to the bottom of the stack.
1027 // This is used for roughly estimating the stack usage later.
1028 CtvAccess(stackBottom) = &argv;
1030 #if !CMK_NO_BUILD_SHARED
1031 // If charm++ is built with shared libraries, it does not support
1032 // a custom AMPI_Setup method and always uses AMPI_Fallback_Main.
1033 // Works around bug #1508.
1034 if (_ampi_fallback_setup_count != 2 && CkMyPe() == 0) {
1035 CkAbort("AMPI> The application provided a custom AMPI_Setup() method, "
1036 "but AMPI is built with shared library support. This is an unsupported "
1037 "configuration. Please recompile charm++/AMPI without `-build-shared` or "
1038 "remove the AMPI_Setup() function from your application.\n");
1040 AMPI_Fallback_Main(argc,argv);
1045 void pup(PUP::er &p) {
1049 PUPmarshall(MPI_threadstart_t)
1052 void AMPI_threadstart(void *data)
1054 STARTUP_DEBUG("MPI_threadstart")
1055 MPI_threadstart_t t;
1057 #if CMK_TRACE_IN_CHARM
1058 if(CpvAccess(traceOn)) CthTraceResume(CthSelf());
1063 void ampiCreateMain(MPI_MainFn mainFn, const char *name,int nameLen)
1065 STARTUP_DEBUG("ampiCreateMain")
1066 int _nchunks=TCHARM_Get_num_chunks();
1067 //Make a new threads array:
1068 MPI_threadstart_t s(mainFn);
1069 memBuf b; pupIntoBuf(b,s);
1070 TCHARM_Create_data(_nchunks,AMPI_threadstart_idx,
1071 b.getData(), b.getSize());
1074 /* TCharm Semaphore ID's for AMPI startup */
1075 #define AMPI_TCHARM_SEMAID 0x00A34100 /* __AMPI__ */
1076 #define AMPI_BARRIER_SEMAID 0x00A34200 /* __AMPI__ */
1078 static CProxy_ampiWorlds ampiWorldsGroup;
1080 void ampiParent::initOps(void)
1082 ops.resize(MPI_NO_OP+1);
1083 ops[MPI_MAX] = OpStruct(MPI_MAX_USER_FN);
1084 ops[MPI_MIN] = OpStruct(MPI_MIN_USER_FN);
1085 ops[MPI_SUM] = OpStruct(MPI_SUM_USER_FN);
1086 ops[MPI_PROD] = OpStruct(MPI_PROD_USER_FN);
1087 ops[MPI_LAND] = OpStruct(MPI_LAND_USER_FN);
1088 ops[MPI_BAND] = OpStruct(MPI_BAND_USER_FN);
1089 ops[MPI_LOR] = OpStruct(MPI_LOR_USER_FN);
1090 ops[MPI_BOR] = OpStruct(MPI_BOR_USER_FN);
1091 ops[MPI_LXOR] = OpStruct(MPI_LXOR_USER_FN);
1092 ops[MPI_BXOR] = OpStruct(MPI_BXOR_USER_FN);
1093 ops[MPI_MAXLOC] = OpStruct(MPI_MAXLOC_USER_FN);
1094 ops[MPI_MINLOC] = OpStruct(MPI_MINLOC_USER_FN);
1095 ops[MPI_REPLACE] = OpStruct(MPI_REPLACE_USER_FN);
1096 ops[MPI_NO_OP] = OpStruct(MPI_NO_OP_USER_FN);
1099 // Create MPI_COMM_SELF from MPI_COMM_WORLD
1100 static void createCommSelf(void) {
1101 STARTUP_DEBUG("ampiInit> creating MPI_COMM_SELF")
1103 MPI_Group worldGroup, selfGroup;
1104 int ranks[1] = { getAmpiInstance(MPI_COMM_WORLD)->getRank() };
1106 AMPI_Comm_group(MPI_COMM_WORLD, &worldGroup);
1107 AMPI_Group_incl(worldGroup, 1, ranks, &selfGroup);
1108 AMPI_Comm_create(MPI_COMM_WORLD, selfGroup, &selfComm);
1109 AMPI_Comm_set_name(selfComm, "MPI_COMM_SELF");
1111 CkAssert(selfComm == MPI_COMM_SELF);
1112 STARTUP_DEBUG("ampiInit> created MPI_COMM_SELF")
1116 Called from MPI_Init, a collective initialization call:
1117 creates a new AMPI array and attaches it to the current
1118 set of TCHARM threads.
1120 static ampi *ampiInit(char **argv)
1122 FUNCCALL_DEBUG(CkPrintf("Calling from proc %d for tcharm element %d\n", CkMyPe(), TCHARM_Element());)
1123 if (CtvAccess(ampiInitDone)) return NULL; /* Already called ampiInit */
1124 STARTUP_DEBUG("ampiInit> begin")
1128 CkArrayOptions opts;
1129 CProxy_ampiParent parent;
1130 if (TCHARM_Element()==0) //the rank of a tcharm object
1131 { /* I'm responsible for building the arrays: */
1132 STARTUP_DEBUG("ampiInit> creating arrays")
1134 // FIXME: Need to serialize global communicator allocation in one place.
1135 //Allocate the next communicator
1136 if(_mpi_nworlds == MPI_MAX_COMM_WORLDS)
1138 CkAbort("AMPI> Number of registered comm_worlds exceeded limit.\n");
1140 int new_idx=_mpi_nworlds;
1141 new_world=MPI_COMM_WORLD+new_idx;
1143 //Create and attach the ampiParent array
1145 opts=TCHARM_Attach_start(&threads,&_nchunks);
1146 opts.setSectionAutoDelegate(false);
1147 CkArrayCreatedMsg *m;
1148 CProxy_ampiParent::ckNew(new_world, threads, opts, CkCallbackResumeThread((void*&)m));
1149 parent = CProxy_ampiParent(m->aid);
1151 STARTUP_DEBUG("ampiInit> array size "<<_nchunks);
1153 int *barrier = (int *)TCharm::get()->semaGet(AMPI_BARRIER_SEMAID);
1155 FUNCCALL_DEBUG(CkPrintf("After BARRIER: sema size %d from tcharm's ele %d\n", TCharm::get()->sema.size(), TCHARM_Element());)
1157 if (TCHARM_Element()==0)
1159 //Make a new ampi array
1162 ampiCommStruct worldComm(new_world,empty,_nchunks);
1164 CkArrayCreatedMsg *m;
1165 CProxy_ampi::ckNew(parent, worldComm, opts, CkCallbackResumeThread((void*&)m));
1166 arr = CProxy_ampi(m->aid);
1169 //Broadcast info. to the mpi_worlds array
1170 // FIXME: remove race condition from MPI_COMM_UNIVERSE broadcast
1171 ampiCommStruct newComm(new_world,arr,_nchunks);
1172 if (ampiWorldsGroup.ckGetGroupID().isZero())
1173 ampiWorldsGroup=CProxy_ampiWorlds::ckNew(newComm);
1175 ampiWorldsGroup.add(newComm);
1176 STARTUP_DEBUG("ampiInit> arrays created")
1179 // Find our ampi object:
1180 ampi *ptr=(ampi *)TCharm::get()->semaGet(AMPI_TCHARM_SEMAID);
1181 CtvAccess(ampiInitDone)=true;
1182 CtvAccess(ampiFinalized)=false;
1183 STARTUP_DEBUG("ampiInit> complete")
1184 #if CMK_BIGSIM_CHARM
1185 // TRACE_BG_AMPI_START(ptr->getThread(), "AMPI_START");
1186 TRACE_BG_ADD_TAG("AMPI_START");
1189 getAmpiParent()->initOps(); // initialize reduction operations
1190 getAmpiParent()->setCommAttr(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, &_nchunks);
1191 ptr->setCommName("MPI_COMM_WORLD");
1193 getAmpiParent()->ampiInitCallDone = 0;
1195 CProxy_ampi cbproxy = ptr->getProxy();
1196 CkCallback cb(CkReductionTarget(ampi, allInitDone), cbproxy[0]);
1197 ptr->contribute(cb);
1199 ampiParent *thisParent = getAmpiParent();
1200 while(thisParent->ampiInitCallDone!=1){
1201 thisParent->getTCharmThread()->stop();
1203 * thisParent needs to be updated in case of the parent is being pupped.
1204 * In such case, thisParent got changed
1206 thisParent = getAmpiParent();
1211 #if CMK_BIGSIM_CHARM
1212 BgSetStartOutOfCore();
1218 /// This group is used to broadcast the MPI_COMM_UNIVERSE communicators.
1219 class ampiWorlds : public CBase_ampiWorlds {
1221 ampiWorlds(const ampiCommStruct &nextWorld) {
1222 ampiWorldsGroup=thisgroup;
1225 ampiWorlds(CkMigrateMessage *m): CBase_ampiWorlds(m) {}
1226 void pup(PUP::er &p) { }
1227 void add(const ampiCommStruct &nextWorld) {
1228 int new_idx=nextWorld.getComm()-(MPI_COMM_WORLD);
1229 mpi_worlds[new_idx]=nextWorld;
1230 if (_mpi_nworlds<=new_idx) _mpi_nworlds=new_idx+1;
1231 STARTUP_DEBUG("ampiInit> listed MPI_COMM_UNIVERSE "<<new_idx)
1235 //-------------------- ampiParent -------------------------
1236 ampiParent::ampiParent(MPI_Comm worldNo_,CProxy_TCharm threads_)
1237 :threads(threads_), worldNo(worldNo_), isTmpRProxySet(false)
1239 int barrier = 0x1234;
1240 STARTUP_DEBUG("ampiParent> starting up")
1243 userAboutToMigrateFn=NULL;
1244 userJustMigratedFn=NULL;
1248 // Allocate an empty groupStruct to represent MPI_EMPTY_GROUP
1249 groups.push_back(new groupStruct);
1253 thread->semaPut(AMPI_BARRIER_SEMAID,&barrier);
1254 AsyncEvacuate(false);
1257 ampiParent::ampiParent(CkMigrateMessage *msg):CBase_ampiParent(msg) {
1264 AsyncEvacuate(false);
1267 PUPfunctionpointer(MPI_MigrateFn)
1269 void ampiParent::pup(PUP::er &p) {
1292 p|userAboutToMigrateFn;
1293 p|userJustMigratedFn;
1300 #if AMPI_PRINT_MSG_SIZES
1305 void ampiParent::prepareCtv(void) {
1306 thread=threads[thisIndex].ckLocal();
1307 if (thread==NULL) CkAbort("AMPIParent cannot find its thread!\n");
1308 CtvAccessOther(thread->getThread(),ampiPtr) = this;
1309 STARTUP_DEBUG("ampiParent> found TCharm")
1312 void ampiParent::init(){
1313 resumeOnRecv = false;
1314 resumeOnColl = false;
1317 if(msgLogWrite && record_msglog(thisIndex)){
1319 sprintf(fname, "%s.%d", msgLogFilename,thisIndex);
1320 #if CMK_PROJECTIONS_USE_ZLIB && 0
1321 fMsgLog = gzopen(fname,"wb");
1322 toPUPer = new PUP::tozDisk(fMsgLog);
1324 fMsgLog = fopen(fname,"wb");
1325 CkAssert(fMsgLog != NULL);
1326 toPUPer = new PUP::toDisk(fMsgLog);
1328 }else if(msgLogRead){
1330 sprintf(fname, "%s.%d", msgLogFilename,msgLogRank);
1331 #if CMK_PROJECTIONS_USE_ZLIB && 0
1332 fMsgLog = gzopen(fname,"rb");
1333 fromPUPer = new PUP::fromzDisk(fMsgLog);
1335 fMsgLog = fopen(fname,"rb");
1336 CkAssert(fMsgLog != NULL);
1337 fromPUPer = new PUP::fromDisk(fMsgLog);
1339 CkPrintf("AMPI> opened message log file: %s for replay\n", fname);
1344 void ampiParent::finalize(){
1346 if(msgLogWrite && record_msglog(thisIndex)){
1348 #if CMK_PROJECTIONS_USE_ZLIB && 0
1353 }else if(msgLogRead){
1355 #if CMK_PROJECTIONS_USE_ZLIB && 0
1364 void ampiParent::setUserAboutToMigrateFn(MPI_MigrateFn f) {
1365 userAboutToMigrateFn = f;
1368 void ampiParent::setUserJustMigratedFn(MPI_MigrateFn f) {
1369 userJustMigratedFn = f;
1372 void ampiParent::ckAboutToMigrate(void) {
1373 if (userAboutToMigrateFn) {
1374 (*userAboutToMigrateFn)();
1378 void ampiParent::ckJustMigrated(void) {
1379 ArrayElement1D::ckJustMigrated();
1381 if (userJustMigratedFn) {
1382 (*userJustMigratedFn)();
1386 void ampiParent::ckJustRestored(void) {
1387 FUNCCALL_DEBUG(CkPrintf("Call just restored from ampiParent[%d] with ampiInitCallDone %d\n", thisIndex, ampiInitCallDone);)
1388 ArrayElement1D::ckJustRestored();
1392 ampiParent::~ampiParent() {
1393 STARTUP_DEBUG("ampiParent> destructor called");
1397 //Children call this when they are first created or just migrated
1398 TCharm *ampiParent::registerAmpi(ampi *ptr,ampiCommStruct s,bool forMigration)
1400 if (thread==NULL) prepareCtv(); //Prevents CkJustMigrated race condition
1402 if (s.getComm()>=MPI_COMM_WORLD)
1403 { //We now have our COMM_WORLD-- register it
1404 //Note that split communicators don't keep a raw pointer, so
1405 //they don't need to re-register on migration.
1406 if (worldPtr!=NULL) CkAbort("One ampiParent has two MPI_COMM_WORLDs");
1412 { //Register the new communicator:
1413 MPI_Comm comm = s.getComm();
1414 STARTUP_DEBUG("ampiParent> registering new communicator "<<comm)
1415 if (comm>=MPI_COMM_WORLD) {
1416 // Pass the new ampi to the waiting ampiInit
1417 thread->semaPut(AMPI_TCHARM_SEMAID, ptr);
1418 } else if (isSplit(comm)) {
1419 splitChildRegister(s);
1420 } else if (isGroup(comm)) {
1421 groupChildRegister(s);
1422 } else if (isCart(comm)) {
1423 cartChildRegister(s);
1424 } else if (isGraph(comm)) {
1425 graphChildRegister(s);
1426 } else if (isInter(comm)) {
1427 interChildRegister(s);
1428 } else if (isIntra(comm)) {
1429 intraChildRegister(s);
1431 CkAbort("ampiParent received child with bad communicator");
1437 // reduction client data - preparation for checkpointing
1438 class ckptClientStruct {
1441 ampiParent *ampiPtr;
1442 ckptClientStruct(const char *s, ampiParent *a): dname(s), ampiPtr(a) {}
1445 static void checkpointClient(void *param,void *msg)
1447 ckptClientStruct *client = (ckptClientStruct*)param;
1448 const char *dname = client->dname;
1449 ampiParent *ampiPtr = client->ampiPtr;
1450 ampiPtr->Checkpoint(strlen(dname), dname);
1454 void ampiParent::startCheckpoint(const char* dname){
1456 ckptClientStruct *clientData = new ckptClientStruct(dname, this);
1457 CkCallback *cb = new CkCallback(checkpointClient, clientData);
1458 thisProxy.ckSetReductionClient(cb);
1464 #if CMK_BIGSIM_CHARM
1465 TRACE_BG_ADD_TAG("CHECKPOINT_RESUME");
1469 void ampiParent::Checkpoint(int len, const char* dname){
1471 // memory checkpoint
1472 CkCallback cb(CkIndex_ampiParent::ResumeThread(),thisArrayID);
1473 CkStartMemCheckpoint(cb);
1477 strncpy(dirname,dname,len);
1479 CkCallback cb(CkIndex_ampiParent::ResumeThread(),thisArrayID);
1480 CkStartCheckpoint(dirname,cb);
1484 void ampiParent::ResumeThread(void){
1488 int ampiParent::createKeyval(MPI_Comm_copy_attr_function *copy_fn, MPI_Comm_delete_attr_function *delete_fn,
1489 int *keyval, void* extra_state){
1490 KeyvalNode* newnode = new KeyvalNode(copy_fn, delete_fn, extra_state);
1491 int idx = kvlist.size();
1492 kvlist.resize(idx+1);
1493 kvlist[idx] = newnode;
1498 int ampiParent::freeKeyval(int *keyval){
1499 #if AMPI_ERROR_CHECKING
1500 if(*keyval<0 || *keyval >= kvlist.size() || !kvlist[*keyval])
1501 return MPI_ERR_KEYVAL;
1503 delete kvlist[*keyval];
1504 kvlist[*keyval] = NULL;
1505 *keyval = MPI_KEYVAL_INVALID;
1509 int ampiParent::setUserKeyval(MPI_Comm comm, int keyval, void *attribute_val){
1510 #if AMPI_ERROR_CHECKING
1511 if(keyval<0 || keyval >= kvlist.size() || (kvlist[keyval]==NULL))
1512 return MPI_ERR_KEYVAL;
1514 ampiCommStruct &cs = *(ampiCommStruct *)&comm2CommStruct(comm);
1515 // Enlarge the keyval list:
1516 if(cs.getKeyvals().size()<=keyval) cs.getKeyvals().resize(keyval+1, NULL);
1517 cs.getKeyvals()[keyval]=attribute_val;
1521 int ampiParent::setWinAttr(MPI_Win win, int keyval, void* attribute_val){
1522 if(kv_set_builtin(keyval,attribute_val))
1524 MPI_Comm comm = (getAmpiParent()->getWinStruct(win))->comm;
1525 return setUserKeyval(comm, keyval, attribute_val);
1528 int ampiParent::setCommAttr(MPI_Comm comm, int keyval, void* attribute_val){
1529 if(kv_set_builtin(keyval,attribute_val))
1531 return setUserKeyval(comm, keyval, attribute_val);
1534 bool ampiParent::kv_set_builtin(int keyval, void* attribute_val) {
1536 case MPI_TAG_UB: /*immutable*/ return false;
1537 case MPI_HOST: /*immutable*/ return false;
1538 case MPI_IO: /*immutable*/ return false;
1539 case MPI_WTIME_IS_GLOBAL: /*immutable*/ return false;
1540 case MPI_APPNUM: /*immutable*/ return false;
1541 case MPI_LASTUSEDCODE: /*immutable*/ return false;
1542 case MPI_UNIVERSE_SIZE: (CkpvAccess(bikvs).universe_size) = *((int*)attribute_val); return true;
1543 case MPI_WIN_BASE: (CkpvAccess(bikvs).win_base) = attribute_val; return true;
1544 case MPI_WIN_SIZE: (CkpvAccess(bikvs).win_size) = *((MPI_Aint*)attribute_val); return true;
1545 case MPI_WIN_DISP_UNIT: (CkpvAccess(bikvs).win_disp_unit) = *((int*)attribute_val); return true;
1546 case MPI_WIN_CREATE_FLAVOR: (CkpvAccess(bikvs).win_create_flavor) = *((int*)attribute_val); return true;
1547 case MPI_WIN_MODEL: (CkpvAccess(bikvs).win_model) = *((int*)attribute_val); return true;
1548 case AMPI_MY_WTH: /*immutable*/ return false;
1549 case AMPI_NUM_WTHS: /*immutable*/ return false;
1550 case AMPI_MY_PROCESS: /*immutable*/ return false;
1551 case AMPI_NUM_PROCESSES: /*immutable*/ return false;
1552 default: return false;
1556 bool ampiParent::kv_get_builtin(int keyval) {
1558 case MPI_TAG_UB: kv_builtin_storage = &(CkpvAccess(bikvs).tag_ub); return true;
1559 case MPI_HOST: kv_builtin_storage = &(CkpvAccess(bikvs).host); return true;
1560 case MPI_IO: kv_builtin_storage = &(CkpvAccess(bikvs).io); return true;
1561 case MPI_WTIME_IS_GLOBAL: kv_builtin_storage = &(CkpvAccess(bikvs).wtime_is_global); return true;
1562 case MPI_APPNUM: kv_builtin_storage = &(CkpvAccess(bikvs).appnum); return true;
1563 case MPI_LASTUSEDCODE: kv_builtin_storage = &(CkpvAccess(bikvs).lastusedcode); return true;
1564 case MPI_UNIVERSE_SIZE: kv_builtin_storage = &(CkpvAccess(bikvs).universe_size); return true;
1565 case MPI_WIN_BASE: win_base_storage = &(CkpvAccess(bikvs).win_base); return true;
1566 case MPI_WIN_SIZE: win_size_storage = &(CkpvAccess(bikvs).win_size); return true;
1567 case MPI_WIN_DISP_UNIT: kv_builtin_storage = &(CkpvAccess(bikvs).win_disp_unit); return true;
1568 case MPI_WIN_CREATE_FLAVOR: kv_builtin_storage = &(CkpvAccess(bikvs).win_create_flavor); return true;
1569 case MPI_WIN_MODEL: kv_builtin_storage = &(CkpvAccess(bikvs).win_model); return true;
1570 default: return false;
1574 bool ampiParent::getBuiltinKeyval(int keyval, void *attribute_val) {
1575 if (kv_get_builtin(keyval)){
1576 /* All builtin keyvals are ints except MPI_WIN_BASE, which is a pointer
1577 * to the window's base address in C but an integer representation of
1578 * the base address in Fortran.
1579 * Also, MPI_WIN_SIZE is an MPI_Aint. */
1580 if (keyval == MPI_WIN_BASE)
1581 *((void**)attribute_val) = *win_base_storage;
1582 else if (keyval == MPI_WIN_SIZE)
1583 *(MPI_Aint**)attribute_val = win_size_storage;
1585 *(int **)attribute_val = kv_builtin_storage;
1589 case AMPI_MY_WTH: *(int *)attribute_val = CkMyPe(); return true;
1590 case AMPI_NUM_WTHS: *(int *)attribute_val = CkNumPes(); return true;
1591 case AMPI_MY_PROCESS: *(int *)attribute_val = CkMyNode(); return true;
1592 case AMPI_NUM_PROCESSES: *(int *)attribute_val = CkNumNodes(); return true;
1598 bool ampiParent::getUserKeyval(MPI_Comm comm, int keyval, void *attribute_val, int *flag) {
1600 if (keyval<0 || keyval >= kvlist.size() || (kvlist[keyval]==NULL))
1602 ampiCommStruct &cs=*(ampiCommStruct *)&comm2CommStruct(comm);
1603 if (keyval>=cs.getKeyvals().size())
1604 return true; /* we don't have a value yet */
1605 if (cs.getKeyvals()[keyval]==NULL)
1606 return true; /* we had a value, but now it's NULL */
1607 /* Otherwise, we have a good value */
1609 *(void **)attribute_val = cs.getKeyvals()[keyval];
1613 int ampiParent::getCommAttr(MPI_Comm comm, int keyval, void *attribute_val, int *flag) {
1615 if (getBuiltinKeyval(keyval, attribute_val)) {
1619 if (getUserKeyval(comm, keyval, attribute_val, flag))
1621 return MPI_ERR_KEYVAL;
1624 int ampiParent::getWinAttr(MPI_Win win, int keyval, void *attribute_val, int *flag) {
1626 if (getBuiltinKeyval(keyval, attribute_val)) {
1630 MPI_Comm comm = (getAmpiParent()->getWinStruct(win))->comm;
1631 if (getUserKeyval(comm, keyval, attribute_val, flag))
1633 return MPI_ERR_KEYVAL;
1636 int ampiParent::deleteCommAttr(MPI_Comm comm, int keyval){
1637 /* no way to delete an attribute: just overwrite it with NULL */
1638 return setUserKeyval(comm, keyval, NULL);
1641 int ampiParent::deleteWinAttr(MPI_Win win, int keyval){
1642 /* no way to delete an attribute: just overwrite it with NULL */
1643 MPI_Comm comm = (getAmpiParent()->getWinStruct(win))->comm;
1644 return setUserKeyval(comm, keyval, NULL);
1648 * AMPI Message Matching (Amm) Interface
1649 * messages are matched based on 2 ints: [tag, src]
1651 struct AmmEntryStruct
1655 int tags[AMM_NTAGS];
1658 struct AmmTableStruct
1666 AmmTable result = (AmmTable)malloc(sizeof(struct AmmTableStruct));
1668 result->lasth = &(result->first);
1672 void AmmFree(AmmTable t)
1674 if (t==NULL) return;
1675 #if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
1676 if (t->first!=NULL) CmiAbort("AMPI> Cannot free a non-empty message table!");
1681 /* free all table entries but not the space pointed by "msg" */
1682 void AmmFreeAll(AmmTable t)
1685 if (t==NULL) return;
1688 AmmEntry toDel = cur;
1694 void AmmPut(AmmTable t, int* tags, void* msg)
1696 AmmEntry e = (AmmEntry)malloc(sizeof(struct AmmEntryStruct));
1699 for (int i=0; i<AMM_NTAGS; i++) e->tags[i] = tags[i];
1701 t->lasth = &(e->next);
1704 static bool AmmMatch(const int tags1[AMM_NTAGS], const int tags2[AMM_NTAGS])
1706 if (tags1[AMM_TAG]==tags2[AMM_TAG] && tags1[AMM_SRC]==tags2[AMM_SRC]) {
1707 // tag and src match
1710 else if (tags1[AMM_TAG]==tags2[AMM_TAG] && (tags1[AMM_SRC]==MPI_ANY_SOURCE || tags2[AMM_SRC]==MPI_ANY_SOURCE)) {
1711 // tag matches, src is MPI_ANY_SOURCE
1714 else if (tags1[AMM_SRC]==tags2[AMM_SRC] && (tags1[AMM_TAG]==MPI_ANY_TAG || tags2[AMM_TAG]==MPI_ANY_TAG)) {
1715 // src matches, tag is MPI_ANY_TAG
1718 else if ((tags1[AMM_SRC]==MPI_ANY_SOURCE || tags2[AMM_SRC]==MPI_ANY_SOURCE) && (tags1[AMM_TAG]==MPI_ANY_TAG || tags2[AMM_TAG]==MPI_ANY_TAG)) {
1719 // src and tag are MPI_ANY
1728 void* AmmGet(AmmTable t, const int tags[AMM_NTAGS], int* rtags)
1734 /* added by Chao Mei in case that t is already freed
1735 * which happens in ~ampi() when doing out-of-core emulation for AMPI programs */
1736 if (t==NULL) return NULL;
1741 if (ent==NULL) return NULL;
1742 if (AmmMatch(tags, ent->tags)) {
1743 if (rtags) for (int i=0; i<AMM_NTAGS; i++) rtags[i] = ent->tags[i];
1745 // unlike probe, delete the matched entry:
1746 AmmEntry next = ent->next;
1748 if (next==NULL) t->lasth = enth;
1752 enth = &(ent->next);
1756 void* AmmProbe(AmmTable t, const int tags[AMM_NTAGS], int* rtags)
1762 /* added by Chao Mei in case that t is already freed
1763 * which happens in ~ampi() when doing out-of-core emulation for AMPI programs */
1764 if (t==NULL) return NULL;
1769 if (ent==NULL) return NULL;
1770 if (AmmMatch(tags, ent->tags)) {
1771 if (rtags) for (int i=0; i<AMM_NTAGS; i++) rtags[i] = ent->tags[i];
1775 enth = &(ent->next);
1780 int AmmEntries(AmmTable t)
1783 AmmEntry e = t->first;
1791 AmmTable AmmPup(pup_er p, AmmTable t, AmmPupMessageFn msgpup)
1795 if (!pup_isUnpacking(p)) {
1797 AmmEntry e = t->first;
1798 nentries = AmmEntries(t);
1799 pup_int(p, &nentries);
1801 pup_ints(p, e->tags, AMM_NTAGS);
1805 if (pup_isDeleting(p)) {
1809 if (pup_isDeleting(p)) {
1820 pup_int(p, &nentries);
1821 for (int i=0; i<nentries; i++) {
1824 tags = (int*)malloc(AMM_NTAGS*sizeof(int));
1825 pup_ints(p, tags, AMM_NTAGS);
1827 AmmPut(t, tags, msg);
1832 return NULL; // <- never executed
1835 //----------------------- ampi -------------------------
1836 void ampi::init(void) {
1842 AsyncEvacuate(false);
1847 /* this constructor only exists so we can create an empty array during split */
1848 CkAbort("Default ampi constructor should never be called");
1851 ampi::ampi(CkArrayID parent_,const ampiCommStruct &s):parentProxy(parent_)
1855 myComm=s; myComm.setArrayID(thisArrayID);
1856 myRank=myComm.getRankForIndex(thisIndex);
1861 posted_ireqs = AmmNew();
1864 ampi::ampi(CkMigrateMessage *msg):CBase_ampi(msg)
1869 void ampi::ckJustMigrated(void)
1872 ArrayElement1D::ckJustMigrated();
1875 void ampi::ckJustRestored(void)
1877 FUNCCALL_DEBUG(CkPrintf("Call just restored from ampi[%d]\n", thisIndex);)
1879 ArrayElement1D::ckJustRestored();
1882 void ampi::findParent(bool forMigration) {
1883 STARTUP_DEBUG("ampi> finding my parent")
1884 parent=parentProxy[thisIndex].ckLocal();
1885 if (parent==NULL) CkAbort("AMPI can't find its parent!");
1886 thread=parent->registerAmpi(this,myComm,forMigration);
1887 if (thread==NULL) CkAbort("AMPI can't find its thread!");
1890 //The following method should be called on the first element of the
1892 void ampi::allInitDone(){
1893 FUNCCALL_DEBUG(CkPrintf("All mpi_init have been called!\n");)
1894 thisProxy.setInitDoneFlag();
1897 void ampi::setInitDoneFlag(){
1898 parent->ampiInitCallDone=1;
1899 parent->getTCharmThread()->start();
1902 static void cmm_pup_ampi_message(pup_er p,void **msg) {
1903 CkPupMessage(*(PUP::er *)p,msg,1);
1904 if (pup_isDeleting(p)) delete (AmpiMsg *)*msg;
1907 static void cmm_pup_posted_ireq(pup_er p,void **msg) {
1908 pup_int(p, (int *)msg);
1911 void ampi::pup(PUP::er &p)
1921 if (!p.isUnpacking()) {
1923 nonnull = blockingReq->getType();
1930 if (p.isUnpacking()) {
1933 blockingReq = new IReq;
1936 blockingReq = new RednReq;
1938 case MPI_GATHER_REQ:
1939 blockingReq = new GatherReq;
1941 case MPI_GATHERV_REQ:
1942 blockingReq = new GathervReq;
1945 blockingReq = new SendReq;
1948 blockingReq = new SsendReq;
1951 blockingReq = new IATAReq;
1955 blockingReq->pup(p);
1959 if (p.isDeleting()) {
1960 delete blockingReq; blockingReq = NULL;
1963 msgs=AmmPup((pup_er)&p,msgs,cmm_pup_ampi_message);
1965 posted_ireqs = AmmPup((pup_er)&p, posted_ireqs, cmm_pup_posted_ireq);
1972 if (CkInRestarting() || _BgOutOfCoreFlag==1) {
1973 // in restarting, we need to flush messages
1974 int tags[2] = { MPI_ANY_TAG, MPI_ANY_SOURCE };
1976 AmpiMsg *msg = (AmpiMsg *) AmmGet(msgs, tags, (int*)&sts);
1979 msg = (AmpiMsg *) AmmGet(msgs, tags, (int*)&sts);
1983 delete blockingReq; blockingReq = NULL;
1985 AmmFreeAll(posted_ireqs);
1988 //------------------------ Communicator Splitting ---------------------
1989 class ampiSplitKey {
1992 int color; //New class of processes we'll belong to
1993 int key; //To determine rank in new ordering
1994 int rank; //Rank in old ordering
1996 ampiSplitKey(int nextSplitComm_,int color_,int key_,int rank_)
1997 :nextSplitComm(nextSplitComm_), color(color_), key(key_), rank(rank_) {}
2000 #define MPI_INTER 10
2002 /* "type" may indicate whether call is for a cartesian topology etc. */
2003 void ampi::split(int color,int key,MPI_Comm *dest, int type)
2005 #if CMK_BIGSIM_CHARM
2006 void *curLog; // store current log in timeline
2007 _TRACE_BG_TLINE_END(&curLog);
2009 if (type == MPI_CART) {
2010 ampiSplitKey splitKey(parent->getNextCart(),color,key,myRank);
2011 int rootIdx=myComm.getIndexForRank(0);
2012 CkCallback cb(CkIndex_ampi::splitPhase1(0),CkArrayIndex1D(rootIdx),myComm.getProxy());
2013 contribute(sizeof(splitKey),&splitKey,CkReduction::concat,cb);
2015 thread->suspend(); //Resumed by ampiParent::cartChildRegister
2016 MPI_Comm newComm=parent->getNextCart()-1;
2019 else if (type == MPI_GRAPH) {
2020 ampiSplitKey splitKey(parent->getNextGraph(),color,key,myRank);
2021 int rootIdx=myComm.getIndexForRank(0);
2022 CkCallback cb(CkIndex_ampi::splitPhase1(0),CkArrayIndex1D(rootIdx),myComm.getProxy());
2023 contribute(sizeof(splitKey),&splitKey,CkReduction::concat,cb);
2025 thread->suspend(); //Resumed by ampiParent::graphChildRegister
2026 MPI_Comm newComm=parent->getNextGraph()-1;
2029 else if (type == MPI_INTER) {
2030 ampiSplitKey splitKey(parent->getNextInter(),color,key,myRank);
2031 int rootIdx=myComm.getIndexForRank(0);
2032 CkCallback cb(CkIndex_ampi::splitPhaseInter(0),CkArrayIndex1D(rootIdx),myComm.getProxy());
2033 contribute(sizeof(splitKey),&splitKey,CkReduction::concat,cb);
2035 thread->suspend(); //Resumed by ampiParent::interChildRegister
2036 MPI_Comm newComm=parent->getNextInter()-1;
2040 ampiSplitKey splitKey(parent->getNextSplit(),color,key,myRank);
2041 int rootIdx=myComm.getIndexForRank(0);
2042 CkCallback cb(CkIndex_ampi::splitPhase1(0),CkArrayIndex1D(rootIdx),myComm.getProxy());
2043 contribute(sizeof(splitKey),&splitKey,CkReduction::concat,cb);
2045 thread->suspend(); //Resumed by ampiParent::splitChildRegister
2046 MPI_Comm newComm=parent->getNextSplit()-1;
2049 #if CMK_BIGSIM_CHARM
2050 _TRACE_BG_SET_INFO(NULL, "SPLIT_RESUME", NULL, 0);
2055 int compareAmpiSplitKey(const void *a_, const void *b_) {
2056 const ampiSplitKey *a=(const ampiSplitKey *)a_;
2057 const ampiSplitKey *b=(const ampiSplitKey *)b_;
2058 if (a->color!=b->color) return a->color-b->color;
2059 if (a->key!=b->key) return a->key-b->key;
2060 return a->rank-b->rank;
2063 // Caller needs to eventually call newAmpi.doneInserting()
2064 CProxy_ampi ampi::createNewChildAmpiSync() {
2065 CkArrayOptions opts;
2066 opts.bindTo(parentProxy);
2067 opts.setSectionAutoDelegate(false);
2068 opts.setNumInitial(0);
2069 CkArrayID unusedAID;
2070 ampiCommStruct unusedComm;
2071 CkCallback cb(CkCallback::resumeThread);
2072 CProxy_ampi::ckNew(unusedAID, unusedComm, opts, cb);
2073 CkArrayCreatedMsg *newAmpiMsg = static_cast<CkArrayCreatedMsg*>(cb.thread_delay());
2074 CProxy_ampi newAmpi = newAmpiMsg->aid;
2079 void ampi::splitPhase1(CkReductionMsg *msg)
2081 //Order the keys, which orders the ranks properly:
2082 int nKeys=msg->getSize()/sizeof(ampiSplitKey);
2083 ampiSplitKey *keys=(ampiSplitKey *)msg->getData();
2084 if (nKeys!=myComm.getSize()) CkAbort("ampi::splitReduce expected a split contribution from every rank!");
2085 qsort(keys,nKeys,sizeof(ampiSplitKey),compareAmpiSplitKey);
2087 MPI_Comm newComm = -1;
2088 for(int i=0;i<nKeys;i++){
2089 if(keys[i].nextSplitComm>newComm)
2090 newComm = keys[i].nextSplitComm;
2093 //Loop over the sorted keys, which gives us the new arrays:
2094 int lastColor=keys[0].color-1; //The color we're building an array for
2095 CProxy_ampi lastAmpi; //The array for lastColor
2096 int lastRoot=0; //C value for new rank 0 process for latest color
2097 ampiCommStruct lastComm; //Communicator info. for latest color
2098 for (int c=0;c<nKeys;c++) {
2099 if (keys[c].color!=lastColor)
2100 { //Hit a new color-- need to build a new communicator and array
2101 lastColor=keys[c].color;
2104 if (c!=0) lastAmpi.doneInserting();
2105 lastAmpi = createNewChildAmpiSync();
2107 vector<int> indices; //Maps rank to array indices for new array
2108 for (int i=c;i<nKeys;i++) {
2109 if (keys[i].color!=lastColor) break; //Done with this color
2110 int idx=myComm.getIndexForRank(keys[i].rank);
2111 indices.push_back(idx);
2114 //FIXME: create a new communicator for each color, instead of
2115 // (confusingly) re-using the same MPI_Comm number for each.
2116 lastComm=ampiCommStruct(newComm,lastAmpi,indices.size(),indices);
2118 int newRank=c-lastRoot;
2119 int newIdx=lastComm.getIndexForRank(newRank);
2121 lastAmpi[newIdx].insert(parentProxy,lastComm);
2123 lastAmpi.doneInserting();
2128 void ampi::splitPhaseInter(CkReductionMsg *msg)
2130 //Order the keys, which orders the ranks properly:
2131 int nKeys=msg->getSize()/sizeof(ampiSplitKey);
2132 ampiSplitKey *keys=(ampiSplitKey *)msg->getData();
2133 if (nKeys!=myComm.getSize()) CkAbort("ampi::splitReduce expected a split contribution from every rank!");
2134 qsort(keys,nKeys,sizeof(ampiSplitKey),compareAmpiSplitKey);
2136 MPI_Comm newComm = -1;
2137 for(int i=0;i<nKeys;i++){
2138 if(keys[i].nextSplitComm>newComm)
2139 newComm = keys[i].nextSplitComm; // FIXME: use nextSplitr instead of nextInter?
2142 //Loop over the sorted keys, which gives us the new arrays:
2143 int lastColor=keys[0].color-1; //The color we're building an array for
2144 CProxy_ampi lastAmpi; //The array for lastColor
2145 int lastRoot=0; //C value for new rank 0 process for latest color
2146 ampiCommStruct lastComm; //Communicator info. for latest color
2148 lastAmpi = createNewChildAmpiSync();
2150 for (int c=0;c<nKeys;c++) {
2151 vector<int> indices; // Maps rank to array indices for new array
2152 if (keys[c].color!=lastColor)
2153 { //Hit a new color-- need to build a new communicator and array
2154 lastColor=keys[c].color;
2157 for (int i=c;i<nKeys;i++) {
2158 if (keys[i].color!=lastColor) break; //Done with this color
2159 int idx=myComm.getIndexForRank(keys[i].rank);
2160 indices.push_back(idx);
2164 lastComm=ampiCommStruct(newComm,lastAmpi,indices.size(),indices, myComm.getRemoteIndices());
2165 for (int i=0; i<indices.size(); i++) {
2166 lastAmpi[indices[i]].insert(parentProxy,lastComm);
2168 lastAmpi.doneInserting();
2173 parentProxy[0].ExchangeProxy(lastAmpi);
2177 //...newly created array elements register with the parent, which calls:
2178 void ampiParent::splitChildRegister(const ampiCommStruct &s) {
2179 int idx=s.getComm()-MPI_COMM_FIRST_SPLIT;
2180 if (splitComm.size()<=idx) splitComm.resize(idx+1);
2181 splitComm[idx]=new ampiCommStruct(s);
2182 thread->resume(); //Matches suspend at end of ampi::split
2185 //-----------------create communicator from group--------------
2186 // The procedure is like that of comm_split very much,
2187 // so the code is shamelessly copied from above
2188 // 1. reduction to make sure all members have called
2189 // 2. the root in the old communicator create the new array
2190 // 3. ampiParent::register is called to register new array as new comm
2195 vecStruct():nextgroup(-1){}
2196 vecStruct(int nextgroup_, groupStruct vec_)
2197 : nextgroup(nextgroup_), vec(vec_) { }
2200 void ampi::commCreate(const groupStruct vec,MPI_Comm* newcomm){
2203 CkCallback cb(CkReductionTarget(ampi,commCreatePhase1),CkArrayIndex1D(rootIdx),myComm.getProxy());
2204 MPI_Comm nextgroup = parent->getNextGroup();
2205 contribute(sizeof(nextgroup), &nextgroup,CkReduction::max_int,cb);
2207 if(getPosOp(thisIndex,vec)>=0){
2208 thread->suspend(); //Resumed by ampiParent::groupChildRegister
2209 MPI_Comm retcomm = parent->getNextGroup()-1;
2212 *newcomm = MPI_COMM_NULL;
2216 void ampi::insertNewChildAmpiElements(MPI_Comm nextComm, CProxy_ampi newAmpi) {
2217 ampiCommStruct newCommStruct = ampiCommStruct(nextComm, newAmpi, tmpVec.size(), tmpVec);
2218 for (int i = 0; i < tmpVec.size(); ++i)
2219 newAmpi[tmpVec[i]].insert(parentProxy, newCommStruct);
2220 newAmpi.doneInserting();
2223 void ampi::commCreatePhase1(MPI_Comm nextGroupComm){
2224 CProxy_ampi newAmpi = createNewChildAmpiSync();
2225 insertNewChildAmpiElements(nextGroupComm, newAmpi);
2228 void ampiParent::groupChildRegister(const ampiCommStruct &s) {
2229 int idx=s.getComm()-MPI_COMM_FIRST_GROUP;
2230 if (groupComm.size()<=idx) groupComm.resize(idx+1);
2231 groupComm[idx]=new ampiCommStruct(s);
2232 thread->resume(); //Matches suspend at end of ampi::split
2235 /* Virtual topology communicator creation */
2237 // 0-dimensional cart comm: rank 0 creates a dup of COMM_SELF with topo info.
2238 MPI_Comm ampi::cartCreate0D(void){
2239 if (getRank() == 0) {
2241 tmpVec.push_back(0);
2242 commCreatePhase1(parent->getNextCart());
2243 return parent->getNextCart()-1;
2246 return MPI_COMM_NULL;
2250 MPI_Comm ampi::cartCreate(groupStruct vec, int ndims, const int* dims){
2252 return cartCreate0D();
2255 // Subtract out ranks from the group that won't be in the new comm
2256 int newsize = dims[0];
2257 for (int i = 1; i < ndims; i++) {
2260 for (int i = vec.size(); i > newsize; i--) {
2264 int rootIdx = vec[0];
2266 CkCallback cb(CkReductionTarget(ampi,commCreatePhase1),CkArrayIndex1D(rootIdx),myComm.getProxy());
2268 MPI_Comm nextcart = parent->getNextCart();
2269 contribute(sizeof(nextcart), &nextcart,CkReduction::max_int,cb);
2271 if (getPosOp(thisIndex,vec)>=0) {
2272 thread->suspend(); //Resumed by ampiParent::cartChildRegister
2273 return parent->getNextCart()-1;
2275 return MPI_COMM_NULL;
2279 void ampiParent::cartChildRegister(const ampiCommStruct &s) {
2280 int idx=s.getComm()-MPI_COMM_FIRST_CART;
2281 if (cartComm.size()<=idx) {
2282 cartComm.resize(idx+1);
2283 cartComm.length()=idx+1;
2285 cartComm[idx]=new ampiCommStruct(s);
2286 thread->resume(); //Matches suspend at end of ampi::cartCreate
2289 void ampi::graphCreate(const groupStruct vec,MPI_Comm* newcomm){
2292 CkCallback cb(CkReductionTarget(ampi,commCreatePhase1),CkArrayIndex1D(rootIdx),
2294 MPI_Comm nextgraph = parent->getNextGraph();
2295 contribute(sizeof(nextgraph), &nextgraph,CkReduction::max_int,cb);
2297 if(getPosOp(thisIndex,vec)>=0){
2298 thread->suspend(); //Resumed by ampiParent::graphChildRegister
2299 MPI_Comm retcomm = parent->getNextGraph()-1;
2302 *newcomm = MPI_COMM_NULL;
2305 void ampiParent::graphChildRegister(const ampiCommStruct &s) {
2306 int idx=s.getComm()-MPI_COMM_FIRST_GRAPH;
2307 if (graphComm.size()<=idx) {
2308 graphComm.resize(idx+1);
2309 graphComm.length()=idx+1;
2311 graphComm[idx]=new ampiCommStruct(s);
2312 thread->resume(); //Matches suspend at end of ampi::graphCreate
2315 void ampi::intercommCreate(const groupStruct remoteVec, const int root, MPI_Comm tcomm, MPI_Comm *ncomm){
2317 if(thisIndex==root) { // not everybody gets the valid rvec
2320 CkCallback cb(CkReductionTarget(ampi, intercommCreatePhase1),CkArrayIndex1D(root),myComm.getProxy());
2321 MPI_Comm nextinter = parent->getNextInter();
2322 contribute(sizeof(nextinter), &nextinter,CkReduction::max_int,cb);
2323 thread->suspend(); //Not resumed by ampiParent::interChildRegister. Resumed by ExchangeProxy.
2324 *ncomm = parent->getNextInter()-1;
2327 void ampi::intercommCreatePhase1(MPI_Comm nextInterComm){
2329 CProxy_ampi newAmpi = createNewChildAmpiSync();
2330 groupStruct lgroup = myComm.getIndices();
2331 ampiCommStruct newCommstruct = ampiCommStruct(nextInterComm,newAmpi,lgroup.size(),lgroup,tmpVec);
2332 for(int i=0;i<lgroup.size();i++){
2333 int newIdx=lgroup[i];
2334 newAmpi[newIdx].insert(parentProxy,newCommstruct);
2336 newAmpi.doneInserting();
2338 parentProxy[0].ExchangeProxy(newAmpi);
2341 void ampiParent::interChildRegister(const ampiCommStruct &s) {
2342 int idx=s.getComm()-MPI_COMM_FIRST_INTER;
2343 if (interComm.size()<=idx) interComm.resize(idx+1);
2344 interComm[idx]=new ampiCommStruct(s);
2345 // don't resume the thread yet, till parent set remote proxy
2348 void ampi::intercommMerge(int first, MPI_Comm *ncomm){ // first valid only at local root
2349 if(myRank == 0 && first == 1){ // first (lower) group creates the intracommunicator for the higher group
2350 groupStruct lvec = myComm.getIndices();
2351 groupStruct rvec = myComm.getRemoteIndices();
2352 int rsize = rvec.size();
2354 for(int i=0;i<rsize;i++)
2355 tmpVec.push_back(rvec[i]);
2356 if(tmpVec.size()==0) CkAbort("Error in ampi::intercommMerge: merging empty comms!\n");
2361 int rootIdx=myComm.getIndexForRank(0);
2362 CkCallback cb(CkReductionTarget(ampi, intercommMergePhase1),CkArrayIndex1D(rootIdx),myComm.getProxy());
2363 MPI_Comm nextintra = parent->getNextIntra();
2364 contribute(sizeof(nextintra), &nextintra,CkReduction::max_int,cb);
2366 thread->suspend(); //Resumed by ampiParent::interChildRegister
2367 MPI_Comm newcomm=parent->getNextIntra()-1;
2371 void ampi::intercommMergePhase1(MPI_Comm nextIntraComm){
2372 // gets called on two roots, first root creates the comm
2373 if(tmpVec.size()==0) return;
2374 CProxy_ampi newAmpi = createNewChildAmpiSync();
2375 insertNewChildAmpiElements(nextIntraComm, newAmpi);
2378 void ampiParent::intraChildRegister(const ampiCommStruct &s) {
2379 int idx=s.getComm()-MPI_COMM_FIRST_INTRA;
2380 if (intraComm.size()<=idx) intraComm.resize(idx+1);
2381 intraComm[idx]=new ampiCommStruct(s);
2382 thread->resume(); //Matches suspend at end of ampi::split
2385 //------------------------ communication -----------------------
2386 const ampiCommStruct &universeComm2CommStruct(MPI_Comm universeNo)
2388 if (universeNo>MPI_COMM_WORLD) {
2389 int worldDex=universeNo-MPI_COMM_WORLD-1;
2390 if (worldDex>=_mpi_nworlds)
2391 CkAbort("Bad world communicator passed to universeComm2CommStruct");
2392 return mpi_worlds[worldDex];
2394 CkAbort("Bad communicator passed to universeComm2CommStruct");
2395 return mpi_worlds[0]; // meaningless return
2398 void ampiParent::block(void){
2402 void ampiParent::yield(void){
2406 void ampi::unblock(void){
2410 ampiParent* ampiParent::blockOnRecv(void){
2411 resumeOnRecv = true;
2412 // In case this thread is migrated while suspended,
2413 // save myComm to get the ampi instance back. Then
2414 // return "dis" in case the caller needs it.
2416 ampiParent* dis = getAmpiParent();
2417 dis->resumeOnRecv = false;
2421 ampi* ampi::blockOnRecv(void){
2422 parent->resumeOnRecv = true;
2423 // In case this thread is migrated while suspended,
2424 // save myComm to get the ampi instance back. Then
2425 // return "dis" in case the caller needs it.
2426 MPI_Comm comm = myComm.getComm();
2428 ampi *dis = getAmpiInstance(comm);
2429 dis->parent->resumeOnRecv = false;
2433 ampi* ampi::blockOnColl(void){
2434 parent->resumeOnColl = true;
2435 MPI_Comm comm = myComm.getComm();
2437 ampi *dis = getAmpiInstance(comm);
2438 dis->parent->resumeOnColl = false;
2442 // block on (All)Reduce or (All)Gather(v)
2443 ampi* ampi::blockOnRedn(AmpiRequest *req){
2447 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
2448 _LOG_E_END_AMPI_PROCESSING(thisIndex)
2450 #if CMK_BIGSIM_CHARM
2451 void *curLog; // store current log in timeline
2452 _TRACE_BG_TLINE_END(&curLog);
2453 #if CMK_TRACE_IN_CHARM
2454 if(CpvAccess(traceOn)) traceSuspend();
2458 ampi* dis = blockOnColl();
2460 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2461 CpvAccess(_currentObj) = dis;
2463 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
2464 _LOG_E_BEGIN_AMPI_PROCESSING(thisIndex, dis->blockingReq->src, dis->blockingReq->count)
2466 #if CMK_BIGSIM_CHARM
2467 #if CMK_TRACE_IN_CHARM
2468 if(CpvAccess(traceOn)) CthTraceResume(dis->thread->getThread());
2470 TRACE_BG_AMPI_BREAK(dis->thread->getThread(), "RECV_RESUME", NULL, 0, 0);
2471 if (dis->blockingReq->eventPe == CkMyPe()) _TRACE_BG_ADD_BACKWARD_DEP(dis->blockingReq->event);
2474 delete dis->blockingReq; dis->blockingReq = NULL;
2478 void ampi::ssend_ack(int sreq_idx){
2480 thread->resume(); // MPI_Ssend
2482 sreq_idx -= 2; // start from 2
2483 AmpiRequestList *reqs = &(parent->ampiReqs);
2484 SsendReq *sreq = (SsendReq *)(*reqs)[sreq_idx];
2485 sreq->statusIreq = true;
2486 if (sreq->isBlocked() && parent->numBlockedReqs != 0) {
2487 parent->numBlockedReqs--;
2489 if (parent->resumeOnRecv && parent->numBlockedReqs == 0) {
2495 void ampi::generic(AmpiMsg* msg)
2498 CkPrintf("AMPI vp %d arrival: tag=%d, src=%d, comm=%d (seq %d) resumeOnRecv %d\n",
2499 thisIndex, msg->getTag(), msg->getSrcRank(), getComm(), msg->getSeq(), parent->resumeOnRecv);
2501 #if CMK_BIGSIM_CHARM
2502 TRACE_BG_ADD_TAG("AMPI_generic");
2506 if(msg->getSeq() != -1) {
2507 int seqIdx = msg->getSeqIdx();
2508 int n=oorder.put(seqIdx,msg);
2509 if (n>0) { // This message was in-order
2511 if (n>1) { // It enables other, previously out-of-order messages
2512 while((msg=oorder.getOutOfOrder(seqIdx))!=0) {
2517 } else { //Cross-world or system messages are unordered
2520 // msg may be free'ed from calling inorder()
2522 if(parent->resumeOnRecv && parent->numBlockedReqs==0){
2527 inline static AmpiRequestList *getReqs(void);
2529 void ampi::inorder(AmpiMsg* msg)
2532 CkPrintf("AMPI vp %d inorder: tag=%d, src=%d, comm=%d (seq %d)\n",
2533 thisIndex, msg->getTag(), msg->getSrcRank(), getComm(), msg->getSeq());
2536 // check posted recvs
2537 int tags[2] = { msg->getTag(), msg->getSrcRank() };
2540 #if CMK_BIGSIM_CHARM
2541 _TRACE_BG_TLINE_END(&msg->event); // store current log
2542 msg->eventPe = CkMyPe();
2545 //in case ampi has not initialized and posted_ireqs are only inserted
2546 //at AMPI_Irecv (MPI_Irecv)
2547 AmpiRequestList *reqL = &(parent->ampiReqs);
2548 //When storing the req index, it's 1-based. The reason is stated in the comments
2549 //in the ampi::irecv function.
2550 int ireqIdx = (int)((long)AmmGet(posted_ireqs, tags, (int*)&sts));
2552 if(reqL->size()>0 && ireqIdx>0)
2553 ireq = (IReq *)(*reqL)[ireqIdx-1];
2554 if (ireq) { // receive posted
2555 if (ireq->isBlocked() && parent->numBlockedReqs != 0) {
2556 parent->numBlockedReqs--;
2558 ireq->receive(this, msg);
2560 AmmPut(msgs, tags, msg);
2564 static inline AmpiMsg* rdma2AmpiMsg(char *buf, int size, int seq, int tag, int srcRank,
2567 // Convert an Rdma message (parameter marshalled buffer) to an AmpiMsg
2568 AmpiMsg* msg = new (size, 0) AmpiMsg(seq, tag, srcRank, size);
2569 if (ssendReq) UsrToEnv(msg)->setRef(ssendReq);
2570 memcpy(msg->data, buf, size); // Assumes the buffer is contiguous
2574 // RDMA version of ampi::generic
2575 void ampi::genericRdma(char* buf, int size, int seq, int tag, int srcRank, MPI_Comm destcomm, int ssendReq)
2578 CkPrintf("[%d] in ampi::genericRdma on index %d, size=%d, seq=%d, srcRank=%d, tag=%d, comm=%d, ssendReq=%d\n",
2579 CkMyPe(), getIndexForRank(getRank()), size, seq, srcRank, tag, destcomm, ssendReq);
2583 int seqIdx = srcRank;
2584 int n = oorder.isInOrder(seqIdx, seq);
2585 if (n > 0) { // This message was in-order
2586 inorderRdma(buf, size, seq, tag, srcRank, destcomm, ssendReq);
2587 if (n > 1) { // It enables other, previously out-of-order messages
2588 AmpiMsg *msg = NULL;
2589 while ((msg = oorder.getOutOfOrder(seqIdx)) != 0) {
2593 } else { // This message was out-of-order: stash it (as an AmpiMsg)
2594 AmpiMsg *msg = rdma2AmpiMsg(buf, size, seq, tag, srcRank, ssendReq);
2595 oorder.putOutOfOrder(seqIdx, msg);
2597 } else { // Cross-world or system messages are unordered
2598 inorderRdma(buf, size, seq, tag, srcRank, destcomm, ssendReq);
2601 if (parent->resumeOnRecv && parent->numBlockedReqs == 0) {
2606 // RDMA version of ampi::inorder
2607 void ampi::inorderRdma(char* buf, int size, int seq, int tag, int srcRank,
2608 MPI_Comm comm, int ssendReq)
2611 CkPrintf("AMPI vp %d inorderRdma: tag=%d, src=%d, comm=%d (seq %d)\n",
2612 thisIndex, tag, srcRank, comm, seq);
2615 // check posted recvs
2616 int tags[2] = { tag, srcRank };
2619 //in case ampi has not initialized and posted_ireqs are only inserted
2620 //at AMPI_Irecv (MPI_Irecv)
2621 AmpiRequestList *reqL = &(parent->ampiReqs);
2622 //When storing the req index, it's 1-based. The reason is stated in the comments
2623 //in the ampi::irecv function.
2624 int ireqIdx = (int)((long)AmmGet(posted_ireqs, tags, (int*)&sts));
2626 if (reqL->size()>0 && ireqIdx>0)
2627 ireq = (IReq *)(*reqL)[ireqIdx-1];
2628 if (ireq) { // receive posted
2629 if (ireq->isBlocked() && parent->numBlockedReqs != 0) {
2630 parent->numBlockedReqs--;
2632 ireq->receiveRdma(this, buf, size, ssendReq, srcRank, comm);
2634 AmpiMsg* msg = rdma2AmpiMsg(buf, size, seq, tag, srcRank, ssendReq);
2635 AmmPut(msgs, tags, msg);
2639 // Callback from ampi::genericRdma() signaling that the send buffer is now safe to re-use
2640 void ampi::completedRdmaSend(CkDataMsg *msg)
2642 // refnum is the index into reqList for this SendReq
2643 int reqIdx = CkGetRefNum(msg);
2646 CkPrintf("[%d] in ampi::completedRdmaSend on index %d, reqIdx = %d\n",
2647 CkMyPe(), parent->thisIndex, reqIdx);
2650 AmpiRequestList& reqList = parent->ampiReqs;
2651 SendReq& sreq = (SendReq&)(*reqList[reqIdx]);
2652 sreq.statusIreq = true;
2654 if (sreq.isBlocked() && parent->numBlockedReqs != 0) {
2655 parent->numBlockedReqs--;
2657 if (parent->resumeOnRecv && parent->numBlockedReqs == 0) {
2660 // CkDataMsg is allocated & freed by the runtime, so do not delete msg
2663 AmpiMsg *ampi::getMessage(int t, int s, MPI_Comm comm, int *sts) const
2665 int tags[2] = { t, s };
2666 AmpiMsg *msg = (AmpiMsg *) AmmGet(msgs, tags, sts);
2670 void handle_MPI_BOTTOM(void* &buf, MPI_Datatype type)
2672 if (buf == MPI_BOTTOM) {
2673 buf = (void*)getDDT()->getType(type)->getLB();
2674 getDDT()->getType(type)->setAbsolute(true);
2678 void handle_MPI_BOTTOM(void* &buf1, MPI_Datatype type1, void* &buf2, MPI_Datatype type2)
2680 if (buf1 == MPI_BOTTOM) {
2681 buf1 = (void*)getDDT()->getType(type1)->getLB();
2682 getDDT()->getType(type1)->setAbsolute(true);
2684 if (buf2 == MPI_BOTTOM) {
2685 buf2 = (void*)getDDT()->getType(type2)->getLB();
2686 getDDT()->getType(type2)->setAbsolute(true);
2690 AmpiMsg *ampi::makeAmpiMsg(int destRank,int t,int sRank,const void *buf,int count,
2691 MPI_Datatype type,MPI_Comm destcomm, int ssendReq/*=0*/)
2693 CkDDT_DataType *ddt = getDDT()->getType(type);
2694 int len = ddt->getSize(count);
2695 int seq = getSeqNo(destRank, destcomm, t);
2696 AmpiMsg *msg = new (len, 0) AmpiMsg(seq, t, sRank, len);
2697 if (ssendReq) UsrToEnv(msg)->setRef(ssendReq);
2698 ddt->serialize((char*)buf, msg->getData(), count, 1);
2702 static inline void freeNonPersReq(int &request) {
2703 AmpiRequestList* reqs = getReqs();
2704 if (!(*reqs)[request]->isPersistent()) {
2705 reqs->free(request);
2706 request = MPI_REQUEST_NULL;
2710 MPI_Request ampi::send(int t, int sRank, const void* buf, int count, MPI_Datatype type,
2711 int rank, MPI_Comm destcomm, int ssendReq/*=0*/, AmpiSendType sendType/*=BLOCKING_SEND*/)
2713 #if CMK_TRACE_IN_CHARM
2714 TRACE_BG_AMPI_BREAK(thread->getThread(), "AMPI_SEND", NULL, 0, 1);
2717 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2718 MPI_Comm disComm = myComm.getComm();
2719 ampi *dis = getAmpiInstance(disComm);
2720 CpvAccess(_currentObj) = dis;
2723 const ampiCommStruct &dest=comm2CommStruct(destcomm);
2724 MPI_Request req = delesend(t,sRank,buf,count,type,rank,destcomm,dest.getProxy(),ssendReq,sendType);
2725 if (sendType == BLOCKING_SEND && req != MPI_REQUEST_NULL) {
2726 AmpiRequestList* reqList = getReqs();
2727 SendReq *sreq = (SendReq*)(*reqList)[req];
2728 sreq->wait(MPI_STATUS_IGNORE);
2730 req = MPI_REQUEST_NULL;
2733 #if CMK_TRACE_IN_CHARM
2734 TRACE_BG_AMPI_BREAK(thread->getThread(), "AMPI_SEND_END", NULL, 0, 1);
2737 if (ssendReq == 1) {
2738 // waiting for receiver side
2739 parent->resumeOnRecv = false; // so no one else awakes it
2746 void ampi::sendraw(int t, int sRank, void* buf, int len, CkArrayID aid, int idx)
2748 AmpiMsg *msg = new (len, 0) AmpiMsg(-1, t, sRank, len);
2749 memcpy(msg->getData(), buf, len);
2750 CProxy_ampi pa(aid);
2751 pa[idx].generic(msg);
2754 int ampi::getSeqNo(int destRank, MPI_Comm destcomm, int tag) {
2755 int seqIdx = destRank;
2757 if (destRank>=0 && destcomm<=MPI_COMM_WORLD && tag<=MPI_ATA_SEQ_TAG) { //Not cross-module: set seqno
2758 seq = oorder.nextOutgoing(seqIdx);
2763 MPI_Request ampi::sendRdmaMsg(int t, int sRank, const void* buf, int size, int destIdx,
2764 int destRank, MPI_Comm destcomm, CProxy_ampi arrProxy, int ssendReq)
2766 int seq = getSeqNo(destRank, destcomm, t);
2768 if (ssendReq) { // Using a SsendReq to track matching receive, so no need for SendReq here
2769 arrProxy[destIdx].genericRdma(CkSendBuffer(buf), size, seq, t, sRank, destcomm, ssendReq);
2770 return MPI_REQUEST_NULL;
2772 else { // Set up a SendReq to track completion of the send buffer
2773 MPI_Request req = postReq(new SendReq(destcomm));
2774 CkCallback completedSendCB(CkIndex_ampi::completedRdmaSend(NULL), thisProxy[thisIndex], true/*inline*/);
2775 completedSendCB.setRefnum(req);
2777 arrProxy[destIdx].genericRdma(CkSendBuffer(buf, completedSendCB), size, seq, t, sRank, destcomm, ssendReq);
2782 // Call genericRdma inline on the local destination object
2783 MPI_Request ampi::sendLocalMsg(int t, int sRank, const void* buf, int size, int destRank,
2784 MPI_Comm destcomm, ampi* destPtr, int ssendReq, AmpiSendType sendType)
2786 int seq = getSeqNo(destRank, destcomm, t);
2788 destPtr->genericRdma((char*)buf, size, seq, t, sRank, destcomm, ssendReq);
2790 if (ssendReq || sendType == BLOCKING_SEND) {
2791 return MPI_REQUEST_NULL;
2793 else { // SendReq is pre-completed since we directly copied the send buffer
2794 return postReq(new SendReq(destcomm, AMPI_REQ_COMPLETED));
2798 MPI_Request ampi::delesend(int t, int sRank, const void* buf, int count, MPI_Datatype type,
2799 int rank, MPI_Comm destcomm, CProxy_ampi arrProxy, int ssendReq,
2800 AmpiSendType sendType)
2802 if (rank==MPI_PROC_NULL) return MPI_REQUEST_NULL;
2803 const ampiCommStruct &dest=comm2CommStruct(destcomm);
2804 int destIdx = dest.getIndexForRank(rank);
2807 destIdx = dest.getIndexForRemoteRank(rank);
2808 arrProxy = remoteProxy;
2812 CkPrintf("AMPI vp %d send: tag=%d, src=%d, comm=%d (to %d)\n",thisIndex,t,sRank,destcomm,destIdx);
2815 ampi *destPtr = arrProxy[destIdx].ckLocal();
2816 CkDDT_DataType *ddt = getDDT()->getType(type);
2817 int size = ddt->getSize(count);
2818 if (ddt->isContig()) {
2820 if (destPtr != NULL) {
2821 return sendLocalMsg(t, sRank, buf, size, rank, destcomm, destPtr, ssendReq, sendType);
2825 if (size >= AMPI_RDMA_THRESHOLD ||
2826 (size >= AMPI_SMP_RDMA_THRESHOLD && destLikelyWithinProcess(arrProxy, destIdx)))
2828 return sendRdmaMsg(t, sRank, buf, size, destIdx, rank, destcomm, arrProxy, ssendReq);
2833 if (destPtr != NULL) {
2834 destPtr->generic(makeAmpiMsg(rank, t, sRank, buf, count, type, destcomm, ssendReq));
2835 return MPI_REQUEST_NULL;
2839 arrProxy[destIdx].generic(makeAmpiMsg(rank, t, sRank, buf, count, type, destcomm, ssendReq));
2840 return MPI_REQUEST_NULL;
2844 void ampi::processAmpiMsg(AmpiMsg *msg, const void* buf, MPI_Datatype type, int count)
2846 int ssendReq = UsrToEnv(msg)->getRef();
2847 if (ssendReq > 0) { // send an ack to sender
2848 int srcRank = msg->getSrcRank();
2849 int srcIdx = getIndexForRank(srcRank);
2850 thisProxy[srcIdx].ssend_ack(ssendReq);
2853 CkDDT_DataType *ddt = getDDT()->getType(type);
2854 int len = ddt->getSize(count);
2856 if(msg->getLength() < len){ // only at rare case shall we reset count by using divide
2857 count = msg->getLength()/(ddt->getSize(1));
2860 ddt->serialize((char*)buf, msg->getData(), count, (-1));
2863 // RDMA version of ampi::processAmpiMsg
2864 void ampi::processRdmaMsg(const void *sbuf, int slength, int ssendReq, int srank, void* rbuf,
2865 int rcount, MPI_Datatype rtype, MPI_Comm comm)
2867 if (ssendReq > 0) { // send an ack to sender
2868 int srcIdx = getIndexForRank(srank);
2869 thisProxy[srcIdx].ssend_ack(ssendReq);
2872 CkDDT_DataType *ddt = getDDT()->getType(rtype);
2873 int rlength = ddt->getSize(rcount);
2875 if (slength < rlength) { // only at rare case shall we reset count by using divide
2876 rcount = slength / (ddt->getSize(1));
2879 ddt->serialize((char*)rbuf, (char*)sbuf, rcount, (-1));
2882 void ampi::processRednMsg(CkReductionMsg *msg, const void* buf, MPI_Datatype type, int count)
2884 // The first sizeof(AmpiOpHeader) bytes in the redn msg data are reserved
2885 // for an AmpiOpHeader if our custom AmpiReducer type was used.
2886 int szhdr = (msg->getReducer() == AmpiReducer) ? sizeof(AmpiOpHeader) : 0;
2887 getDDT()->getType(type)->serialize((char*)buf, (char*)msg->getData()+szhdr, count, (-1));
2890 void ampi::processNoncommutativeRednMsg(CkReductionMsg *msg, void* buf, MPI_Datatype type, int count, MPI_User_function* func)
2892 CkReduction::tupleElement* results = NULL;
2893 int numReductions = 0;
2894 msg->toTuple(&results, &numReductions);
2896 // Contributions are unordered and consist of a (srcRank, data) tuple
2897 CkReduction::setElement *currentSrc = (CkReduction::setElement*)results[0].data;
2898 CkReduction::setElement *currentData = (CkReduction::setElement*)results[1].data;
2899 CkDDT_DataType *ddt = getDDT()->getType(type);
2900 int contributionSize = ddt->getSize(count);
2901 int commSize = getSize();
2903 // Store pointers to each contribution's data at index 'srcRank' in contributionData
2904 vector<void *> contributionData(commSize);
2905 for (int i=0; i<commSize; i++) {
2906 CkAssert(currentSrc && currentData);
2907 int srcRank = *((int*)currentSrc->data);
2908 CkAssert(currentData->dataSize == contributionSize);
2909 contributionData[srcRank] = currentData->data;
2910 currentSrc = currentSrc->next();
2911 currentData = currentData->next();
2914 if (ddt->isContig()) {
2915 // Copy rank 0's contribution into buf first
2916 memcpy(buf, contributionData[0], contributionSize);
2918 // Invoke the MPI_User_function on the contributions in 'rank' order
2919 for (int i=1; i<commSize; i++) {
2920 (*func)(contributionData[i], buf, &count, &type);
2924 // Deserialize rank 0's contribution into buf first
2925 ddt->serialize((char*)contributionData[0], (char*)buf, count, -1);
2927 // Invoke the MPI_User_function on the deserialized contributions in 'rank' order
2928 vector<char> deserializedBuf(ddt->getExtent() * count);
2929 for (int i=1; i<commSize; i++) {
2930 ddt->serialize((char*)contributionData[i], &deserializedBuf[0], count, -1);
2931 (*func)(&deserializedBuf[0], buf, &count, &type);
2937 void ampi::processGatherMsg(CkReductionMsg *msg, const void* buf, MPI_Datatype type, int recvCount)
2939 CkReduction::tupleElement* results = NULL;
2940 int numReductions = 0;
2941 msg->toTuple(&results, &numReductions);
2943 // Re-order the gather data based on the rank of the contributor
2944 CkReduction::setElement *currentSrc = (CkReduction::setElement*)results[0].data;
2945 CkReduction::setElement *currentData = (CkReduction::setElement*)results[1].data;
2946 CkDDT_DataType *ddt = getDDT()->getType(type);
2947 int contributionSize = ddt->getSize(recvCount);
2948 int contributionExtent = ddt->getExtent()*recvCount;
2950 for (int i=0; i<getSize(); i++) {
2951 CkAssert(currentSrc && currentData);
2952 int srcRank = *((int*)currentSrc->data);
2953 CkAssert(currentData->dataSize == contributionSize);
2954 ddt->serialize(&(((char*)buf)[srcRank*contributionExtent]), currentData->data, recvCount, (-1));
2955 currentSrc = currentSrc->next();
2956 currentData = currentData->next();
2961 void ampi::processGathervMsg(CkReductionMsg *msg, const void* buf, MPI_Datatype type,
2962 int* recvCounts, int* displs)
2964 CkReduction::tupleElement* results = NULL;
2965 int numReductions = 0;
2966 msg->toTuple(&results, &numReductions);
2968 // Re-order the gather data based on the rank of the contributor
2969 CkReduction::setElement *currentSrc = (CkReduction::setElement*)results[0].data;
2970 CkReduction::setElement *currentData = (CkReduction::setElement*)results[1].data;
2971 CkDDT_DataType *ddt = getDDT()->getType(type);
2972 int contributionSize = ddt->getSize();
2973 int contributionExtent = ddt->getExtent();
2975 for (int i=0; i<getSize(); i++) {
2976 CkAssert(currentSrc && currentData);
2977 int srcRank = *((int*)currentSrc->data);
2978 CkAssert(currentData->dataSize == contributionSize*recvCounts[srcRank]);
2979 ddt->serialize(&((char*)buf)[displs[srcRank]*contributionExtent], currentData->data, recvCounts[srcRank], (-1));
2980 currentSrc = currentSrc->next();
2981 currentData = currentData->next();
2986 static inline void clearStatus(MPI_Status *sts) {
2987 if (sts != MPI_STATUS_IGNORE) {
2988 sts->MPI_TAG = MPI_ANY_TAG;
2989 sts->MPI_SOURCE = MPI_ANY_SOURCE;
2990 sts->MPI_COMM = MPI_COMM_NULL;
2991 sts->MPI_LENGTH = 0;
2992 sts->MPI_ERROR = MPI_SUCCESS;
2993 sts->MPI_CANCEL = 0;
2997 static inline void clearStatus(MPI_Status sts[], int idx) {
2998 if (sts != MPI_STATUSES_IGNORE) {
2999 clearStatus(&sts[idx]);
3003 static inline bool handle_MPI_PROC_NULL(int src, MPI_Comm comm, MPI_Status* sts)
3005 if (src == MPI_PROC_NULL) {
3012 int ampi::recv(int t, int s, void* buf, int count, MPI_Datatype type, MPI_Comm comm, MPI_Status *sts)
3014 MPI_Comm disComm = myComm.getComm();
3015 if (handle_MPI_PROC_NULL(s, disComm, sts)) return 0;
3017 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
3018 _LOG_E_END_AMPI_PROCESSING(thisIndex)
3020 #if CMK_BIGSIM_CHARM
3021 void *curLog; // store current log in timeline
3022 _TRACE_BG_TLINE_END(&curLog);
3023 #if CMK_TRACE_IN_CHARM
3024 if(CpvAccess(traceOn)) traceSuspend();
3029 s = myComm.getIndexForRemoteRank(s);
3033 CkPrintf("AMPI vp %d blocking recv: tag=%d, src=%d, comm=%d\n",thisIndex,t,s,comm);
3036 ampi *dis = getAmpiInstance(disComm);
3037 MPI_Status tmpStatus;
3038 int tags[2] = { t, s };
3039 AmpiMsg *msg = NULL;
3040 msg = (AmpiMsg *)AmmGet(msgs, tags, (sts == MPI_STATUS_IGNORE) ? (int*)&tmpStatus : (int*)sts);
3041 if (msg) { // the matching message has already arrived
3042 if (sts != MPI_STATUS_IGNORE) {
3043 sts->MPI_SOURCE = msg->getSrcRank();
3044 sts->MPI_TAG = msg->getTag();
3045 sts->MPI_COMM = comm;
3046 sts->MPI_LENGTH = msg->getLength();
3047 sts->MPI_CANCEL = 0;
3049 processAmpiMsg(msg, buf, type, count);
3050 #if CMK_BIGSIM_CHARM
3051 TRACE_BG_AMPI_BREAK(thread->getThread(), "RECV_RESUME", NULL, 0, 0);
3052 if (msg->eventPe == CkMyPe()) _TRACE_BG_ADD_BACKWARD_DEP(msg->event);
3056 else { // post a request and block until the matching message arrives
3057 int request = postReq(new IReq(buf, count, type, s, t, comm, AMPI_REQ_BLOCKED));
3058 CkAssert(parent->numBlockedReqs == 0);
3059 parent->numBlockedReqs = 1;
3060 dis = dis->blockOnRecv(); // "dis" is updated in case an ampi thread is migrated while waiting for a message
3061 if (sts != MPI_STATUS_IGNORE) {
3062 AmpiRequestList* reqs = getReqs();
3063 AmpiRequest& req = *(*reqs)[request];
3064 sts->MPI_SOURCE = req.src;
3065 sts->MPI_TAG = req.tag;
3066 sts->MPI_COMM = req.comm;
3067 sts->MPI_LENGTH = req.getNumReceivedBytes(getDDT());
3068 sts->MPI_CANCEL = 0;
3070 freeNonPersReq(request);
3073 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3074 CpvAccess(_currentObj) = dis;
3075 MSG_ORDER_DEBUG( printf("[%d] AMPI thread rescheduled to Index %d buf %p src %d\n",CkMyPe(),dis->thisIndex,buf,s); )
3077 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
3078 _LOG_E_BEGIN_AMPI_PROCESSING(thisIndex,s,count)
3080 #if CMK_BIGSIM_CHARM && CMK_TRACE_IN_CHARM
3081 //Due to the reason mentioned the in the else-statement above, we need to
3082 //use "dis" as "this" in the case of migration (or out-of-core execution in BigSim)
3083 if(CpvAccess(traceOn)) CthTraceResume(dis->thread->getThread());
3089 void ampi::probe(int t, int s, MPI_Comm comm, MPI_Status *sts)
3091 if (handle_MPI_PROC_NULL(s, comm, sts)) return;
3094 #if CMK_BIGSIM_CHARM
3095 void *curLog; // store current log in timeline
3096 _TRACE_BG_TLINE_END(&curLog);
3099 ampi *dis = getAmpiInstance(comm);
3102 MPI_Status tmpStatus;
3103 tags[0] = t; tags[1] = s;
3104 msg = (AmpiMsg *) AmmProbe(dis->msgs, tags, (sts == MPI_STATUS_IGNORE) ? (int*)&tmpStatus : (int*)sts);
3106 // "dis" is updated in case an ampi thread is migrated while waiting for a message
3107 dis = dis->blockOnRecv();
3110 if (sts != MPI_STATUS_IGNORE) {
3111 sts->MPI_SOURCE = msg->getSrcRank();
3112 sts->MPI_TAG = msg->getTag();
3113 sts->MPI_COMM = comm;
3114 sts->MPI_LENGTH = msg->getLength();
3115 sts->MPI_CANCEL = 0;
3118 #if CMK_BIGSIM_CHARM
3119 _TRACE_BG_SET_INFO((char *)msg, "PROBE_RESUME", &curLog, 1);
3123 int ampi::iprobe(int t, int s, MPI_Comm comm, MPI_Status *sts)
3125 if (handle_MPI_PROC_NULL(s, comm, sts)) return 1;
3129 MPI_Status tmpStatus;
3130 tags[0] = t; tags[1] = s;
3131 msg = (AmpiMsg *) AmmProbe(msgs, tags, (sts == MPI_STATUS_IGNORE) ? (int*)&tmpStatus : (int*)sts);
3133 if (sts != MPI_STATUS_IGNORE) {
3134 sts->MPI_SOURCE = msg->getSrcRank();
3135 sts->MPI_TAG = msg->getTag();
3136 sts->MPI_COMM = comm;
3137 sts->MPI_LENGTH = msg->getLength();
3138 sts->MPI_CANCEL = 0;
3142 #if CMK_BIGSIM_CHARM
3143 void *curLog; // store current log in timeline
3144 _TRACE_BG_TLINE_END(&curLog);
3147 #if CMK_BIGSIM_CHARM
3148 _TRACE_BG_SET_INFO(NULL, "IPROBE_RESUME", &curLog, 1);
3153 void ampi::bcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm destcomm)
3155 if (root==getRank()) {
3156 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3157 CpvAccess(_currentObj) = this;
3159 thisProxy.generic(makeAmpiMsg(-1, MPI_BCAST_TAG, root, buf, count, type, destcomm));
3162 if (-1==recv(MPI_BCAST_TAG, root, buf, count, type, destcomm)) CkAbort("AMPI> Error in broadcast");
3165 int ampi::intercomm_bcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm intercomm)
3167 if (root==MPI_ROOT) {
3168 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3169 CpvAccess(_currentObj) = this;
3171 remoteProxy.generic(makeAmpiMsg(-1, MPI_BCAST_TAG, getRank(), buf, count, type, intercomm));
3174 if (root!=MPI_PROC_NULL && root!=MPI_ROOT) {
3175 // remote group ranks
3176 if (-1==recv(MPI_BCAST_TAG, root, buf, count, type, intercomm)) CkAbort("AMPI> Error in intercomm broadcast");
3181 void ampi::ibcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm destcomm, MPI_Request* request)
3183 if (root==getRank()) {
3184 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3185 CpvAccess(_currentObj) = this;
3187 thisProxy.generic(makeAmpiMsg(-1, MPI_BCAST_TAG, root, buf, count, type, destcomm));
3190 // call irecv to post an IReq and check for any pending messages
3191 irecv(buf, count, type, root, MPI_BCAST_TAG, destcomm, request);
3194 int ampi::intercomm_ibcast(int root, void* buf, int count, MPI_Datatype type, MPI_Comm intercomm, MPI_Request *request)
3196 if (root==MPI_ROOT) {
3197 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
3198 CpvAccess(_currentObj) = this;
3200 remoteProxy.generic(makeAmpiMsg(-1, MPI_BCAST_TAG, getRank(), buf, count, type, intercomm));
3203 if (root!=MPI_PROC_NULL && root!=MPI_ROOT) {
3204 // call irecv to post IReq and process pending messages
3205 irecv(buf, count, type, root, MPI_BCAST_TAG, intercomm, request);
3210 void ampi::bcastraw(void* buf, int len, CkArrayID aid)
3212 AmpiMsg *msg = new (len, 0) AmpiMsg(-1, MPI_BCAST_TAG, 0, len);
3213 memcpy(msg->getData(), buf, len);
3214 CProxy_ampi pa(aid);
3218 AmpiMsg* ampi::Alltoall_RemoteIget(MPI_Aint disp, int cnt, MPI_Datatype type, int tag)
3220 CkAssert(tag==MPI_ATA_TAG && AlltoallGetFlag);
3222 CkDDT_DataType *ddt = getDDT()->getType(type);
3223 unit = ddt->getSize(1);
3224 int totalsize = unit*cnt;
3226 AmpiMsg *msg = new (totalsize, 0) AmpiMsg(-1, MPI_ATA_TAG, thisIndex,totalsize);
3227 char* addr = (char*)Alltoallbuff+disp*unit;
3228 ddt->serialize(msg->getData(), addr, cnt, (-1));
3232 int ampi::intercomm_scatter(int root, const void *sendbuf, int sendcount, MPI_Datatype sendtype,
3233 void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm intercomm)
3235 if (root == MPI_ROOT) {
3236 int remote_size = getRemoteIndices().size();
3238 CkDDT_DataType* dttype = getDDT()->getType(sendtype) ;
3239 int itemsize = dttype->getSize(sendcount) ;
3240 for(int i = 0; i < remote_size; i++) {
3241 send(MPI_SCATTER_TAG, getRank(), ((char*)sendbuf)+(itemsize*i),
3242 sendcount, sendtype, i, intercomm);
3246 if (root!=MPI_PROC_NULL && root!=MPI_ROOT) { //remote group ranks
3247 if(-1==recv(MPI_SCATTER_TAG, root, recvbuf, recvcount, recvtype, intercomm))
3248 CkAbort("AMPI> Error in intercomm MPI_Scatter recv");
3254 int ampi::intercomm_iscatter(int root, const void *sendbuf, int sendcount, MPI_Datatype sendtype,
3255 void *recvbuf, int recvcount, MPI_Datatype recvtype,
3256 MPI_Comm intercomm, MPI_Request *request)
3258 if (root == MPI_ROOT) {
3259 int remote_size = getRemoteIndices().size();
3261 CkDDT_DataType* dttype = getDDT()->getType(sendtype) ;
3262 int itemsize = dttype->getSize(sendcount) ;
3263 for(int i = 0; i < remote_size; i++) {
3264 send(MPI_SCATTER_TAG, getRank(), ((char*)sendbuf)+(itemsize*i),
3265 sendcount, sendtype, i, intercomm);
3269 if (root!=MPI_PROC_NULL && root!=MPI_ROOT) { //remote group ranks
3270 // call irecv to post an IReq and process any pending messages
3271 irecv(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,intercomm,request);
3277 int ampi::intercomm_scatterv(int root, const void* sendbuf, const int* sendcounts, const int* displs,
3278 MPI_Datatype sendtype, void* recvbuf, int recvcount,
3279 MPI_Datatype recvtype, MPI_Comm intercomm)
3281 if (root == MPI_ROOT) {
3282 int remote_size = getRemoteIndices().size();
3284 CkDDT_DataType* dttype = getDDT()->getType(sendtype);
3285 int itemsize = dttype->getSize();
3286 for (int i = 0; i < remote_size; i++) {
3287 send(MPI_SCATTER_TAG, getRank(), ((char*)sendbuf)+(itemsize*displs[i]),
3288 sendcounts[i], sendtype, i, intercomm);
3292 if (root != MPI_PROC_NULL && root != MPI_ROOT) { // remote group ranks
3293 if (-1 == recv(MPI_SCATTER_TAG, root, recvbuf, recvcount, recvtype, intercomm))
3294 CkAbort("AMPI> Error in intercomm MPI_Scatterv recv");
3300 int ampi::intercomm_iscatterv(int root, const void* sendbuf, const int* sendcounts, const int* displs,
3301 MPI_Datatype sendtype, void* recvbuf, int recvcount,
3302 MPI_Datatype recvtype, MPI_Comm intercomm, MPI_Request* request)
3304 if (root == MPI_ROOT) {
3305 int remote_size = getRemoteIndices().size();
3307 CkDDT_DataType* dttype = getDDT()->getType(sendtype);
3308 int itemsize = dttype->getSize();
3309 for (int i = 0; i < remote_size; i++) {
3310 send(MPI_SCATTER_TAG, getRank(), ((char*)sendbuf)+(itemsize*displs[i]),
3311 sendcounts[i], sendtype, i, intercomm);
3315 if (root != MPI_PROC_NULL && root != MPI_ROOT) { // remote group ranks
3316 // call irecv to post an IReq and process any pending messages
3317 irecv(recvbuf, recvcount, recvtype, root, MPI_SCATTER_TAG, intercomm, request);
3323 int MPI_comm_null_copy_fn(MPI_Comm comm, int keyval, void *extra_state,
3324 void *attr_in, void *attr_out, int *flag){
3326 return (MPI_SUCCESS);
3329 int MPI_comm_dup_fn(MPI_Comm comm, int keyval, void *extra_state,
3330 void *attr_in, void *attr_out, int *flag){
3331 (*(void **)attr_out) = attr_in;
3333 return (MPI_SUCCESS);
3336 int MPI_comm_null_delete_fn(MPI_Comm comm, int keyval, void *attr, void *extra_state){
3337 return (MPI_SUCCESS);
3340 int MPI_type_null_copy_fn(MPI_Datatype type, int keyval, void *extra_state,
3341 void *attr_in, void *attr_out, int *flag){
3343 return (MPI_SUCCESS);
3346 int MPI_type_dup_fn(MPI_Datatype type, int keyval, void *extra_state,
3347 void *attr_in, void *attr_out, int *flag){
3348 (*(void **)attr_out) = attr_in;
3350 return (MPI_SUCCESS);
3353 int MPI_type_null_delete_fn(MPI_Datatype type, int keyval, void *attr, void *extra_state){
3354 return (MPI_SUCCESS);
3357 AmpiSeqQ::~AmpiSeqQ () {
3360 void AmpiSeqQ::pup(PUP::er &p) {
3365 void AmpiSeqQ::putOutOfOrder(int seqIdx, AmpiMsg *msg)
3367 AmpiOtherElement &el=elements[seqIdx];
3368 #if CMK_ERROR_CHECKING
3369 if (msg->getSeq() < el.seqIncoming)
3370 CkAbort("AMPI Logic error: received late out-of-order message!\n");
3373 el.nOut++; // We have another message in the out-of-order queue
3376 AmpiMsg *AmpiSeqQ::getOutOfOrder(int seqIdx)
3378 AmpiOtherElement &el=elements[seqIdx];
3379 if (el.nOut==0) return 0; // No more out-of-order left.
3380 // Walk through our out-of-order queue, searching for our next message:
3381 for (int i=0;i<out.length();i++) {
3382 AmpiMsg *msg=out.deq();
3383 if (msg->getSeqIdx()==seqIdx && msg->getSeq()==el.seqIncoming) {
3385 el.nOut--; // We have one less message out-of-order
3391 // We walked the whole queue-- ours is not there.
3395 void AmpiRequest::print(){
3396 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);
3400 AmpiRequest::print();
3401 CkPrintf("In IReq: this=%p, status=%d, length=%d\n", this, statusIreq, length);
3404 void RednReq::print(){
3405 AmpiRequest::print();
3406 CkPrintf("In RednReq: this=%p, status=%d\n", this, statusIreq);
3409 void GatherReq::print(){
3410 AmpiRequest::print();
3411 CkPrintf("In GatherReq: this=%p, status=%d\n", this, statusIreq);
3414 void GathervReq::print(){
3415 AmpiRequest::print();
3416 CkPrintf("In GathervReq: this=%p, status=%d\n", this, statusIreq);
3419 void IATAReq::print(){ //not complete for myreqs
3420 AmpiRequest::print();
3421 CkPrintf("In IATAReq: elmcount=%d, idx=%d\n", elmcount, idx);
3424 void SendReq::print(){
3425 AmpiRequest::print();
3426 CkPrintf("In SendReq: this=%p, status=%d\n", this, statusIreq);
3429 void SsendReq::print(){
3430 AmpiRequest::print();
3431 CkPrintf("In SsendReq: this=%p, status=%d\n", this, statusIreq);
3434 void AmpiRequestList::pup(PUP::er &p) {
3435 if(!CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC)){
3439 p(blklen); //Allocated size of block
3440 p(len); //Number of used elements in block
3441 if(p.isUnpacking()){
3442 makeBlock(blklen,len);
3445 for(int i=0;i<len;i++){
3447 if(!p.isUnpacking()){
3448 if(block[i] == NULL){
3451 nonnull = block[i]->getType();
3456 if(p.isUnpacking()){
3459 block[i] = new IReq;
3462 block[i] = new RednReq;
3464 case MPI_GATHER_REQ:
3465 block[i] = new GatherReq;
3467 case MPI_GATHERV_REQ:
3468 block[i] = new GathervReq;
3471 block[i] = new SendReq;
3474 block[i] = new SsendReq;
3477 block[i] = new IATAReq;
3492 //------------------ External Interface -----------------
3493 ampiParent *getAmpiParent(void) {
3494 ampiParent *p = CtvAccess(ampiPtr);
3495 #if CMK_ERROR_CHECKING
3496 if (p==NULL) CkAbort("Cannot call MPI routines before AMPI is initialized.\n");
3501 ampi *getAmpiInstance(MPI_Comm comm) {
3502 ampi *ptr=getAmpiParent()->comm2ampi(comm);
3503 #if CMK_ERROR_CHECKING
3504 if (ptr==NULL) CkAbort("AMPI's getAmpiInstance> null pointer\n");
3509 bool isAmpiThread(void) {
3510 return (CtvAccess(ampiPtr)) ? true : false;
3513 inline static AmpiRequestList *getReqs(void) {
3514 return &(getAmpiParent()->ampiReqs);
3517 inline void checkComm(MPI_Comm comm){
3518 #if AMPI_ERROR_CHECKING
3519 getAmpiParent()->checkComm(comm);
3523 inline void checkRequest(MPI_Request req){
3524 #if AMPI_ERROR_CHECKING
3525 getReqs()->checkRequest(req);
3529 inline void checkRequests(int n, MPI_Request* reqs){
3530 #if AMPI_ERROR_CHECKING
3531 AmpiRequestList* reqlist = getReqs();
3532 for(int i=0;i<n;i++)
3533 reqlist->checkRequest(reqs[i]);
3537 int testRequest(MPI_Request *reqIdx, int *flag, MPI_Status *sts){
3538 if(*reqIdx==MPI_REQUEST_NULL){
3543 checkRequest(*reqIdx);
3544 AmpiRequestList* reqList = getReqs();
3545 AmpiRequest& req = *(*reqList)[*reqIdx];
3546 if(1 == (*flag = req.test())){
3548 freeNonPersReq(*reqIdx);
3553 int testRequestNoFree(MPI_Request *reqIdx, int *flag, MPI_Status *sts){
3554 if(*reqIdx==MPI_REQUEST_NULL){
3559 checkRequest(*reqIdx);
3560 AmpiRequestList* reqList = getReqs();
3561 AmpiRequest& req = *(*reqList)[*reqIdx];
3569 int AMPI_Is_thread_main(int *flag)
3571 AMPIAPI_INIT("AMPI_Is_thread_main");
3572 if (isAmpiThread()) {
3581 int AMPI_Query_thread(int *provided)
3583 AMPIAPI("AMPI_Query_thread");
3584 *provided = CkpvAccess(ampiThreadLevel);
3589 int AMPI_Init_thread(int *p_argc, char*** p_argv, int required, int *provided)
3591 if (nodeinit_has_been_called) {
3592 AMPIAPI_INIT("AMPI_Init_thread");
3594 #if AMPI_ERROR_CHECKING
3595 if (required < MPI_THREAD_SINGLE || required > MPI_THREAD_MULTIPLE) {
3596 return ampiErrhandler("AMPI_Init_thread", MPI_ERR_ARG);
3600 if (required == MPI_THREAD_SINGLE) {
3601 CkpvAccess(ampiThreadLevel) = MPI_THREAD_SINGLE;
3604 CkpvAccess(ampiThreadLevel) = MPI_THREAD_FUNNELED;
3606 // AMPI does not support MPI_THREAD_SERIALIZED or MPI_THREAD_MULTIPLE
3608 *provided = CkpvAccess(ampiThreadLevel);
3609 return AMPI_Init(p_argc, p_argv);
3612 { /* Charm hasn't been started yet! */
3613 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!");
3619 int AMPI_Init(int *p_argc, char*** p_argv)
3621 if (nodeinit_has_been_called) {
3622 AMPIAPI_INIT("AMPI_Init");
3624 if (p_argv) argv=*p_argv;
3625 else argv=CkGetArgv();
3627 if (p_argc) *p_argc=CmiGetArgc(argv);
3630 { /* Charm hasn't been started yet! */
3631 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!");
3638 int AMPI_Initialized(int *isInit)
3640 if (nodeinit_has_been_called) {
3641 AMPIAPI_INIT("AMPI_Initialized"); /* in case charm init not called */
3642 *isInit=CtvAccess(ampiInitDone);
3644 else /* !nodeinit_has_been_called */ {
3645 *isInit=nodeinit_has_been_called;
3651 int AMPI_Finalized(int *isFinalized)
3653 AMPIAPI_INIT("AMPI_Finalized"); /* in case charm init not called */
3654 *isFinalized=(CtvAccess(ampiFinalized)) ? 1 : 0;
3659 int AMPI_Comm_rank(MPI_Comm comm, int *rank)
3661 AMPIAPI("AMPI_Comm_rank");
3663 #if AMPI_ERROR_CHECKING
3664 int ret = checkCommunicator("AMPI_Comm_rank", comm);
3665 if(ret != MPI_SUCCESS)
3670 ampiParent* pptr = getAmpiParent();
3672 PUParray(*(pptr->fromPUPer), (char*)rank, sizeof(int));
3677 *rank = getAmpiInstance(comm)->getRank();
3680 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3681 PUParray(*(pptr->toPUPer), (char*)rank, sizeof(int));
3688 int AMPI_Comm_size(MPI_Comm comm, int *size)
3690 AMPIAPI("AMPI_Comm_size");
3692 #if AMPI_ERROR_CHECKING
3693 int ret = checkCommunicator("AMPI_Comm_size", comm);
3694 if(ret != MPI_SUCCESS)
3699 ampiParent* pptr = getAmpiParent();
3701 PUParray(*(pptr->fromPUPer), (char*)size, sizeof(int));
3706 *size = getAmpiInstance(comm)->getSize();
3709 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3710 PUParray(*(pptr->toPUPer), (char*)size, sizeof(int));
3718 int AMPI_Comm_compare(MPI_Comm comm1,MPI_Comm comm2, int *result)
3720 AMPIAPI("AMPI_Comm_compare");
3722 #if AMPI_ERROR_CHECKING
3724 ret = checkCommunicator("AMPI_Comm_compare", comm1);
3725 if(ret != MPI_SUCCESS)
3727 ret = checkCommunicator("AMPI_Comm_compare", comm2);
3728 if(ret != MPI_SUCCESS)
3732 if(comm1==comm2) *result=MPI_IDENT;
3735 vector<int> ind1, ind2;
3736 ind1 = getAmpiInstance(comm1)->getIndices();
3737 ind2 = getAmpiInstance(comm2)->getIndices();
3738 if(ind1.size()==ind2.size()){
3739 for(int i=0;i<ind1.size();i++){
3741 for(int j=0;j<ind2.size();j++){
3742 if(ind1[i]==ind2[j]){
3744 if(i!=j) congruent=0;
3748 *result=MPI_UNEQUAL;
3753 if(congruent==1) *result=MPI_CONGRUENT;
3754 else *result=MPI_SIMILAR;
3760 void AMPI_Exit(int exitCode)
3762 // If we are not actually running AMPI code (e.g., by compiling a serial
3763 // application with ampicc), exit cleanly when the application calls exit().
3764 AMPIAPI_INIT("AMPI_Exit");
3767 sprintf(err, "Application terminated with exit code %d.\n", exitCode);
3774 void FTN_NAME(MPI_EXIT,mpi_exit)(int *exitCode)
3776 AMPI_Exit(*exitCode);
3780 int AMPI_Finalize(void)
3782 { // This brace is necessary here to make sure the object created on the stack
3783 // by the AMPIAPI call gets destroyed before the call to AMPI_Exit(), since
3784 // AMPI_Exit() never returns.
3785 AMPIAPI("AMPI_Finalize");
3788 CkPrintf("[%d] Idle time %fs.\n", CkMyPe(), totalidle);
3790 CtvAccess(ampiFinalized)=true;
3792 #if AMPI_PRINT_MSG_SIZES
3793 getAmpiParent()->printMsgSizes();
3796 #if CMK_BIGSIM_CHARM && CMK_TRACE_IN_CHARM
3797 if(CpvAccess(traceOn)) traceSuspend();
3801 AMPI_Exit(0); // Never returns
3805 MPI_Request ampi::postReq(AmpiRequest* newreq)
3807 MPI_Request request = getReqs()->insert(newreq);
3808 // Completed requests should not be inserted into the posted_ireqs queue.
3809 // All types of send requests are matched by their request number,
3810 // not by (tag, src, comm), so they should not be inserted either.
3811 if (!newreq->statusIreq &&
3812 newreq->getType() != MPI_SEND_REQ &&
3813 newreq->getType() != MPI_SSEND_REQ)
3815 int tags[2] = { newreq->tag, newreq->src };
3816 AmmPut(posted_ireqs, tags, (void *)(CmiIntPtr)(request+1));
3822 int AMPI_Send(const void *msg, int count, MPI_Datatype type, int dest, int tag, MPI_Comm comm) {
3823 AMPIAPI("AMPI_Send");
3825 handle_MPI_BOTTOM((void*&)msg, type);
3827 #if AMPI_ERROR_CHECKING
3829 ret = errorCheck("AMPI_Send", comm, 1, count, 1, type, 1, tag, 1, dest, 1, msg, 1);
3830 if(ret != MPI_SUCCESS)
3840 ampi *ptr = getAmpiInstance(comm);
3841 ptr->send(tag, ptr->getRank(), msg, count, type, dest, comm);
3847 int AMPI_Ssend(const void *msg, int count, MPI_Datatype type, int dest, int tag, MPI_Comm comm)
3849 AMPIAPI("AMPI_Ssend");
3851 handle_MPI_BOTTOM((void*&)msg, type);
3853 #if AMPI_ERROR_CHECKING
3854 int ret = errorCheck("AMPI_Ssend", comm, 1, count, 1, type, 1, tag, 1, dest, 1, msg, 1);
3855 if(ret != MPI_SUCCESS)
3865 ampi *ptr = getAmpiInstance(comm);
3866 ptr->send(tag, ptr->getRank(), msg, count, type, dest, comm, 1);
3872 int AMPI_Issend(const void *buf, int count, MPI_Datatype type, int dest,
3873 int tag, MPI_Comm comm, MPI_Request *request)
3875 AMPIAPI("AMPI_Issend");
3877 handle_MPI_BOTTOM((void*&)buf, type);
3879 #if AMPI_ERROR_CHECKING
3880 int ret = errorCheck("AMPI_Issend", comm, 1, count, 1, type, 1, tag, 1, dest, 1, buf, 1);
3881 if(ret != MPI_SUCCESS){
3882 *request = MPI_REQUEST_NULL;
3888 ampiParent* pptr = getAmpiParent();
3890 PUParray(*(pptr->fromPUPer), (char *)request, sizeof(MPI_Request));
3895 USER_CALL_DEBUG("AMPI_Issend("<<type<<","<<dest<<","<<tag<<","<<comm<<")");
3896 ampi *ptr = getAmpiInstance(comm);
3897 *request = ptr->postReq(new SsendReq(comm));
3898 // 1: blocking now - used by MPI_Ssend
3899 // >=2: the index of the requests - used by MPI_Issend
3900 ptr->send(tag, ptr->getRank(), buf, count, type, dest, comm, *request+2, I_SEND);
3903 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3904 PUParray(*(pptr->toPUPer), (char *)request, sizeof(MPI_Request));
3912 int AMPI_Recv(void *msg, int count, MPI_Datatype type, int src, int tag,
3913 MPI_Comm comm, MPI_Status *status)
3915 AMPIAPI("AMPI_Recv");
3917 handle_MPI_BOTTOM(msg, type);
3919 #if AMPI_ERROR_CHECKING
3920 int ret = errorCheck("AMPI_Recv", comm, 1, count, 1, type, 1, tag, 1, src, 1, msg, 1);
3921 if(ret != MPI_SUCCESS)
3926 ampiParent* pptr = getAmpiParent();
3928 (*(pptr->fromPUPer))|(pptr->pupBytes);
3929 PUParray(*(pptr->fromPUPer), (char *)msg, (pptr->pupBytes));
3930 PUParray(*(pptr->fromPUPer), (char *)status, sizeof(MPI_Status));
3935 ampi *ptr = getAmpiInstance(comm);
3936 if(-1==ptr->recv(tag,src,msg,count,type,comm,status)) CkAbort("AMPI> Error in MPI_Recv");
3939 if(msgLogWrite && record_msglog(pptr->thisIndex)){
3940 (pptr->pupBytes) = getDDT()->getSize(type) * count;
3941 (*(pptr->toPUPer))|(pptr->pupBytes);
3942 PUParray(*(pptr->toPUPer), (char *)msg, (pptr->pupBytes));
3943 PUParray(*(pptr->toPUPer), (char *)status, sizeof(MPI_Status));
3951 int AMPI_Probe(int src, int tag, MPI_Comm comm, MPI_Status *status)
3953 AMPIAPI("AMPI_Probe");
3955 #if AMPI_ERROR_CHECKING
3956 int ret = errorCheck("AMPI_Probe", comm, 1, 0, 0, 0, 0, tag, 1, src, 1, 0, 0);
3957 if(ret != MPI_SUCCESS)
3961 ampi *ptr = getAmpiInstance(comm);
3962 ptr->probe(tag, src, comm, status);
3967 int AMPI_Iprobe(int src,int tag,MPI_Comm comm,int *flag,MPI_Status *status)
3969 AMPIAPI("AMPI_Iprobe");
3971 #if AMPI_ERROR_CHECKING
3972 int ret = errorCheck("AMPI_Iprobe", comm, 1, 0, 0, 0, 0, tag, 1, src, 1, 0, 0);
3973 if(ret != MPI_SUCCESS)
3977 ampi *ptr = getAmpiInstance(comm);
3978 *flag = ptr->iprobe(tag, src, comm, status);
3982 void ampi::sendrecv(const void *sbuf, int scount, MPI_Datatype stype, int dest, int stag,
3983 void *rbuf, int rcount, MPI_Datatype rtype, int src, int rtag,
3984 MPI_Comm comm, MPI_Status *sts)
3986 MPI_Request reqs[2];
3987 irecv(rbuf, rcount, rtype, src, rtag, comm, &reqs[0]);
3989 reqs[1] = send(stag, getRank(), sbuf, scount, stype, dest, comm, 0, I_SEND);
3991 if (sts == MPI_STATUS_IGNORE) {
3992 AMPI_Waitall(2, reqs, MPI_STATUSES_IGNORE);
3995 MPI_Status statuses[2];
3996 AMPI_Waitall(2, reqs, statuses);
4002 int AMPI_Sendrecv(const void *sbuf, int scount, MPI_Datatype stype, int dest,
4003 int stag, void *rbuf, int rcount, MPI_Datatype rtype,
4004 int src, int rtag, MPI_Comm comm, MPI_Status *sts)
4006 AMPIAPI("AMPI_Sendrecv");
4008 handle_MPI_BOTTOM((void*&)sbuf, stype, rbuf, rtype);
4010 #if AMPI_ERROR_CHECKING
4011 if(sbuf == MPI_IN_PLACE || rbuf == MPI_IN_PLACE)
4012 CkAbort("MPI_sendrecv does not accept MPI_IN_PLACE; use MPI_Sendrecv_replace instead.");
4014 ret = errorCheck("AMPI_Sendrecv", comm, 1, scount, 1, stype, 1, stag, 1, dest, 1, sbuf, 1);
4015 if(ret != MPI_SUCCESS)
4017 ret = errorCheck("AMPI_Sendrecv", comm, 1, rcount, 1, rtype, 1, rtag, 1, src, 1, rbuf, 1);
4018 if(ret != MPI_SUCCESS)
4022 ampi *ptr = getAmpiInstance(comm);
4024 ptr->sendrecv(sbuf, scount, stype, dest, stag,
4025 rbuf, rcount, rtype, src, rtag,
4032 int AMPI_Sendrecv_replace(void* buf, int count, MPI_Datatype datatype,
4033 int dest, int sendtag, int source, int recvtag,
4034 MPI_Comm comm, MPI_Status *status)
4036 AMPIAPI("AMPI_Sendrecv_replace");
4038 handle_MPI_BOTTOM(buf, datatype, buf, datatype);
4040 #if AMPI_ERROR_CHECKING
4042 ret = errorCheck("AMPI_Sendrecv_replace", comm, 1, count, 1, datatype, 1, sendtag, 1, dest, 1, buf, 1);
4043 if(ret != MPI_SUCCESS)
4045 ret = errorCheck("AMPI_Sendrecv_replace", comm, 1, count, 1, datatype, 1, recvtag, 1, source, 1, buf, 1);
4046 if(ret != MPI_SUCCESS)
4050 ampi* ptr = getAmpiInstance(comm);
4053 ptr->irecv(buf, count, datatype, source, recvtag, comm, &req);
4055 CkDDT_DataType* ddt = getDDT()->getType(datatype);
4056 vector<char> tmpBuf(ddt->getSize(count));
4057 ddt->serialize((char*)buf, &tmpBuf[0], count, 1);
4059 // FIXME: this send may do a copy internally! If we knew now that it would, we could avoid double copying:
4060 ptr->send(sendtag, source, &tmpBuf[0], count, datatype, dest, comm, 0, BLOCKING_SEND);
4062 AMPI_Wait(&req, status);
4067 void ampi::barrier()
4069 CkCallback barrierCB(CkReductionTarget(ampi, barrierResult), getProxy());
4070 contribute(barrierCB);
4071 thread->suspend(); //Resumed by ampi::barrierResult
4074 void ampi::barrierResult(void)
4076 MSG_ORDER_DEBUG(CkPrintf("[%d] barrierResult called\n", thisIndex));
4081 int AMPI_Barrier(MPI_Comm comm)
4083 AMPIAPI("AMPI_Barrier");
4085 #if AMPI_ERROR_CHECKING
4086 int ret = checkCommunicator("AMPI_Barrier", comm);
4087 if(ret != MPI_SUCCESS)
4091 #if CMK_BIGSIM_CHARM
4092 TRACE_BG_AMPI_LOG(MPI_BARRIER, 0);
4095 ampi *ptr = getAmpiInstance(comm);
4096 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Barrier called on comm %d\n", ptr->thisIndex, comm));
4098 if (ptr->getSize() == 1 && !getAmpiParent()->isInter(comm))
4101 // implementation of intercomm barrier is equivalent to that for intracomm barrier
4108 void ampi::ibarrier(MPI_Request *request)
4110 CkCallback ibarrierCB(CkReductionTarget(ampi, ibarrierResult), getProxy());
4111 contribute(ibarrierCB);
4113 // use an IReq to non-block the caller and get a request ptr
4114 *request = postReq(new IReq(NULL, 0, MPI_INT, AMPI_COLL_SOURCE, MPI_ATA_TAG, myComm.getComm()));
4117 void ampi::ibarrierResult(void)
4119 MSG_ORDER_DEBUG(CkPrintf("[%d] ibarrierResult called\n", thisIndex));
4120 ampi::sendraw(MPI_ATA_TAG, AMPI_COLL_SOURCE, NULL, 0, thisArrayID, thisIndex);
4124 int AMPI_Ibarrier(MPI_Comm comm, MPI_Request *request)
4126 AMPIAPI("AMPI_Ibarrier");
4128 #if AMPI_ERROR_CHECKING
4129 int ret = checkCommunicator("AMPI_Ibarrier", comm);
4130 if(ret != MPI_SUCCESS){
4131 *request = MPI_REQUEST_NULL;
4136 ampi *ptr = getAmpiInstance(comm);
4138 if (ptr->getSize() == 1 && !getAmpiParent()->isInter(comm)) {
4139 *request = ptr->postReq(new IReq(NULL, 0, MPI_INT, AMPI_COLL_SOURCE, MPI_ATA_TAG, AMPI_COLL_COMM,
4140 AMPI_REQ_COMPLETED));
4144 // implementation of intercomm ibarrier is equivalent to that for intracomm ibarrier
4146 #if CMK_BIGSIM_CHARM
4147 TRACE_BG_AMPI_LOG(MPI_BARRIER, 0);
4150 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Ibarrier called on comm %d\n", ptr->thisIndex, comm));
4152 ptr->ibarrier(request);
4158 int AMPI_Bcast(void *buf, int count, MPI_Datatype type, int root, MPI_Comm comm)
4160 AMPIAPI("AMPI_Bcast");
4162 handle_MPI_BOTTOM(buf, type);
4164 #if AMPI_ERROR_CHECKING
4165 int validateBuf = 1;
4166 if (getAmpiParent()->isInter(comm)) {
4167 //if comm is an intercomm, then only root and remote ranks need to have a valid buf
4168 //local ranks need not validate it
4169 if (root==MPI_PROC_NULL) validateBuf = 0;
4171 int ret = errorCheck("AMPI_Bcast", comm, 1, count, 1, type, 1, 0, 0, root, 1, buf, validateBuf);
4173 if(ret != MPI_SUCCESS)
4177 ampi* ptr = getAmpiInstance(comm);
4179 if(getAmpiParent()->isInter(comm)) {
4180 return ptr->intercomm_bcast(root, buf, count, type, comm);
4182 if(ptr->getSize() == 1)
4186 ampiParent* pptr = getAmpiParent();
4188 (*(pptr->fromPUPer))|(pptr->pupBytes);
4189 PUParray(*(pptr->fromPUPer), (char *)buf, (pptr->pupBytes));
4194 ptr->bcast(root, buf, count, type,comm);
4197 if(msgLogWrite && record_msglog(pptr->thisIndex)) {
4198 (pptr->pupBytes) = getDDT()->getSize(type) * count;
4199 (*(pptr->toPUPer))|(pptr->pupBytes);
4200 PUParray(*(pptr->toPUPer), (char *)buf, (pptr->pupBytes));
4208 int AMPI_Ibcast(void *buf, int count, MPI_Datatype type, int root,
4209 MPI_Comm comm, MPI_Request *request)
4211 AMPIAPI("AMPI_Ibcast");
4213 handle_MPI_BOTTOM(buf, type);
4215 #if AMPI_ERROR_CHECKING
4216 int validateBuf = 1;
4217 if (getAmpiParent()->isInter(comm)) {
4218 //if comm is an intercomm, then only root and remote ranks need to have a valid buf
4219 //local ranks need not validate it
4220 if (root==MPI_PROC_NULL) validateBuf = 0;
4222 int ret = errorCheck("AMPI_Ibcast", comm, 1, count, 1, type, 1, 0, 0, root, 1, buf, validateBuf);
4224 if(ret != MPI_SUCCESS){
4225 *request = MPI_REQUEST_NULL;
4230 ampi* ptr = getAmpiInstance(comm);
4232 if(getAmpiParent()->isInter(comm)) {
4233 return ptr->intercomm_ibcast(root, buf, count, type, comm, request);
4235 if(ptr->getSize() == 1){
4236 *request = ptr->postReq(new IReq(buf, count, type, root, MPI_BCAST_TAG, comm,
4237 AMPI_REQ_COMPLETED));
4242 ampiParent* pptr = getAmpiParent();
4244 (*(pptr->fromPUPer))|(pptr->pupBytes);
4245 PUParray(*(pptr->fromPUPer), (char *)buf, (pptr->pupBytes));
4250 ptr->ibcast(root, buf, count, type, comm, request);
4253 if(msgLogWrite && record_msglog(pptr->thisIndex)) {
4254 (pptr->pupBytes) = getDDT()->getSize(type) * count;
4255 (*(pptr->toPUPer))|(pptr->pupBytes);
4256 PUParray(*(pptr->toPUPer), (char *)buf, (pptr->pupBytes));
4263 // This routine is called with the results of an (All)Reduce or (All)Gather(v)
4264 void ampi::rednResult(CkReductionMsg *msg)
4266 MSG_ORDER_DEBUG(CkPrintf("[%d] rednResult called on comm %d\n", thisIndex, myComm.getComm()));
4268 if (blockingReq == NULL) {
4269 CkAbort("AMPI> recv'ed a blocking reduction unexpectedly!\n");
4272 #if CMK_BIGSIM_CHARM
4273 TRACE_BG_ADD_TAG("AMPI_generic");
4275 _TRACE_BG_TLINE_END(&msg->event); // store current log
4276 msg->eventPe = CkMyPe();
4279 blockingReq->receive(this, msg);
4281 if (parent->resumeOnColl) {
4284 // [nokeep] entry method, so do not delete msg
4287 // This routine is called with the results of an I(all)reduce or I(all)gather(v)
4288 void ampi::irednResult(CkReductionMsg *msg)
4290 MSG_ORDER_DEBUG(CkPrintf("[%d] irednResult called on comm %d\n", thisIndex, myComm.getComm()));
4293 int tags[2] = { MPI_REDN_TAG, AMPI_COLL_SOURCE };
4294 AmpiRequestList *reqL = &(parent->ampiReqs);
4295 int rednReqIdx = (int)((long)AmmGet(posted_ireqs, tags, (int*)&sts));
4296 AmpiRequest *rednReq = NULL;
4297 if(reqL->size()>0 && rednReqIdx>0)
4298 rednReq = (AmpiRequest *)(*reqL)[rednReqIdx-1];
4299 if (rednReq == NULL)
4300 CkAbort("AMPI> recv'ed a non-blocking reduction unexpectedly!\n");
4302 #if CMK_BIGSIM_CHARM
4303 TRACE_BG_ADD_TAG("AMPI_generic");
4305 _TRACE_BG_TLINE_END(&msg->event); // store current log
4306 msg->eventPe = CkMyPe();
4310 PUParray(*(getAmpiParent()->fromPUPer), (char *)rednReq, sizeof(int));
4315 if (rednReq->isBlocked() && parent->numBlockedReqs != 0) {
4316 parent->numBlockedReqs--;
4318 rednReq->receive(this, msg);
4321 if(msgLogWrite && record_msglog(getAmpiParent()->thisIndex)){
4322 PUParray(*(getAmpiParent()->toPUPer), (char *)reqnReq, sizeof(int));
4326 if (parent->resumeOnColl && parent->numBlockedReqs==0) {
4329 // [nokeep] entry method, so do not delete msg
4332 static CkReductionMsg *makeRednMsg(CkDDT_DataType *ddt,const void *inbuf,int count,int type,int rank,MPI_Op op)
4334 CkReductionMsg *msg;
4335 ampiParent *parent = getAmpiParent();
4336 int szdata = ddt->getSize(count);
4337 CkReduction::reducerType reducer = getBuiltinReducerType(type, op);
4339 if (reducer != CkReduction::invalid) {
4340 // MPI predefined op matches a Charm++ builtin reducer type
4341 AMPI_DEBUG("[%d] In makeRednMsg, using Charm++ built-in reducer type for a predefined op\n", parent->thisIndex);
4342 msg = CkReductionMsg::buildNew(szdata, NULL, reducer);
4343 ddt->serialize((char*)inbuf, (char*)msg->getData(), count, 1);
4345 else if (parent->opIsCommutative(op) && ddt->isContig()) {
4346 // Either an MPI predefined reducer operation with no Charm++ builtin reducer type equivalent, or
4347 // a commutative user-defined reducer operation on a contiguous datatype
4348 AMPI_DEBUG("[%d] In makeRednMsg, using custom AmpiReducer type for a commutative op\n", parent->thisIndex);
4349 AmpiOpHeader newhdr = parent->op2AmpiOpHeader(op, type, count);
4350 int szhdr = sizeof(AmpiOpHeader);
4351 msg = CkReductionMsg::buildNew(szdata+szhdr, NULL, AmpiReducer);
4352 memcpy(msg->getData(), &newhdr, szhdr);
4353 ddt->serialize((char*)inbuf, (char*)msg->getData()+szhdr, count, 1);
4356 // Non-commutative user-defined reducer operation, or
4357 // a commutative user-defined reduction on a non-contiguous datatype
4358 AMPI_DEBUG("[%d] In makeRednMsg, using a non-commutative user-defined operation\n", parent->thisIndex);
4359 const int tupleSize = 2;
4360 CkReduction::tupleElement tupleRedn[tupleSize];
4361 tupleRedn[0] = CkReduction::tupleElement(sizeof(int), &rank, CkReduction::set);
4362 if (!ddt->isContig()) {
4363 vector<char> sbuf(szdata);
4364 ddt->serialize((char*)inbuf, &sbuf[0], count, 1);
4365 tupleRedn[1] = CkReduction::tupleElement(szdata, &sbuf[0], CkReduction::set);
4368 tupleRedn[1] = CkReduction::tupleElement(szdata, (void*)inbuf, CkReduction::set);
4370 msg = CkReductionMsg::buildFromTuple(tupleRedn, tupleSize);
4375 // Copy the MPI datatype "type" from inbuf to outbuf
4376 static int copyDatatype(MPI_Datatype sendtype, int sendcount, MPI_Datatype recvtype,
4377 int recvcount, const void *inbuf, void *outbuf)
4379 if (inbuf == outbuf) return MPI_SUCCESS; // handle MPI_IN_PLACE
4381 CkDDT_DataType *sddt = getDDT()->getType(sendtype);
4382 int slen = sddt->getSize(sendcount);
4383 CkDDT_DataType *rddt = getDDT()->getType(recvtype);
4385 if (sddt->isContig() && rddt->isContig()) {
4386 memcpy(outbuf, inbuf, slen);
4388 // ddts don't have "copy", so fake it by serializing into a temp buffer, then
4389 // deserializing into the output.
4390 vector<char> serialized(slen);
4391 sddt->serialize((char*)inbuf, &serialized[0], sendcount, 1);
4392 rddt->serialize((char*)outbuf, &serialized[0], recvcount, -1);
4398 static void handle_MPI_IN_PLACE(void* &inbuf, void* &outbuf)
4400 if (inbuf == MPI_IN_PLACE) inbuf = outbuf;
4401 if (outbuf == MPI_IN_PLACE) outbuf = inbuf;
4402 CkAssert(inbuf != MPI_IN_PLACE && outbuf != MPI_IN_PLACE);
4405 static void handle_MPI_IN_PLACE_gather(void* &sendbuf, void* recvbuf, int &sendcount,
4406 MPI_Datatype &sendtype, int recvdispl,
4407 int recvcount, MPI_Datatype recvtype)
4409 if (sendbuf == MPI_IN_PLACE) {
4410 // The MPI standard says that when MPI_IN_PLACE is passed to any of the gather
4411 // variants, the contribution of the root to the gathered vector is assumed
4412 // to be already in the correct place in the receive buffer.
4413 sendbuf = (char*)recvbuf + (recvdispl * getDDT()->getExtent(recvtype));
4414 sendcount = recvcount;
4415 sendtype = recvtype;
4417 CkAssert(recvbuf != MPI_IN_PLACE);
4420 static void handle_MPI_IN_PLACE_alltoall(void* &sendbuf, void* recvbuf, int &sendcount,
4421 MPI_Datatype &sendtype, int recvcount,
4422 MPI_Datatype recvtype)
4424 if (sendbuf == MPI_IN_PLACE) {
4426 sendcount = recvcount;
4427 sendtype = recvtype;
4429 CkAssert(recvbuf != MPI_IN_PLACE);
4432 static void handle_MPI_IN_PLACE_alltoallv(void* &sendbuf, void* recvbuf, int* &sendcounts,
4433 MPI_Datatype &sendtype, int* &sdispls,
4434 const int* recvcounts, MPI_Datatype recvtype,
4437 if (sendbuf == MPI_IN_PLACE) {
4439 sendcounts = (int*)recvcounts;
4440 sendtype = recvtype;
4441 sdispls = (int*)rdispls;
4443 CkAssert(recvbuf != MPI_IN_PLACE);
4446 static void handle_MPI_IN_PLACE_alltoallw(void* &sendbuf, void* recvbuf, int* &sendcounts,
4447 MPI_Datatype* &sendtypes, int* &sdispls,
4448 const int* recvcounts, const MPI_Datatype* recvtypes,
4451 if (sendbuf == MPI_IN_PLACE) {
4453 sendcounts = (int*)recvcounts;
4454 sendtypes = (MPI_Datatype*)recvtypes;
4455 sdispls = (int*)rdispls;
4457 CkAssert(recvbuf != MPI_IN_PLACE);
4460 #define AMPI_SYNC_REDUCE 0
4463 int AMPI_Reduce(const void *inbuf, void *outbuf, int count, MPI_Datatype type, MPI_Op op, int root, MPI_Comm comm)
4465 AMPIAPI("AMPI_Reduce");
4467 handle_MPI_BOTTOM((void*&)inbuf, type, outbuf, type);
4468 handle_MPI_IN_PLACE((void*&)inbuf, outbuf);
4470 #if AMPI_ERROR_CHECKING
4471 if(op == MPI_OP_NULL)
4472 return ampiErrhandler("AMPI_Reduce", MPI_ERR_OP);
4473 int ret = errorCheck("AMPI_Reduce", comm, 1, count, 1, type, 1, 0, 0, root, 1, inbuf, 1,
4474 outbuf, getAmpiInstance(comm)->getRank() == root);
4475 if(ret != MPI_SUCCESS)
4479 ampi *ptr = getAmpiInstance(comm);
4481 if(getAmpiParent()->isInter(comm))
4482 CkAbort("AMPI does not implement MPI_Reduce for Inter-communicators!");
4483 if(ptr->getSize() == 1)
4484 return copyDatatype(type,count,type,count,inbuf,outbuf);
4487 ampiParent* pptr = getAmpiParent();
4489 (*(pptr->fromPUPer))|(pptr->pupBytes);
4490 PUParray(*(pptr->fromPUPer), (char *)outbuf, (pptr->pupBytes));
4495 int rootIdx=ptr->comm2CommStruct(comm).getIndexForRank(root);
4496 CkReductionMsg *msg=makeRednMsg(ptr->getDDT()->getType(type),inbuf,count,type,ptr->getRank(),op);
4498 CkCallback reduceCB(CkIndex_ampi::rednResult(0),CkArrayIndex1D(rootIdx),ptr->getProxy());
4499 msg->setCallback(reduceCB);
4500 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Reduce called on comm %d root %d \n",ptr->thisIndex,comm,rootIdx));
4501 ptr->contribute(msg);
4503 if (ptr->thisIndex == rootIdx){
4504 ptr = ptr->blockOnRedn(new RednReq(outbuf, count, type, comm, op));
4506 #if AMPI_SYNC_REDUCE
4507 AmpiMsg *msg = new (0, 0) AmpiMsg(-1, MPI_REDN_TAG, rootIdx, 0);
4508 CProxy_ampi pa(ptr->getProxy());
4512 #if AMPI_SYNC_REDUCE
4513 ptr->recv(MPI_REDN_TAG, AMPI_COLL_SOURCE, NULL, 0, type, comm);
4517 if(msgLogWrite && record_msglog(pptr->thisIndex)){
4518 (pptr->pupBytes) = getDDT()->getSize(type) * count;
4519 (*(pptr->toPUPer))|(pptr->pupBytes);
4520 PUParray(*(pptr->toPUPer), (char *)outbuf, (pptr->pupBytes));
4528 int AMPI_Allreduce(const void *inbuf, void *outbuf, int count, MPI_Datatype type, MPI_Op op, MPI_Comm comm)
4530 AMPIAPI("AMPI_Allreduce");
4532 handle_MPI_BOTTOM((void*&)inbuf, type, outbuf, type);
4533 handle_MPI_IN_PLACE((void*&)inbuf, outbuf);
4535 #if AMPI_ERROR_CHECKING
4536 if(op == MPI_OP_NULL)
4537 return ampiErrhandler("AMPI_Allreduce", MPI_ERR_OP);
4538 int ret = errorCheck("AMPI_Allreduce", comm, 1, count, 1, type, 1, 0, 0, 0, 0, inbuf, 1, outbuf, 1);
4539 if(ret != MPI_SUCCESS)
4543 ampi *ptr = getAmpiInstance(comm);
4545 if(getAmpiParent()->isInter(comm))
4546 CkAbort("AMPI does not implement MPI_Allreduce for Inter-communicators!");
4547 if(ptr->getSize() == 1)
4548 return copyDatatype(type,count,type,count,inbuf,outbuf);
4550 #if CMK_BIGSIM_CHARM
4551 TRACE_BG_AMPI_LOG(MPI_ALLREDUCE, getAmpiInstance(comm)->getDDT()->getType(type)->getSize(count));
4555 ampiParent* pptr = getAmpiParent();
4557 (*(pptr->fromPUPer))|(pptr->pupBytes);
4558 PUParray(*(pptr->fromPUPer), (char *)outbuf, (pptr->pupBytes));
4563 CkReductionMsg *msg=makeRednMsg(ptr->getDDT()->getType(type), inbuf, count, type, ptr->getRank(), op);
4564 CkCallback allreduceCB(CkIndex_ampi::rednResult(0),ptr->getProxy());
4565 msg->setCallback(allreduceCB);
4566 ptr->contribute(msg);
4568 ptr->blockOnRedn(new RednReq(outbuf, count, type, comm, op));
4571 if(msgLogWrite && record_msglog(pptr->thisIndex)){
4572 (pptr->pupBytes) = getDDT()->getSize(type) * count;
4573 (*(pptr->toPUPer))|(pptr->pupBytes);
4574 PUParray(*(pptr->toPUPer), (char *)outbuf, (pptr->pupBytes));
4582 int AMPI_Iallreduce(const void *inbuf, void *outbuf, int count, MPI_Datatype type, MPI_Op op,
4583 MPI_Comm comm, MPI_Request* request)
4585 AMPIAPI("AMPI_Iallreduce");
4587 handle_MPI_BOTTOM((void*&)inbuf, type, outbuf, type);
4588 handle_MPI_IN_PLACE((void*&)inbuf, outbuf);
4590 #if AMPI_ERROR_CHECKING
4591 if(op == MPI_OP_NULL)
4592 return ampiErrhandler("AMPI_Iallreduce", MPI_ERR_OP);
4593 int ret = errorCheck("AMPI_Iallreduce", comm, 1, count, 1, type, 1, 0, 0, 0, 0, inbuf, 1, outbuf, 1);
4594 if(ret != MPI_SUCCESS){
4595 *request = MPI_REQUEST_NULL;
4600 ampi *ptr = getAmpiInstance(comm);
4602 if(getAmpiParent()->isInter(comm))
4603 CkAbort("AMPI does not implement MPI_Iallreduce for Inter-communicators!");
4604 if(ptr->getSize() == 1){
4605 *request = ptr->postReq(new RednReq(outbuf,count,type,comm,op,AMPI_REQ_COMPLETED));
4606 return copyDatatype(type,count,type,count,inbuf,outbuf);
4609 CkReductionMsg *msg=makeRednMsg(ptr->getDDT()->getType(type),inbuf,count,type,ptr->getRank(),op);
4610 CkCallback allreduceCB(CkIndex_ampi::irednResult(0),ptr->getProxy());
4611 msg->setCallback(allreduceCB);
4612 ptr->contribute(msg);
4614 // use a RednReq to non-block the caller and get a request ptr
4615 *request = ptr->postReq(new RednReq(outbuf,count,type,comm,op));
4621 int AMPI_Reduce_local(const void *inbuf, void *outbuf, int count, MPI_Datatype type, MPI_Op op)
4623 AMPIAPI("AMPI_Reduce_local");
4625 handle_MPI_BOTTOM((void*&)inbuf, type, outbuf, type);
4627 #if AMPI_ERROR_CHECKING
4628 if(op == MPI_OP_NULL)
4629 return ampiErrhandler("AMPI_Reduce_local", MPI_ERR_OP);
4630 if(inbuf == MPI_IN_PLACE || outbuf == MPI_IN_PLACE)
4631 CkAbort("MPI_Reduce_local does not accept MPI_IN_PLACE!");
4632 int ret = errorCheck("AMPI_Reduce_local", MPI_COMM_SELF, 1, count, 1, type, 1, 0, 0, 0, 1, inbuf, 1, outbuf, 1);
4633 if(ret != MPI_SUCCESS)
4637 getAmpiParent()->applyOp(type, op, count, inbuf, outbuf);
4642 int AMPI_Reduce_scatter_block(const void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype,
4643 MPI_Op op, MPI_Comm comm)
4645 AMPIAPI("AMPI_Reduce_scatter_block");
4647 handle_MPI_BOTTOM((void*&)sendbuf, datatype, recvbuf, datatype);
4648 handle_MPI_IN_PLACE((void*&)sendbuf, recvbuf);
4650 #if AMPI_ERROR_CHECKING
4651 if(op == MPI_OP_NULL)
4652 return ampiErrhandler("AMPI_Reduce_scatter_block", MPI_ERR_OP);
4653 int ret = errorCheck("AMPI_Reduce_scatter_block", comm, 1, 0, 0, datatype, 1, 0, 0, 0, 0, sendbuf, 1, recvbuf, 1);
4654 if(ret != MPI_SUCCESS)
4658 ampi *ptr = getAmpiInstance(comm);
4659 int size = ptr->getSize();
4661 if(getAmpiParent()->isInter(comm))
4662 CkAbort("AMPI does not implement MPI_Reduce_scatter_block for Inter-communicators!");
4664 return copyDatatype(datatype, count, datatype, count, sendbuf, recvbuf);
4666 vector<char> tmpbuf(ptr->getDDT()->getType(datatype)->getSize(count)*size);
4668 AMPI_Reduce(sendbuf, &tmpbuf[0], count*size, datatype, op, AMPI_COLL_SOURCE, comm);
4669 AMPI_Scatter(&tmpbuf[0], count, datatype, recvbuf, count, datatype, AMPI_COLL_SOURCE, comm);
4675 int AMPI_Reduce_scatter(const void* sendbuf, void* recvbuf, const int *recvcounts, MPI_Datatype datatype,
4676 MPI_Op op, MPI_Comm comm)
4678 AMPIAPI("AMPI_Reduce_scatter");
4680 handle_MPI_BOTTOM((void*&)sendbuf, datatype, recvbuf, datatype);
4681 handle_MPI_IN_PLACE((void*&)sendbuf, recvbuf);
4683 #if AMPI_ERROR_CHECKING
4684 if(op == MPI_OP_NULL)
4685 return ampiErrhandler("AMPI_Reduce_scatter", MPI_ERR_OP);
4686 int ret = errorCheck("AMPI_Reduce_scatter", comm, 1, 0, 0, datatype, 1, 0, 0, 0, 0, sendbuf, 1, recvbuf, 1);
4687 if(ret != MPI_SUCCESS)
4691 ampi *ptr = getAmpiInstance(comm);
4692 int size = ptr->getSize();
4694 if(getAmpiParent()->isInter(comm))
4695 CkAbort("AMPI does not implement MPI_Reduce_scatter for Inter-communicators!");
4697 return copyDatatype(datatype,recvcounts[0],datatype,recvcounts[0],sendbuf,recvbuf);
4700 vector<int> displs(size);
4703 //under construction
4704 for(int i=0;i<size;i++){
4706 count+= recvcounts[i];
4708 vector<char> tmpbuf(ptr->getDDT()->getType(datatype)->getSize(count));
4709 AMPI_Reduce(sendbuf, &tmpbuf[0], count, datatype, op, AMPI_COLL_SOURCE, comm);
4710 AMPI_Scatterv(&tmpbuf[0], recvcounts, &displs[0], datatype,
4711 recvbuf, recvcounts[ptr->getRank()], datatype, AMPI_COLL_SOURCE, comm);
4716 int AMPI_Scan(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype,
4717 MPI_Op op, MPI_Comm comm ){
4718 AMPIAPI("AMPI_Scan");
4720 handle_MPI_BOTTOM(sendbuf, datatype, recvbuf, datatype);
4721 handle_MPI_IN_PLACE(sendbuf,recvbuf);
4723 #if AMPI_ERROR_CHECKING
4724 if(op == MPI_OP_NULL)
4725 return ampiErrhandler("AMPI_Scan", MPI_ERR_OP);
4726 int ret = errorCheck("AMPI_Scan", comm, 1, count, 1, datatype, 1, 0, 0, 0, 0, sendbuf, 1, recvbuf, 1);
4727 if(ret != MPI_SUCCESS)
4731 ampi *ptr = getAmpiInstance(comm);
4732 int size = ptr->getSize();
4734 if (size == 1 && !getAmpiParent()->isInter(comm))
4735 return copyDatatype(datatype, count, datatype, count, sendbuf, recvbuf);
4737 int blklen = ptr->getDDT()->getType(datatype)->getSize(count);
4738 int rank = ptr->getRank();
4741 vector<char> tmp_buf(blklen);
4742 vector<char> partial_scan(blklen);
4744 memcpy(recvbuf, sendbuf, blklen);
4745 memcpy(&partial_scan[0], sendbuf, blklen);
4749 ptr->sendrecv(&partial_scan[0], count, datatype, dst, MPI_SCAN_TAG,
4750 &tmp_buf[0], count, datatype, dst, MPI_SCAN_TAG, comm, MPI_STATUS_IGNORE);
4752 getAmpiParent()->applyOp(datatype, op, count, &tmp_buf[0], &partial_scan[0]);
4753 getAmpiParent()->applyOp(datatype, op, count, &tmp_buf[0], recvbuf);
4755 getAmpiParent()->applyOp(datatype, op, count, &partial_scan[0], &tmp_buf[0]);
4756 memcpy(&partial_scan[0],&tmp_buf[0],blklen);
4766 int AMPI_Exscan(const void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype,
4767 MPI_Op op, MPI_Comm comm){
4768 AMPIAPI("AMPI_Exscan");
4770 handle_MPI_BOTTOM((void*&)sendbuf, datatype, recvbuf, datatype);
4771 handle_MPI_IN_PLACE((void*&)sendbuf,recvbuf);
4773 #if AMPI_ERROR_CHECKING
4774 if(op == MPI_OP_NULL)
4775 return ampiErrhandler("AMPI_Exscan", MPI_ERR_OP);
4776 int ret = errorCheck("AMPI_Excan", comm, 1, count, 1, datatype, 1, 0, 0, 0, 0, sendbuf, 1, recvbuf, 1);
4777 if(ret != MPI_SUCCESS)
4781 ampi *ptr = getAmpiInstance(comm);
4782 int size = ptr->getSize();
4784 if (size == 1 && !getAmpiParent()->isInter(comm))
4787 int blklen = ptr->getDDT()->getType(datatype)->getSize(count);
4788 int rank = ptr->getRank();
4791 vector<char> tmp_buf(blklen);
4792 vector<char> partial_scan(blklen);
4794 if (rank > 0) memcpy(recvbuf, sendbuf, blklen);
4795 memcpy(&partial_scan[0], sendbuf, blklen);
4801 ptr->sendrecv(&partial_scan[0], count, datatype, dst, MPI_EXSCAN_TAG,
4802 &tmp_buf[0], count, datatype, dst, MPI_EXSCAN_TAG, comm, MPI_STATUS_IGNORE);
4804 getAmpiParent()->applyOp(datatype, op, count, &tmp_buf[0], &partial_scan[0]);
4807 memcpy(recvbuf,&tmp_buf[0],blklen);
4811 getAmpiParent()->applyOp(datatype, op, count, &tmp_buf[0], recvbuf);
4816 getAmpiParent()->applyOp(datatype, op, count, &partial_scan[0], &tmp_buf[0]);
4817 memcpy(&partial_scan[0],&tmp_buf[0],blklen);
4827 int AMPI_Op_create(MPI_User_function *function, int commute, MPI_Op *op){
4828 AMPIAPI("AMPI_Op_create");
4829 *op = getAmpiParent()->createOp(function, commute);
4834 int AMPI_Op_free(MPI_Op *op){
4835 AMPIAPI("AMPI_Op_free");
4836 getAmpiParent()->freeOp(*op);
4842 int AMPI_Op_commutative(MPI_Op op, int *commute){
4843 AMPIAPI("AMPI_Op_commutative");
4844 *commute = (int)getAmpiParent()->opIsCommutative(op);
4849 double AMPI_Wtime(void)
4851 //AMPIAPI("AMPI_Wtime");
4854 double ret=TCHARM_Wall_timer();
4855 ampiParent* pptr = getAmpiParent();
4857 (*(pptr->fromPUPer))|ret;
4861 if(msgLogWrite && record_msglog(pptr->thisIndex)){
4862 (*(pptr->toPUPer))|ret;
4866 #if CMK_BIGSIM_CHARM
4869 return TCHARM_Wall_timer();
4874 double AMPI_Wtick(void){
4875 //AMPIAPI("AMPI_Wtick");
4880 int AMPI_Start(MPI_Request *request)
4882 AMPIAPI("AMPI_Start");
4883 checkRequest(*request);
4884 AmpiRequestList *reqs = getReqs();
4885 #if AMPI_ERROR_CHECKING
4886 if (!(*reqs)[*request]->isPersistent())
4887 return ampiErrhandler("AMPI_Start", MPI_ERR_REQUEST);
4889 (*reqs)[*request]->start(*request);
4894 int AMPI_Startall(int count, MPI_Request *requests){
4895 AMPIAPI("AMPI_Startall");
4896 checkRequests(count,requests);
4897 AmpiRequestList *reqs = getReqs();
4898 for(int i=0;i<count;i++){
4899 #if AMPI_ERROR_CHECKING
4900 if (!(*reqs)[requests[i]]->isPersistent())
4901 return ampiErrhandler("MPI_Startall", MPI_ERR_REQUEST);
4903 (*reqs)[requests[i]]->start(requests[i]);
4908 void IReq::start(MPI_Request reqIdx){
4909 CkAssert(persistent);
4911 ampi* ptr = getAmpiInstance(comm);
4912 AmpiMsg *msg = NULL;
4913 msg = ptr->getMessage(tag, src, comm, &tag);
4914 if (msg) { // if msg has already arrived, do the receive right away
4917 else { // ... otherwise post the receive
4918 int tags[2] = { tag, src };
4919 AmmPut(ptr->posted_ireqs, tags, (void *)(CmiIntPtr)(reqIdx+1));
4923 void SendReq::start(MPI_Request reqIdx){
4924 CkAssert(persistent);
4926 ampi* ptr = getAmpiInstance(comm);
4927 ptr->send(tag, ptr->getRank(), buf, count, type, src /*really, the destination*/, comm);
4931 void SsendReq::start(MPI_Request reqIdx){
4932 CkAssert(persistent);
4934 ampi* ptr = getAmpiInstance(comm);
4935 ptr->send(tag, ptr->getRank(), buf, count, type, src /*really, the destination*/, comm, reqIdx+2, I_SEND);
4938 int IReq::wait(MPI_Status *sts){
4939 // ampi::generic() writes directly to the buffer, so the only thing we do here is wait
4940 ampiParent *parent = getAmpiParent();
4942 while (!statusIreq) {
4943 // parent is updated in case an ampi thread is migrated while waiting for a message
4944 parent->resumeOnRecv = true;
4945 parent->numBlockedReqs = 1;
4949 parent = getAmpiParent();
4952 if (sts != MPI_STATUS_IGNORE) sts->MPI_CANCEL = 1;
4954 parent->resumeOnRecv = false;
4958 #if CMK_BIGSIM_CHARM
4959 //Because of the out-of-core emulation, this pointer is changed after in-out
4960 //memory operation. So we need to return from this function and do the while loop
4961 //in the outer function call.
4962 if(_BgInOutOfCoreMode)
4966 parent->resumeOnRecv = false;
4968 AMPI_DEBUG("IReq::wait has resumed\n");
4970 if(sts!=MPI_STATUS_IGNORE) {
4971 AMPI_DEBUG("Setting sts->MPI_TAG to this->tag=%d in IReq::wait this=%p\n", (int)this->tag, this);
4973 sts->MPI_SOURCE = src;
4974 sts->MPI_COMM = comm;
4975 sts->MPI_LENGTH = length;
4976 sts->MPI_CANCEL = 0;
4982 int RednReq::wait(MPI_Status *sts){
4983 // ampi::irednResult() writes directly to the buffer, so the only thing we do here is wait
4984 ampiParent *parent = getAmpiParent();
4986 while (!statusIreq) {
4987 parent->resumeOnColl = true;
4988 parent->numBlockedReqs = 1;
4992 parent = getAmpiParent();
4994 #if CMK_BIGSIM_CHARM
4995 //Because of the out-of-core emulation, this pointer is changed after in-out
4996 //memory operation. So we need to return from this function and do the while loop
4997 //in the outer function call.
4998 if (_BgInOutOfCoreMode)
5002 parent->resumeOnColl = false;
5004 AMPI_DEBUG("RednReq::wait has resumed\n");
5006 if (sts != MPI_STATUS_IGNORE) {
5008 sts->MPI_SOURCE = src;
5009 sts->MPI_COMM = comm;
5010 sts->MPI_CANCEL = 0;
5015 int GatherReq::wait(MPI_Status *sts){
5016 // ampi::irednResult() writes directly to the buffer, so the only thing we do here is wait
5017 ampiParent *parent = getAmpiParent();
5019 while (!statusIreq) {
5020 parent->resumeOnColl = true;
5021 parent->numBlockedReqs = 1;
5025 parent = getAmpiParent();
5027 #if CMK_BIGSIM_CHARM
5028 //Because of the out-of-core emulation, this pointer is changed after in-out
5029 //memory operation. So we need to return from this function and do the while loop
5030 //in the outer function call.
5031 if (_BgInOutOfCoreMode)
5035 parent->resumeOnColl = false;
5037 AMPI_DEBUG("GatherReq::wait has resumed\n");
5039 if (sts != MPI_STATUS_IGNORE) {
5041 sts->MPI_SOURCE = src;
5042 sts->MPI_COMM = comm;
5043 sts->MPI_CANCEL = 0;
5048 int GathervReq::wait(MPI_Status *sts){
5049 // ampi::irednResult writes directly to the buffer, so the only thing we do here is wait
5050 ampiParent *parent = getAmpiParent();
5052 while (!statusIreq) {
5053 parent->resumeOnColl = true;
5054 parent->numBlockedReqs = 1;
5058 parent = getAmpiParent();
5060 #if CMK_BIGSIM_CHARM
5061 //Because of the out-of-core emulation, this pointer is changed after in-out
5062 //memory operation. So we need to return from this function and do the while loop
5063 //in the outer function call.
5064 if (_BgInOutOfCoreMode)
5068 parent->resumeOnColl = false;
5070 AMPI_DEBUG("GathervReq::wait has resumed\n");
5072 if (sts != MPI_STATUS_IGNORE) {
5074 sts->MPI_SOURCE = src;
5075 sts->MPI_COMM = comm;
5076 sts->MPI_CANCEL = 0;
5081 int SendReq::wait(MPI_Status *sts){
5082 ampiParent *parent = getAmpiParent();
5083 while (!statusIreq) {
5084 parent->resumeOnRecv = true;
5085 parent->numBlockedReqs = 1;
5089 // "dis" is updated in case an ampi thread is migrated while waiting for a message
5090 parent = getAmpiParent();
5092 parent->resumeOnRecv = false;
5093 AMPI_DEBUG("SendReq::wait has resumed\n");
5094 if (sts != MPI_STATUS_IGNORE) {
5095 sts->MPI_COMM = comm;
5096 sts->MPI_CANCEL = 0;
5101 int SsendReq::wait(MPI_Status *sts){
5102 ampiParent *parent = getAmpiParent();
5103 while (!statusIreq) {
5104 // "dis" is updated in case an ampi thread is migrated while waiting for a message
5105 parent = parent->blockOnRecv();
5107 if (sts != MPI_STATUS_IGNORE) {
5108 sts->MPI_COMM = comm;
5109 sts->MPI_CANCEL = 0;
5114 int IATAReq::wait(MPI_Status *sts){
5116 for(i=0;i<elmcount;i++){
5117 if(-1==getAmpiInstance(myreqs[i].comm)->recv(myreqs[i].tag, myreqs[i].src, myreqs[i].buf,
5118 myreqs[i].count, myreqs[i].type,
5119 myreqs[i].comm, sts))
5120 CkAbort("AMPI> Error in ialltoall request wait");
5121 #if CMK_BIGSIM_CHARM
5122 _TRACE_BG_TLINE_END(&myreqs[i].event);
5125 #if CMK_BIGSIM_CHARM
5126 TRACE_BG_AMPI_BREAK(getAmpiInstance(MPI_COMM_WORLD)->getThread(), "IATAReq_wait", NULL, 0, 1);
5127 for (i=0; i<elmcount; i++)
5128 _TRACE_BG_ADD_BACKWARD_DEP(myreqs[i].event);
5129 _TRACE_BG_TLINE_END(&event);
5135 int AMPI_Wait(MPI_Request *request, MPI_Status *sts)
5137 AMPIAPI("AMPI_Wait");
5139 if(*request == MPI_REQUEST_NULL){
5143 checkRequest(*request);
5144 AmpiRequestList* reqs = getReqs();
5147 ampiParent* pptr = getAmpiParent();
5149 (*(pptr->fromPUPer))|(pptr->pupBytes);
5150 PUParray(*(pptr->fromPUPer), (char *)((*reqs)[*request]->buf), (pptr->pupBytes));
5151 PUParray(*(pptr->fromPUPer), (char *)sts, sizeof(MPI_Status));
5156 #if CMK_BIGSIM_CHARM
5157 void *curLog; // store current log in timeline
5158 _TRACE_BG_TLINE_END(&curLog);
5161 AMPI_DEBUG("AMPI_Wait request=%d (*reqs)[*request]=%p (*reqs)[*request]->tag=%d\n",
5162 *request, (*reqs)[*request], (int)((*reqs)[*request]->tag));
5163 AMPI_DEBUG("MPI_Wait: request=%d, reqs.size=%d, &reqs=%d\n",
5164 *request, reqs->size(), reqs);
5165 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5166 int waitResult = -1;
5168 AmpiRequest& waitReq = *(*reqs)[*request];
5169 waitResult = waitReq.wait(sts);
5170 #if CMK_BIGSIM_CHARM
5171 if(_BgInOutOfCoreMode){
5175 }while(waitResult==-1);
5177 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5178 AMPI_DEBUG("AMPI_Wait after calling wait, request=%d (*reqs)[*request]=%p (*reqs)[*request]->tag=%d\n",
5179 *request, (*reqs)[*request], (int)((*reqs)[*request]->tag));
5182 if(msgLogWrite && record_msglog(pptr->thisIndex)){
5183 (pptr->pupBytes) = getDDT()->getSize((*reqs)[*request]->type) * ((*reqs)[*request]->count);
5184 (*(pptr->toPUPer))|(pptr->pupBytes);
5185 PUParray(*(pptr->toPUPer), (char *)((*reqs)[*request]->buf), (pptr->pupBytes));
5186 PUParray(*(pptr->toPUPer), (char *)sts, sizeof(MPI_Status));
5190 #if CMK_BIGSIM_CHARM
5191 TRACE_BG_AMPI_WAIT(reqs); // setup forward and backward dependence
5194 freeNonPersReq(*request);
5196 AMPI_DEBUG("End of AMPI_Wait\n");
5202 int AMPI_Waitall(int count, MPI_Request request[], MPI_Status sts[])
5204 AMPIAPI("AMPI_Waitall");
5206 checkRequests(count, request);
5207 if (count == 0) return MPI_SUCCESS;
5209 AmpiRequestList* reqs = getReqs();
5210 ampiParent* pptr = getAmpiParent();
5211 CkAssert(pptr->numBlockedReqs == 0);
5215 for(int i=0;i<count;i++){
5216 if(request[i] == MPI_REQUEST_NULL){
5217 clearStatus(sts, i);
5220 AmpiRequest *waitReq = (*reqs)[request[i]];
5221 (*(pptr->fromPUPer))|(pptr->pupBytes);
5222 PUParray(*(pptr->fromPUPer), (char *)(waitReq->buf), pptr->pupBytes);
5223 PUParray(*(pptr->fromPUPer), (char *)(&sts[i]), sizeof(MPI_Status));
5228 #if CMK_BIGSIM_CHARM
5229 void *curLog; // store current log in timeline
5230 _TRACE_BG_TLINE_END(&curLog);
5233 // First check for any incomplete requests
5234 for (int i=0; i<count; i++) {
5235 if (request[i] == MPI_REQUEST_NULL) {
5236 clearStatus(sts, i);
5239 AmpiRequest& req = *(*reqs)[request[i]];
5241 req.wait((sts == MPI_STATUSES_IGNORE) ? MPI_STATUS_IGNORE : &sts[i]);
5242 req.setBlocked(false);
5244 if(msgLogWrite && record_msglog(pptr->thisIndex)){
5245 (pptr->pupBytes) = getDDT()->getSize(req.type) * req.count;
5246 (*(pptr->toPUPer))|(pptr->pupBytes);
5247 PUParray(*(pptr->toPUPer), (char *)(req.buf), pptr->pupBytes);
5248 PUParray(*(pptr->toPUPer), (char *)(&sts[i]), sizeof(MPI_Status));
5251 freeNonPersReq(request[i]);
5254 req.setBlocked(true);
5255 pptr->numBlockedReqs++;
5259 // If any requests are incomplete, block until all have been completed
5260 if (pptr->numBlockedReqs > 0) {
5261 getAmpiParent()->blockOnRecv();
5262 reqs = getReqs(); //update pointer in case of migration while suspended
5263 pptr = getAmpiParent();
5265 for (int i=0; i<count; i++) {
5266 if (request[i] == MPI_REQUEST_NULL) {
5269 AmpiRequest& req = *(*reqs)[request[i]];
5270 #if CMK_ERROR_CHECKING
5272 CkAbort("In AMPI_Waitall, all requests should have completed by now!");
5274 req.wait((sts == MPI_STATUSES_IGNORE) ? MPI_STATUS_IGNORE : &sts[i]);
5275 req.setBlocked(false);
5277 if(msgLogWrite && record_msglog(pptr->thisIndex)){
5278 (pptr->pupBytes) = getDDT()->getSize(req.type) * req.count;
5279 (*(pptr->toPUPer))|(pptr->pupBytes);
5280 PUParray(*(pptr->toPUPer), (char *)(req.buf), pptr->pupBytes);
5281 PUParray(*(pptr->toPUPer), (char *)(&sts[i]), sizeof(MPI_Status));
5284 freeNonPersReq(request[i]);
5288 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5290 #if CMK_BIGSIM_CHARM
5291 TRACE_BG_AMPI_WAITALL(reqs); // setup forward and backward dependence
5298 int AMPI_Waitany(int count, MPI_Request *request, int *idx, MPI_Status *sts)
5300 AMPIAPI("AMPI_Waitany");
5302 checkRequests(count, request);
5304 *idx = MPI_UNDEFINED;
5308 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5310 AmpiRequestList* reqs = getReqs();
5313 // First check for an already complete request
5314 for (int i=0; i<count; i++) {
5315 if (request[i] == MPI_REQUEST_NULL) {
5319 AmpiRequest& req = *(*reqs)[request[i]];
5322 reqs->unblockReqs(&request[0], i);
5323 freeNonPersReq(request[i]);
5325 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5329 req.setBlocked(true);
5332 if (nullReqs == count) {
5334 *idx = MPI_UNDEFINED;
5335 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5339 // block until one of the requests is completed
5340 getAmpiParent()->numBlockedReqs = 1;
5341 getAmpiParent()->blockOnRecv();
5342 reqs = getReqs(); // update pointer in case of migration while suspended
5344 for (int i=0; i<count; i++) {
5345 if (request[i] == MPI_REQUEST_NULL) {
5348 AmpiRequest& req = *(*reqs)[request[i]];
5351 reqs->unblockReqs(&request[i], count-i);
5352 freeNonPersReq(request[i]);
5354 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5358 req.setBlocked(false);
5360 #if CMK_ERROR_CHECKING
5361 CkAbort("In AMPI_Waitany, a request should have completed by now!");
5368 int AMPI_Waitsome(int incount, MPI_Request *array_of_requests, int *outcount,
5369 int *array_of_indices, MPI_Status *array_of_statuses)
5371 AMPIAPI("AMPI_Waitsome");
5373 checkRequests(incount, array_of_requests);
5375 *outcount = MPI_UNDEFINED;
5379 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5381 AmpiRequestList* reqs = getReqs();
5386 for (int i=0; i<incount; i++) {
5387 if (array_of_requests[i] == MPI_REQUEST_NULL) {
5388 clearStatus(array_of_statuses, i);
5392 AmpiRequest& req = *(*reqs)[array_of_requests[i]];
5395 array_of_indices[(*outcount)] = i;
5397 if (array_of_statuses != MPI_STATUSES_IGNORE)
5398 array_of_statuses[(*outcount)] = sts;
5399 freeNonPersReq(array_of_requests[i]);
5402 req.setBlocked(true);
5406 if (*outcount > 0) {
5407 reqs->unblockReqs(&array_of_requests[0], incount);
5408 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5411 else if (nullReqs == incount) {
5412 *outcount = MPI_UNDEFINED;
5413 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5416 else { // block until one of the requests is completed
5417 getAmpiParent()->numBlockedReqs = 1;
5418 getAmpiParent()->blockOnRecv();
5419 reqs = getReqs(); // update pointer in case of migration while suspended
5421 for (int i=0; i<incount; i++) {
5422 if (array_of_requests[i] == MPI_REQUEST_NULL) {
5425 AmpiRequest& req = *(*reqs)[array_of_requests[i]];
5428 array_of_indices[(*outcount)] = i;
5430 if (array_of_statuses != MPI_STATUSES_IGNORE)
5431 array_of_statuses[(*outcount)] = sts;
5432 reqs->unblockReqs(&array_of_requests[i], incount-i);
5433 freeNonPersReq(array_of_requests[i]);
5434 CkAssert(getAmpiParent()->numBlockedReqs == 0);
5438 req.setBlocked(false);
5441 #if CMK_ERROR_CHECKING
5442 CkAbort("In AMPI_Waitsome, a request should have completed by now!");
5448 bool IReq::test(MPI_Status *sts/*=MPI_STATUS_IGNORE*/) {
5449 if (sts != MPI_STATUS_IGNORE) {
5451 sts->MPI_CANCEL = 1;
5454 else if (statusIreq) {
5455 sts->MPI_SOURCE = src;
5457 sts->MPI_COMM = comm;
5458 sts->MPI_LENGTH = length;
5459 sts->MPI_CANCEL = 0;
5462 else if (cancelled) {
5468 bool RednReq::test(MPI_Status *sts/*=MPI_STATUS_IGNORE*/) {
5472 bool GatherReq::test(MPI_Status *sts/*=MPI_STATUS_IGNORE*/) {
5476 bool GathervReq::test(MPI_Status *sts/*=MPI_STATUS_IGNORE*/) {
5480 bool SendReq::test(MPI_Status *sts/*=MPI_STATUS_IGNORE*/) {
5484 bool SsendReq::test(MPI_Status *sts/*=MPI_STATUS_IGNORE*/) {
5488 bool IATAReq::test(MPI_Status *sts/*=MPI_STATUS_IGNORE*/){
5489 for(int i=0;i<elmcount;i++){
5490 if(!myreqs[i].test(sts))
5496 void IReq::receive(ampi *ptr, AmpiMsg *msg)
5498 ptr->processAmpiMsg(msg, buf, type, count);
5500 length = msg->getLength();
5501 this->tag = msg->getTag(); // Although not required, we also extract tag from msg
5502 src = msg->getSrcRank(); // Although not required, we also extract src from msg
5503 comm = ptr->getComm();
5504 AMPI_DEBUG("Setting this->tag to %d in IReq::receive this=%p\n", tag, this);
5505 #if CMK_BIGSIM_CHARM
5507 eventPe = msg->eventPe;
5512 void IReq::receiveRdma(ampi *ptr, char *sbuf, int slength, int ssendReq, int srcRank, MPI_Comm scomm)
5514 ptr->processRdmaMsg(sbuf, slength, ssendReq, srcRank, buf, count, type, scomm);
5518 // ampi::genericRdma is parameter marshalled, so there is no msg to delete
5521 void RednReq::receive(ampi *ptr, CkReductionMsg *msg)
5523 if (ptr->opIsCommutative(op) && ptr->getDDT()->isContig(type)) {
5524 ptr->processRednMsg(msg, buf, type, count);
5526 MPI_User_function* func = ptr->op2User_function(op);
5527 ptr->processNoncommutativeRednMsg(msg, buf, type, count, func);
5530 comm = ptr->getComm();
5531 #if CMK_BIGSIM_CHARM
5533 eventPe = msg->eventPe;
5535 // ampi::rednResult is a [nokeep] entry method, so do not delete msg
5538 void GatherReq::receive(ampi *ptr, CkReductionMsg *msg)
5540 ptr->processGatherMsg(msg, buf, type, count);
5542 comm = ptr->getComm();
5543 #if CMK_BIGSIM_CHARM
5545 eventPe = msg->eventPe;
5547 // ampi::rednResult is a [nokeep] entry method, so do not delete msg
5550 void GathervReq::receive(ampi *ptr, CkReductionMsg *msg)
5552 ptr->processGathervMsg(msg, buf, type, &recvCounts[0], &displs[0]);
5554 comm = ptr->getComm();
5555 #if CMK_BIGSIM_CHARM
5557 eventPe = msg->eventPe;
5559 // ampi::rednResult is a [nokeep] entry method, so do not delete msg
5563 int AMPI_Request_get_status(MPI_Request request, int *flag, MPI_Status *sts)
5565 AMPIAPI("AMPI_Request_get_status");
5566 testRequestNoFree(&request, flag, sts);
5568 getAmpiParent()->yield();
5573 int AMPI_Test(MPI_Request *request, int *flag, MPI_Status *sts)
5575 AMPIAPI("AMPI_Test");
5576 testRequest(request, flag, sts);
5578 getAmpiParent()->yield();
5583 int AMPI_Testany(int count, MPI_Request *request, int *index, int *flag, MPI_Status *sts){
5584 AMPIAPI("AMPI_Testany");
5586 checkRequests(count, request);
5590 *index = MPI_UNDEFINED;
5598 for (int i=0; i<count; i++) {
5599 if (request[i] == MPI_REQUEST_NULL) {
5603 testRequest(&request[i], flag, sts);
5610 *index = MPI_UNDEFINED;
5611 if (nullReqs == count) {
5616 getAmpiParent()->yield();
5623 int AMPI_Testall(int count, MPI_Request *request, int *flag, MPI_Status *sts)
5625 AMPIAPI("AMPI_Testall");
5627 checkRequests(count, request);
5633 AmpiRequestList* reqs = getReqs();
5637 for (int i=0; i<count; i++) {
5638 if (request[i] == MPI_REQUEST_NULL) {
5639 clearStatus(sts, i);
5643 if (!(*reqs)[request[i]]->test()) {
5645 getAmpiParent()->yield();
5650 if (nullReqs != count) {
5651 for (int i=0; i<count; i++) {
5652 int reqIdx = request[i];
5653 if (reqIdx != MPI_REQUEST_NULL) {
5654 AmpiRequest& req = *(*reqs)[reqIdx];
5655 req.wait((sts == MPI_STATUSES_IGNORE) ? MPI_STATUS_IGNORE : &sts[i]);
5656 freeNonPersReq(request[i]);
5665 int AMPI_Testsome(int incount, MPI_Request *array_of_requests, int *outcount,
5666 int *array_of_indices, MPI_Status *array_of_statuses)
5668 AMPIAPI("AMPI_Testsome");
5670 checkRequests(incount, array_of_requests);
5672 *outcount = MPI_UNDEFINED;
5677 int flag = 0, nullReqs = 0;
5680 for (int i=0; i<incount; i++) {
5681 if (array_of_requests[i] == MPI_REQUEST_NULL) {
5682 clearStatus(array_of_statuses, i);
5686 testRequest(&array_of_requests[i], &flag, &sts);
5688 array_of_indices[(*outcount)] = i;
5690 if (array_of_statuses != MPI_STATUSES_IGNORE)
5691 array_of_statuses[(*outcount)] = sts;
5695 if (nullReqs == incount) {
5696 *outcount = MPI_UNDEFINED;
5698 else if (*outcount == 0) {
5699 getAmpiParent()->yield();
5706 int AMPI_Request_free(MPI_Request *request){
5707 AMPIAPI("AMPI_Request_free");
5708 if(*request==MPI_REQUEST_NULL) return MPI_SUCCESS;
5709 checkRequest(*request);
5710 AmpiRequestList* reqs = getReqs();
5711 reqs->free(*request);
5712 *request = MPI_REQUEST_NULL;
5717 int AMPI_Cancel(MPI_Request *request){
5718 AMPIAPI("AMPI_Cancel");
5719 if(*request == MPI_REQUEST_NULL) return MPI_SUCCESS;
5720 checkRequest(*request);
5721 AmpiRequestList* reqs = getReqs();
5722 AmpiRequest& req = *(*reqs)[*request];
5723 if(req.getType() == MPI_I_REQ) {
5728 return ampiErrhandler("AMPI_Cancel", MPI_ERR_REQUEST);
5733 int AMPI_Test_cancelled(const MPI_Status* status, int* flag) {
5734 AMPIAPI("AMPI_Test_cancelled");
5735 // NOTE : current implementation requires AMPI_{Wait,Test}{any,some,all}
5736 // to be invoked before AMPI_Test_cancelled
5737 *flag = status->MPI_CANCEL;
5742 int AMPI_Status_set_cancelled(MPI_Status *status, int flag){
5743 AMPIAPI("AMPI_Status_set_cancelled");
5744 status->MPI_CANCEL = flag;
5749 int AMPI_Recv_init(void *buf, int count, MPI_Datatype type, int src, int tag,
5750 MPI_Comm comm, MPI_Request *req)
5752 AMPIAPI("AMPI_Recv_init");
5754 handle_MPI_BOTTOM(buf, type);
5756 #if AMPI_ERROR_CHECKING
5757 int ret = errorCheck("AMPI_Recv_init", comm, 1, count, 1, type, 1, tag, 1, src, 1, buf, 1);
5758 if(ret != MPI_SUCCESS){
5759 *req = MPI_REQUEST_NULL;
5764 IReq* ireq = new IReq(buf,count,type,src,tag,comm);
5765 ireq->setPersistent(true);
5766 *req = getAmpiInstance(comm)->postReq(ireq);
5771 int AMPI_Send_init(const void *buf, int count, MPI_Datatype type, int dest, int tag,
5772 MPI_Comm comm, MPI_Request *req)
5774 AMPIAPI("AMPI_Send_init");
5776 handle_MPI_BOTTOM((void*&)buf, type);
5778 #if AMPI_ERROR_CHECKING
5779 int ret = errorCheck("AMPI_Send_init", comm, 1, count, 1, type, 1, tag, 1, dest, 1, buf, 1);
5780 if(ret != MPI_SUCCESS){
5781 *req = MPI_REQUEST_NULL;
5786 SendReq* sreq = new SendReq(const_cast<void*>(buf),count,type,dest,tag,comm);
5787 sreq->setPersistent(true);
5788 *req = getAmpiInstance(comm)->postReq(sreq);
5793 int AMPI_Ssend_init(const void *buf, int count, MPI_Datatype type, int dest, int tag,
5794 MPI_Comm comm, MPI_Request *req)
5796 AMPIAPI("AMPI_Ssend_init");
5798 handle_MPI_BOTTOM((void*&)buf, type);
5800 #if AMPI_ERROR_CHECKING
5801 int ret = errorCheck("AMPI_Ssend_init", comm, 1, count, 1, type, 1, tag, 1, dest, 1, buf, 1);
5802 if(ret != MPI_SUCCESS){
5803 *req = MPI_REQUEST_NULL;
5808 SsendReq* sreq = new SsendReq(const_cast<void*>(buf),count,type,dest,tag,comm);
5809 sreq->setPersistent(true);
5810 *req = getAmpiInstance(comm)->postReq(sreq);
5815 int AMPI_Type_contiguous(int count, MPI_Datatype oldtype,
5816 MPI_Datatype *newtype)
5818 AMPIAPI("AMPI_Type_contiguous");
5819 getDDT()->newContiguous(count, oldtype, newtype);
5824 int AMPI_Type_vector(int count, int blocklength, int stride,
5825 MPI_Datatype oldtype, MPI_Datatype* newtype)
5827 AMPIAPI("AMPI_Type_vector");
5828 getDDT()->newVector(count, blocklength, stride, oldtype, newtype);
5833 int AMPI_Type_create_hvector(int count, int blocklength, MPI_Aint stride,
5834 MPI_Datatype oldtype, MPI_Datatype* newtype)
5836 AMPIAPI("AMPI_Type_create_hvector");
5837 getDDT()->newHVector(count, blocklength, stride, oldtype, newtype);
5842 int AMPI_Type_hvector(int count, int blocklength, MPI_Aint stride,
5843 MPI_Datatype oldtype, MPI_Datatype* newtype)
5845 AMPIAPI("AMPI_Type_hvector");
5846 return AMPI_Type_create_hvector(count, blocklength, stride, oldtype, newtype);
5850 int AMPI_Type_indexed(int count, const int* arrBlength, const int* arrDisp,
5851 MPI_Datatype oldtype, MPI_Datatype* newtype)
5853 AMPIAPI("AMPI_Type_indexed");
5854 /*CkDDT_Indexed's arrDisp has type MPI_Aint* (not int*). */
5855 vector<MPI_Aint> arrDispAint(count);
5856 for(int i=0; i<count; i++)
5857 arrDispAint[i] = (MPI_Aint)(arrDisp[i]);
5858 getDDT()->newIndexed(count, arrBlength, &arrDispAint[0], oldtype, newtype);
5863 int AMPI_Type_create_hindexed(int count, const int* arrBlength, const MPI_Aint* arrDisp,
5864 MPI_Datatype oldtype, MPI_Datatype* newtype)
5866 AMPIAPI("AMPI_Type_create_hindexed");
5867 getDDT()->newHIndexed(count, arrBlength, arrDisp, oldtype, newtype);
5872 int AMPI_Type_hindexed(int count, int* arrBlength, MPI_Aint* arrDisp,
5873 MPI_Datatype oldtype, MPI_Datatype* newtype)
5875 AMPIAPI("AMPI_Type_hindexed");
5876 return AMPI_Type_create_hindexed(count, arrBlength, arrDisp, oldtype, newtype);
5880 int AMPI_Type_create_indexed_block(int count, int Blength, const MPI_Aint *arr,
5881 MPI_Datatype oldtype, MPI_Datatype *newtype)
5883 AMPIAPI("AMPI_Type_create_indexed_block");
5884 getDDT()->newIndexedBlock(count,Blength, arr, oldtype, newtype);
5889 int AMPI_Type_create_hindexed_block(int count, int Blength, const MPI_Aint *arr,
5890 MPI_Datatype oldtype, MPI_Datatype *newtype)
5892 AMPIAPI("AMPI_Type_create_hindexed_block");
5893 getDDT()->newHIndexedBlock(count,Blength, arr, oldtype, newtype);
5898 int AMPI_Type_create_struct(int count, const int* arrBlength, const MPI_Aint* arrDisp,
5899 const MPI_Datatype* oldtype, MPI_Datatype* newtype)
5901 AMPIAPI("AMPI_Type_create_struct");
5902 getDDT()->newStruct(count, arrBlength, arrDisp, oldtype, newtype);
5907 int AMPI_Type_struct(int count, int* arrBlength, MPI_Aint* arrDisp,
5908 MPI_Datatype* oldtype, MPI_Datatype* newtype)
5910 AMPIAPI("AMPI_Type_struct");
5911 return AMPI_Type_create_struct(count, arrBlength, arrDisp, oldtype, newtype);
5915 int AMPI_Type_commit(MPI_Datatype *datatype)
5917 AMPIAPI("AMPI_Type_commit");
5922 int AMPI_Type_free(MPI_Datatype *datatype)
5924 AMPIAPI("AMPI_Type_free");
5925 getDDT()->freeType(datatype);
5930 int AMPI_Type_get_extent(MPI_Datatype datatype, MPI_Aint *lb, MPI_Aint *extent)
5932 AMPIAPI("AMPI_Type_get_extent");
5933 *lb = getDDT()->getLB(datatype);
5934 *extent = getDDT()->getExtent(datatype);
5939 int AMPI_Type_extent(MPI_Datatype datatype, MPI_Aint *extent)
5941 AMPIAPI("AMPI_Type_extent");
5943 return AMPI_Type_get_extent(datatype, &tmpLB, extent);
5947 int AMPI_Type_get_true_extent(MPI_Datatype datatype, MPI_Aint *true_lb, MPI_Aint *true_extent)
5949 AMPIAPI("AMPI_Type_get_true_extent");
5950 *true_lb = getDDT()->getTrueLB(datatype);
5951 *true_extent = getDDT()->getTrueExtent(datatype);
5956 int AMPI_Type_size(MPI_Datatype datatype, int *size)
5958 AMPIAPI("AMPI_Type_size");
5959 *size=getDDT()->getSize(datatype);
5964 int AMPI_Type_set_name(MPI_Datatype datatype, const char *name)
5966 AMPIAPI("AMPI_Type_set_name");
5967 getDDT()->setName(datatype, name);
5972 int AMPI_Type_get_name(MPI_Datatype datatype, char *name, int *resultlen)
5974 AMPIAPI("AMPI_Type_get_name");
5975 getDDT()->getName(datatype, name, resultlen);
5980 int AMPI_Type_create_resized(MPI_Datatype oldtype, MPI_Aint lb, MPI_Aint extent, MPI_Datatype *newtype)
5982 AMPIAPI("AMPI_Type_create_resized");
5983 getDDT()->createResized(oldtype, lb, extent, newtype);
5988 int AMPI_Type_dup(MPI_Datatype oldtype, MPI_Datatype *newtype)
5990 AMPIAPI("AMPI_Type_dup");
5991 getDDT()->createDup(oldtype, newtype);
5995 int AMPI_Type_set_attr(MPI_Datatype datatype, int type_keyval, void *attribute_val)
5997 AMPIAPI("AMPI_Type_set_attr");
5998 /* no-op implementation */
6003 int AMPI_Type_get_attr(MPI_Datatype datatype, int type_keyval, void *attribute_val, int *flag)
6005 AMPIAPI("AMPI_Type_get_attr");
6006 /* no-op implementation */
6011 int AMPI_Type_delete_attr(MPI_Datatype datatype, int type_keyval)
6013 AMPIAPI("AMPI_Type_delete_attr");
6014 /* no-op implementation */
6019 int AMPI_Type_create_keyval(MPI_Type_copy_attr_function *type_copy_attr_fn,
6020 MPI_Type_delete_attr_function *type_delete_attr_fn,
6021 int *type_keyval, void *extra_state)
6023 AMPIAPI("AMPI_Type_create_keyval");
6024 /* no-op implementation */
6029 int AMPI_Type_free_keyval(int *type_keyval)
6031 AMPIAPI("AMPI_Type_free_keyval");
6032 /* no-op implementation */
6037 int AMPI_Isend(const void *buf, int count, MPI_Datatype type, int dest,
6038 int tag, MPI_Comm comm, MPI_Request *request)
6040 AMPIAPI("AMPI_Isend");
6042 handle_MPI_BOTTOM((void*&)buf, type);
6044 #if AMPI_ERROR_CHECKING
6045 int ret = errorCheck("AMPI_Isend", comm, 1, count, 1, type, 1, tag, 1, dest, 1, buf, 1);
6046 if(ret != MPI_SUCCESS){
6047 *request = MPI_REQUEST_NULL;
6053 ampiParent* pptr = getAmpiParent();
6055 PUParray(*(pptr->fromPUPer), (char *)request, sizeof(MPI_Request));
6060 USER_CALL_DEBUG("AMPI_Isend("<<type<<","<<dest<<","<<tag<<","<<comm<<")");
6062 ampi *ptr = getAmpiInstance(comm);
6063 *request = ptr->send(tag, ptr->getRank(), buf, count, type, dest, comm, 0, I_SEND);
6066 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6067 PUParray(*(pptr->toPUPer), (char *)request, sizeof(MPI_Request));
6074 void ampi::irecv(void *buf, int count, MPI_Datatype type, int src,
6075 int tag, MPI_Comm comm, MPI_Request *request)
6077 if (src==MPI_PROC_NULL) {
6078 *request = MPI_REQUEST_NULL;
6083 src = myComm.getIndexForRemoteRank(src);
6086 AmpiRequestList* reqs = getReqs();
6087 IReq *newreq = new IReq(buf, count, type, src, tag, comm);
6088 *request = reqs->insert(newreq);
6091 ampiParent* pptr = getAmpiParent();
6093 PUParray(*(pptr->fromPUPer), (char *)request, sizeof(MPI_Request));
6098 AmpiMsg *msg = NULL;
6099 msg = getMessage(tag, src, comm, &newreq->tag);
6100 // if msg has already arrived, do the receive right away
6102 newreq->receive(this, msg);
6104 // ... otherwise post the receive
6106 int tags[2] = { tag, src };
6108 //just insert the index of the newreq in the ampiParent::ampiReqs
6109 //to posted_ireqs. Such change is due to the need for Out-of-core Emulation
6110 //in BigSim. Before this change, posted_ireqs and ampiReqs both hold pointers to
6111 //AmpiRequest instances. After going through the Pupping routines, both will have
6112 //pointers to different AmpiRequest instances and no longer refer to the same AmpiRequest
6113 //instance. Therefore, to keep both always accessing the same AmpiRequest instance,
6114 //posted_ireqs stores the index (an integer) to ampiReqs.
6115 //The index is 1-based rather 0-based because when pulling entries from posted_ireqs,
6116 //if not found, a "0" (i.e. NULL) is returned, this confuses the indexing of ampiReqs.
6117 AmmPut(posted_ireqs, tags, (void *)(CmiIntPtr)((*request)+1));
6121 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6122 PUParray(*(pptr->toPUPer), (char *)request, sizeof(MPI_Request));
6128 int AMPI_Irecv(void *buf, int count, MPI_Datatype type, int src,
6129 int tag, MPI_Comm comm, MPI_Request *request)
6131 AMPIAPI("AMPI_Irecv");
6133 handle_MPI_BOTTOM(buf, type);
6135 #if AMPI_ERROR_CHECKING
6136 int ret = errorCheck("AMPI_Irecv", comm, 1, count, 1, type, 1, tag, 1, src, 1, buf, 1);
6137 if(ret != MPI_SUCCESS){
6138 *request = MPI_REQUEST_NULL;
6143 USER_CALL_DEBUG("AMPI_Irecv("<<type<<","<<src<<","<<tag<<","<<comm<<")");
6144 ampi *ptr = getAmpiInstance(comm);
6146 ptr->irecv(buf, count, type, src, tag, comm, request);
6152 int AMPI_Ireduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype type, MPI_Op op,
6153 int root, MPI_Comm comm, MPI_Request *request)
6155 AMPIAPI("AMPI_Ireduce");
6157 handle_MPI_BOTTOM((void*&)sendbuf, type, recvbuf, type);
6158 handle_MPI_IN_PLACE((void*&)sendbuf, recvbuf);
6160 #if AMPI_ERROR_CHECKING
6161 if(op == MPI_OP_NULL)
6162 return ampiErrhandler("AMPI_Ireduce", MPI_ERR_OP);
6163 int ret = errorCheck("AMPI_Ireduce", comm, 1, count, 1, type, 1, 0, 0, root, 1, sendbuf, 1,
6164 recvbuf, getAmpiInstance(comm)->getRank() == root);
6165 if(ret != MPI_SUCCESS){
6166 *request = MPI_REQUEST_NULL;
6171 ampi *ptr = getAmpiInstance(comm);
6173 if(getAmpiParent()->isInter(comm))
6174 CkAbort("AMPI does not implement MPI_Ireduce for Inter-communicators!");
6175 if(ptr->getSize() == 1){
6176 *request = ptr->postReq(new RednReq(recvbuf, count, type, comm, op, AMPI_REQ_COMPLETED));
6177 return copyDatatype(type,count,type,count,sendbuf,recvbuf);
6180 CkReductionMsg *msg=makeRednMsg(ptr->getDDT()->getType(type),sendbuf,count,type,ptr->getRank(),op);
6181 int rootIdx=ptr->comm2CommStruct(comm).getIndexForRank(root);
6183 CkCallback reduceCB(CkIndex_ampi::irednResult(0),CkArrayIndex1D(rootIdx),ptr->getProxy());
6184 msg->setCallback(reduceCB);
6185 ptr->contribute(msg);
6187 if (ptr->thisIndex == rootIdx){
6188 // use a RednReq to non-block the caller and get a request ptr
6189 *request = ptr->postReq(new RednReq(recvbuf,count,type,comm,op));
6192 *request = ptr->postReq(new RednReq(recvbuf,count,type,comm,op,AMPI_REQ_COMPLETED));
6198 static CkReductionMsg *makeGatherMsg(const void *inbuf, int count, MPI_Datatype type, int rank)
6200 CkDDT_DataType* ddt = getDDT()->getType(type);
6201 int szdata = ddt->getSize(count);
6202 const int tupleSize = 2;
6203 CkReduction::tupleElement tupleRedn[tupleSize];
6204 tupleRedn[0] = CkReduction::tupleElement(sizeof(int), &rank, CkReduction::set);
6206 if (ddt->isContig()) {
6207 tupleRedn[1] = CkReduction::tupleElement(szdata, (void*)inbuf, CkReduction::set);
6209 vector<char> sbuf(szdata);
6210 ddt->serialize((char*)inbuf, &sbuf[0], count, 1);
6211 tupleRedn[1] = CkReduction::tupleElement(szdata, &sbuf[0], CkReduction::set);
6214 return CkReductionMsg::buildFromTuple(tupleRedn, tupleSize);
6218 int AMPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6219 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6222 AMPIAPI("AMPI_Allgather");
6224 ampi *ptr = getAmpiInstance(comm);
6225 int rank = ptr->getRank();
6227 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6228 handle_MPI_IN_PLACE_gather((void*&)sendbuf, recvbuf, sendcount, sendtype,
6229 rank*recvcount, recvcount, recvtype);
6231 #if AMPI_ERROR_CHECKING
6233 if (sendbuf != recvbuf) {
6234 ret = errorCheck("AMPI_Allgather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6235 if(ret != MPI_SUCCESS)
6238 ret = errorCheck("AMPI_Allgather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6239 if(ret != MPI_SUCCESS)
6243 if(getAmpiParent()->isInter(comm))
6244 CkAbort("AMPI does not implement MPI_Allgather for Inter-communicators!");
6245 if(ptr->getSize() == 1)
6246 return copyDatatype(sendtype,sendcount,recvtype,recvcount,sendbuf,recvbuf);
6248 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6249 CkCallback allgatherCB(CkIndex_ampi::rednResult(0), ptr->getProxy());
6250 msg->setCallback(allgatherCB);
6251 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Allgather called on comm %d\n", ptr->thisIndex, comm));
6252 ptr->contribute(msg);
6254 ptr->blockOnRedn(new GatherReq(recvbuf, recvcount, recvtype, comm));
6260 int AMPI_Iallgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6261 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6262 MPI_Comm comm, MPI_Request* request)
6264 AMPIAPI("AMPI_Iallgather");
6266 ampi *ptr = getAmpiInstance(comm);
6267 int rank = ptr->getRank();
6269 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6270 handle_MPI_IN_PLACE_gather((void*&)sendbuf, recvbuf, sendcount, sendtype,
6271 rank*recvcount, recvcount, recvtype);
6273 #if AMPI_ERROR_CHECKING
6275 if (sendbuf != recvbuf) {
6276 ret = errorCheck("AMPI_Iallgather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6277 if(ret != MPI_SUCCESS){
6278 *request = MPI_REQUEST_NULL;
6282 ret = errorCheck("AMPI_Iallgather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6283 if(ret != MPI_SUCCESS){
6284 *request = MPI_REQUEST_NULL;
6289 if(getAmpiParent()->isInter(comm))
6290 CkAbort("AMPI does not implement MPI_Iallgather for Inter-communicators!");
6291 if(ptr->getSize() == 1){
6292 *request = ptr->postReq(new GatherReq(recvbuf, recvcount, recvtype, comm, AMPI_REQ_COMPLETED));
6293 return copyDatatype(sendtype,sendcount,recvtype,recvcount,sendbuf,recvbuf);
6296 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6297 CkCallback allgatherCB(CkIndex_ampi::irednResult(0), ptr->getProxy());
6298 msg->setCallback(allgatherCB);
6299 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Iallgather called on comm %d\n", ptr->thisIndex, comm));
6300 ptr->contribute(msg);
6302 // use a RednReq to non-block the caller and get a request ptr
6303 *request = ptr->postReq(new GatherReq(recvbuf, recvcount, recvtype, comm));
6309 int AMPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6310 void *recvbuf, const int *recvcounts, const int *displs,
6311 MPI_Datatype recvtype, MPI_Comm comm)
6313 AMPIAPI("AMPI_Allgatherv");
6315 ampi *ptr = getAmpiInstance(comm);
6316 int rank = ptr->getRank();
6318 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6319 handle_MPI_IN_PLACE_gather((void*&)sendbuf, recvbuf, sendcount, sendtype,
6320 displs[rank], recvcounts[rank], recvtype);
6322 #if AMPI_ERROR_CHECKING
6324 if (sendbuf != recvbuf) {
6325 ret = errorCheck("AMPI_Allgatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6326 if(ret != MPI_SUCCESS)
6329 ret = errorCheck("AMPI_Allgatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6330 if(ret != MPI_SUCCESS)
6334 if(getAmpiParent()->isInter(comm))
6335 CkAbort("AMPI does not implement MPI_Allgatherv for Inter-communicators!");
6336 if(ptr->getSize() == 1)
6337 return copyDatatype(sendtype,sendcount,recvtype,recvcounts[0],sendbuf,recvbuf);
6339 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6340 CkCallback allgathervCB(CkIndex_ampi::rednResult(0), ptr->getProxy());
6341 msg->setCallback(allgathervCB);
6342 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Allgatherv called on comm %d\n", ptr->thisIndex, comm));
6343 ptr->contribute(msg);
6345 ptr->blockOnRedn(new GathervReq(recvbuf, ptr->getSize(), recvtype, comm, recvcounts, displs));
6351 int AMPI_Iallgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6352 void *recvbuf, const int *recvcounts, const int *displs,
6353 MPI_Datatype recvtype, MPI_Comm comm, MPI_Request *request)
6355 AMPIAPI("AMPI_Iallgatherv");
6357 ampi *ptr = getAmpiInstance(comm);
6358 int rank = ptr->getRank();
6360 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6361 handle_MPI_IN_PLACE_gather((void*&)sendbuf, recvbuf, sendcount, sendtype,
6362 displs[rank], recvcounts[rank], recvtype);
6364 #if AMPI_ERROR_CHECKING
6366 if (sendbuf != recvbuf) {
6367 ret = errorCheck("AMPI_Iallgatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6368 if(ret != MPI_SUCCESS){
6369 *request = MPI_REQUEST_NULL;
6373 ret = errorCheck("AMPI_Iallgatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6374 if(ret != MPI_SUCCESS){
6375 *request = MPI_REQUEST_NULL;
6380 if(getAmpiParent()->isInter(comm))
6381 CkAbort("AMPI does not implement MPI_Iallgatherv for Inter-communicators!");
6382 if(ptr->getSize() == 1){
6383 *request = ptr->postReq(new GathervReq(recvbuf, rank, recvtype, comm, recvcounts, displs,
6384 AMPI_REQ_COMPLETED));
6385 return copyDatatype(sendtype,sendcount,recvtype,recvcounts[0],sendbuf,recvbuf);
6388 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6389 CkCallback allgathervCB(CkIndex_ampi::irednResult(0), ptr->getProxy());
6390 msg->setCallback(allgathervCB);
6391 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Iallgatherv called on comm %d\n", ptr->thisIndex, comm));
6392 ptr->contribute(msg);
6394 // use a GathervReq to non-block the caller and get a request ptr
6395 *request = ptr->postReq(new GathervReq(recvbuf, ptr->getSize(), recvtype,
6396 comm, recvcounts, displs));
6402 int AMPI_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6403 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6404 int root, MPI_Comm comm)
6406 AMPIAPI("AMPI_Gather");
6408 ampi *ptr = getAmpiInstance(comm);
6409 int rank = ptr->getRank();
6411 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6412 handle_MPI_IN_PLACE_gather((void*&)sendbuf, recvbuf, sendcount, sendtype,
6413 rank*recvcount, recvcount, recvtype);
6415 #if AMPI_ERROR_CHECKING
6417 if (sendbuf != recvbuf) {
6418 ret = errorCheck("AMPI_Gather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6419 if(ret != MPI_SUCCESS)
6422 if (getAmpiInstance(comm)->getRank() == root) {
6423 ret = errorCheck("AMPI_Gather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6424 if(ret != MPI_SUCCESS)
6429 if(getAmpiParent()->isInter(comm))
6430 CkAbort("AMPI does not implement MPI_Gather for Inter-communicators!");
6431 if(ptr->getSize() == 1)
6432 return copyDatatype(sendtype,sendcount,recvtype,recvcount,sendbuf,recvbuf);
6435 ampiParent* pptr = getAmpiParent();
6437 (*(pptr->fromPUPer))|(pptr->pupBytes);
6438 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6443 int rootIdx = ptr->comm2CommStruct(comm).getIndexForRank(root);
6444 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6445 CkCallback gatherCB(CkIndex_ampi::rednResult(0), CkArrayIndex1D(rootIdx), ptr->getProxy());
6446 msg->setCallback(gatherCB);
6447 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Gather called on comm %d root %d \n", ptr->thisIndex, comm, rootIdx));
6448 ptr->contribute(msg);
6451 ptr->blockOnRedn(new GatherReq(recvbuf, recvcount, recvtype, comm));
6455 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6456 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount * size;
6457 (*(pptr->toPUPer))|(pptr->pupBytes);
6458 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
6466 int AMPI_Igather(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6467 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6468 int root, MPI_Comm comm, MPI_Request *request)
6470 AMPIAPI("AMPI_Igather");
6472 ampi *ptr = getAmpiInstance(comm);
6473 int rank = ptr->getRank();
6475 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6476 handle_MPI_IN_PLACE_gather((void*&)sendbuf, recvbuf, sendcount, sendtype,
6477 rank*recvcount, recvcount, recvtype);
6479 #if AMPI_ERROR_CHECKING
6481 if (sendbuf != recvbuf) {
6482 ret = errorCheck("AMPI_Igather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6483 if(ret != MPI_SUCCESS){
6484 *request = MPI_REQUEST_NULL;
6488 if (getAmpiInstance(comm)->getRank() == root) {
6489 ret = errorCheck("AMPI_Igather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6490 if(ret != MPI_SUCCESS){
6491 *request = MPI_REQUEST_NULL;
6497 if(getAmpiParent()->isInter(comm))
6498 CkAbort("AMPI does not implement MPI_Igather for Inter-communicators!");
6499 if(ptr->getSize() == 1){
6500 *request = ptr->postReq(new GatherReq(recvbuf, recvcount, recvtype, comm, AMPI_REQ_COMPLETED));
6501 return copyDatatype(sendtype,sendcount,recvtype,recvcount,sendbuf,recvbuf);
6505 ampiParent* pptr = getAmpiParent();
6507 (*(pptr->fromPUPer))|(pptr->pupBytes);
6508 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6513 int rootIdx = ptr->comm2CommStruct(comm).getIndexForRank(root);
6514 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6515 CkCallback gatherCB(CkIndex_ampi::irednResult(0), CkArrayIndex1D(rootIdx), ptr->getProxy());
6516 msg->setCallback(gatherCB);
6517 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Igather called on comm %d root %d \n", ptr->thisIndex, comm, rootIdx));
6518 ptr->contribute(msg);
6521 // use a GatherReq to non-block the caller and get a request ptr
6522 *request = ptr->postReq(new GatherReq(recvbuf, recvcount, recvtype, comm));
6525 *request = ptr->postReq(new GatherReq(recvbuf, recvcount, recvtype, comm, AMPI_REQ_COMPLETED));
6529 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6530 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount * size;
6531 (*(pptr->toPUPer))|(pptr->pupBytes);
6532 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
6540 int AMPI_Gatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6541 void *recvbuf, const int *recvcounts, const int *displs,
6542 MPI_Datatype recvtype, int root, MPI_Comm comm)
6544 AMPIAPI("AMPI_Gatherv");
6546 ampi *ptr = getAmpiInstance(comm);
6547 int rank = ptr->getRank();
6549 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6550 handle_MPI_IN_PLACE_gather((void*&)sendbuf, recvbuf, sendcount, sendtype,
6551 displs[rank], recvcounts[rank], recvtype);
6553 #if AMPI_ERROR_CHECKING
6555 if (sendbuf != recvbuf) {
6556 ret = errorCheck("AMPI_Gatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6557 if(ret != MPI_SUCCESS)
6560 if (getAmpiInstance(comm)->getRank() == root) {
6561 ret = errorCheck("AMPI_Gatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6562 if(ret != MPI_SUCCESS)
6567 if(getAmpiParent()->isInter(comm))
6568 CkAbort("AMPI does not implement MPI_Gatherv for Inter-communicators!");
6569 if(ptr->getSize() == 1)
6570 return copyDatatype(sendtype,sendcount,recvtype,recvcounts[0],sendbuf,recvbuf);
6573 ampiParent* pptr = getAmpiParent();
6576 int itemsize = getDDT()->getSize(recvtype);
6577 (*(pptr->fromPUPer))|commsize;
6578 for(int i=0;i<commsize;i++){
6579 (*(pptr->fromPUPer))|(pptr->pupBytes);
6580 PUParray(*(pptr->fromPUPer), (char *)(((char*)recvbuf)+(itemsize*displs[i])), (pptr->pupBytes));
6586 int rootIdx = ptr->comm2CommStruct(comm).getIndexForRank(root);
6587 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6588 CkCallback gathervCB(CkIndex_ampi::rednResult(0), CkArrayIndex1D(rootIdx), ptr->getProxy());
6589 msg->setCallback(gathervCB);
6590 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Gatherv called on comm %d root %d \n", ptr->thisIndex, comm, rootIdx));
6591 ptr->contribute(msg);
6594 ptr->blockOnRedn(new GathervReq(recvbuf, ptr->getSize(), recvtype, comm, recvcounts, displs));
6598 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6599 for(int i=0;i<size;i++){
6600 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcounts[i];
6601 (*(pptr->toPUPer))|(pptr->pupBytes);
6602 PUParray(*(pptr->toPUPer), (char *)(((char*)recvbuf)+(itemsize*displs[i])), (pptr->pupBytes));
6611 int AMPI_Igatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6612 void *recvbuf, const int *recvcounts, const int *displs,
6613 MPI_Datatype recvtype, int root, MPI_Comm comm, MPI_Request *request)
6615 AMPIAPI("AMPI_Igatherv");
6617 ampi *ptr = getAmpiInstance(comm);
6618 int rank = ptr->getRank();
6620 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6621 handle_MPI_IN_PLACE_gather((void*&)sendbuf, recvbuf, sendcount, sendtype,
6622 displs[rank], recvcounts[rank], recvtype);
6624 #if AMPI_ERROR_CHECKING
6626 if (sendbuf != recvbuf) {
6627 ret = errorCheck("AMPI_Igatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6628 if(ret != MPI_SUCCESS){
6629 *request = MPI_REQUEST_NULL;
6633 if (getAmpiInstance(comm)->getRank() == root) {
6634 ret = errorCheck("AMPI_Igatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6635 if(ret != MPI_SUCCESS){
6636 *request = MPI_REQUEST_NULL;
6642 if(getAmpiParent()->isInter(comm))
6643 CkAbort("AMPI does not implement MPI_Igatherv for Inter-communicators!");
6644 if(ptr->getSize() == 1){
6645 *request = ptr->postReq(new GathervReq(recvbuf, rank, recvtype, comm, recvcounts, displs,
6646 AMPI_REQ_COMPLETED));
6647 return copyDatatype(sendtype,sendcount,recvtype,recvcounts[0],sendbuf,recvbuf);
6651 ampiParent* pptr = getAmpiParent();
6654 int itemsize = getDDT()->getSize(recvtype);
6655 (*(pptr->fromPUPer))|commsize;
6656 for(int i=0;i<commsize;i++){
6657 (*(pptr->fromPUPer))|(pptr->pupBytes);
6658 PUParray(*(pptr->fromPUPer), (char *)(((char*)recvbuf)+(itemsize*displs[i])), (pptr->pupBytes));
6664 int rootIdx = ptr->comm2CommStruct(comm).getIndexForRank(root);
6666 CkReductionMsg* msg = makeGatherMsg(sendbuf, sendcount, sendtype, rank);
6667 CkCallback gathervCB(CkIndex_ampi::irednResult(0), CkArrayIndex1D(rootIdx), ptr->getProxy());
6668 msg->setCallback(gathervCB);
6669 MSG_ORDER_DEBUG(CkPrintf("[%d] AMPI_Igatherv called on comm %d root %d \n", ptr->thisIndex, comm, rootIdx));
6670 ptr->contribute(msg);
6673 // use a GathervReq to non-block the caller and get a request ptr
6674 *request = ptr->postReq(new GathervReq(recvbuf, ptr->getSize(), recvtype,
6675 comm, recvcounts, displs));
6678 *request = ptr->postReq(new GathervReq(recvbuf, ptr->getSize(), recvtype,
6679 comm, recvcounts, displs, AMPI_REQ_COMPLETED));
6683 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6684 for(int i=0;i<size;i++){
6685 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcounts[i];
6686 (*(pptr->toPUPer))|(pptr->pupBytes);
6687 PUParray(*(pptr->toPUPer), (char *)(((char*)recvbuf)+(itemsize*displs[i])), (pptr->pupBytes));
6696 int AMPI_Scatter(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6697 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6698 int root, MPI_Comm comm)
6700 AMPIAPI("AMPI_Scatter");
6702 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6703 handle_MPI_IN_PLACE((void*&)sendbuf,recvbuf);
6705 #if AMPI_ERROR_CHECKING
6707 if (getAmpiInstance(comm)->getRank() == root) {
6708 ret = errorCheck("AMPI_Scatter", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6709 if(ret != MPI_SUCCESS)
6712 if (sendbuf != recvbuf || getAmpiInstance(comm)->getRank() != root) {
6713 ret = errorCheck("AMPI_Scatter", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6714 if(ret != MPI_SUCCESS)
6719 ampi *ptr = getAmpiInstance(comm);
6721 if(getAmpiParent()->isInter(comm)) {
6722 return ptr->intercomm_scatter(root,sendbuf,sendcount,sendtype,recvbuf,recvcount,recvtype,comm);
6724 if(ptr->getSize() == 1)
6725 return copyDatatype(sendtype,sendcount,recvtype,recvcount,sendbuf,recvbuf);
6728 ampiParent* pptr = getAmpiParent();
6730 (*(pptr->fromPUPer))|(pptr->pupBytes);
6731 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6736 int size = ptr->getSize();
6737 int rank = ptr->getRank();
6741 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6742 int itemsize = dttype->getSize(sendcount) ;
6743 for(i=0;i<size;i++) {
6745 ptr->send(MPI_SCATTER_TAG, rank, ((char*)sendbuf)+(itemsize*i),
6746 sendcount, sendtype, i, comm);
6749 if (sendbuf != recvbuf) {
6750 copyDatatype(sendtype,sendcount,recvtype,recvcount,(char*)sendbuf+(itemsize*rank),recvbuf);
6754 if(-1==ptr->recv(MPI_SCATTER_TAG, root, recvbuf, recvcount, recvtype, comm))
6755 CkAbort("AMPI> Error in MPI_Scatter recv");
6759 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6760 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount;
6761 (*(pptr->toPUPer))|(pptr->pupBytes);
6762 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
6770 int AMPI_Iscatter(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
6771 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6772 int root, MPI_Comm comm, MPI_Request *request)
6774 AMPIAPI("AMPI_Iscatter");
6776 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6777 handle_MPI_IN_PLACE((void*&)sendbuf,recvbuf);
6779 #if AMPI_ERROR_CHECKING
6781 if (getAmpiInstance(comm)->getRank() == root) {
6782 ret = errorCheck("AMPI_Iscatter", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6783 if(ret != MPI_SUCCESS){
6784 *request = MPI_REQUEST_NULL;
6788 if (sendbuf != recvbuf || getAmpiInstance(comm)->getRank() != root) {
6789 ret = errorCheck("AMPI_Iscatter", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6790 if(ret != MPI_SUCCESS){
6791 *request = MPI_REQUEST_NULL;
6797 ampi *ptr = getAmpiInstance(comm);
6799 if(getAmpiParent()->isInter(comm)) {
6800 return ptr->intercomm_iscatter(root,sendbuf,sendcount,sendtype,recvbuf,recvcount,recvtype,comm,request);
6802 if(ptr->getSize() == 1){
6803 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,
6804 AMPI_REQ_COMPLETED));
6805 return copyDatatype(sendtype,sendcount,recvtype,recvcount,sendbuf,recvbuf);
6809 ampiParent* pptr = getAmpiParent();
6811 (*(pptr->fromPUPer))|(pptr->pupBytes);
6812 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6817 int size = ptr->getSize();
6818 int rank = ptr->getRank();
6822 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6823 int itemsize = dttype->getSize(sendcount) ;
6824 for(i=0;i<size;i++) {
6826 ptr->send(MPI_SCATTER_TAG, rank, ((char*)sendbuf)+(itemsize*i),
6827 sendcount, sendtype, i, comm);
6830 if (sendbuf != recvbuf) {
6831 copyDatatype(sendtype,sendcount,recvtype,recvcount,(char*)sendbuf+(itemsize*rank),recvbuf);
6833 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,AMPI_REQ_COMPLETED));
6836 ptr->irecv(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,request);
6840 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6841 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount;
6842 (*(pptr->toPUPer))|(pptr->pupBytes);
6843 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
6851 int AMPI_Scatterv(const void *sendbuf, const int *sendcounts, const int *displs, MPI_Datatype sendtype,
6852 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6853 int root, MPI_Comm comm)
6855 AMPIAPI("AMPI_Scatterv");
6857 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6858 handle_MPI_IN_PLACE((void*&)sendbuf, recvbuf);
6860 #if AMPI_ERROR_CHECKING
6862 if (getAmpiInstance(comm)->getRank() == root) {
6863 ret = errorCheck("AMPI_Scatterv", comm, 1, 0, 0, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6864 if(ret != MPI_SUCCESS)
6867 if (sendbuf != recvbuf || getAmpiInstance(comm)->getRank() != root) {
6868 ret = errorCheck("AMPI_Scatterv", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6869 if(ret != MPI_SUCCESS)
6874 ampi* ptr = getAmpiInstance(comm);
6876 if (getAmpiParent()->isInter(comm)) {
6877 return ptr->intercomm_scatterv(root, sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, recvtype, comm);
6879 if(ptr->getSize() == 1)
6880 return copyDatatype(sendtype,sendcounts[0],recvtype,recvcount,sendbuf,recvbuf);
6883 ampiParent* pptr = getAmpiParent();
6885 (*(pptr->fromPUPer))|(pptr->pupBytes);
6886 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6891 int size = ptr->getSize();
6892 int rank = ptr->getRank();
6896 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6897 int itemsize = dttype->getSize() ;
6898 for(i=0;i<size;i++) {
6900 ptr->send(MPI_SCATTER_TAG, rank, ((char*)sendbuf)+(itemsize*displs[i]),
6901 sendcounts[i], sendtype, i, comm);
6904 if (sendbuf != recvbuf) {
6905 copyDatatype(sendtype,sendcounts[rank],recvtype,recvcount,(char*)sendbuf+(itemsize*displs[rank]),recvbuf);
6909 if(-1==ptr->recv(MPI_SCATTER_TAG, root, recvbuf, recvcount, recvtype, comm))
6910 CkAbort("AMPI> Error in MPI_Scatterv recv");
6914 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6915 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount;
6916 (*(pptr->toPUPer))|(pptr->pupBytes);
6917 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
6925 int AMPI_Iscatterv(const void *sendbuf, const int *sendcounts, const int *displs, MPI_Datatype sendtype,
6926 void *recvbuf, int recvcount, MPI_Datatype recvtype,
6927 int root, MPI_Comm comm, MPI_Request *request)
6929 AMPIAPI("AMPI_Iscatterv");
6931 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
6932 handle_MPI_IN_PLACE((void*&)sendbuf,recvbuf);
6934 #if AMPI_ERROR_CHECKING
6936 if (getAmpiInstance(comm)->getRank() == root) {
6937 ret = errorCheck("AMPI_Iscatterv", comm, 1, 0, 0, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
6938 if(ret != MPI_SUCCESS){
6939 *request = MPI_REQUEST_NULL;
6943 if (sendbuf != recvbuf || getAmpiInstance(comm)->getRank() != root) {
6944 ret = errorCheck("AMPI_Iscatterv", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
6945 if(ret != MPI_SUCCESS){
6946 *request = MPI_REQUEST_NULL;
6952 ampi* ptr = getAmpiInstance(comm);
6954 if (getAmpiParent()->isInter(comm)) {
6955 return ptr->intercomm_iscatterv(root, sendbuf, sendcounts, displs, sendtype, recvbuf, recvcount, recvtype, comm, request);
6957 if(ptr->getSize() == 1){
6958 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,
6959 AMPI_REQ_COMPLETED));
6960 return copyDatatype(sendtype,sendcounts[0],recvtype,recvcount,sendbuf,recvbuf);
6964 ampiParent* pptr = getAmpiParent();
6966 (*(pptr->fromPUPer))|(pptr->pupBytes);
6967 PUParray(*(pptr->fromPUPer), (char *)recvbuf, (pptr->pupBytes));
6972 int size = ptr->getSize();
6973 int rank = ptr->getRank();
6977 CkDDT_DataType* dttype = ptr->getDDT()->getType(sendtype) ;
6978 int itemsize = dttype->getSize() ;
6979 for(i=0;i<size;i++) {
6981 ptr->send(MPI_SCATTER_TAG, rank, ((char*)sendbuf)+(itemsize*displs[i]),
6982 sendcounts[i], sendtype, i, comm);
6985 if (sendbuf != recvbuf) {
6986 copyDatatype(sendtype,sendcounts[rank],recvtype,recvcount,(char*)sendbuf+(itemsize*displs[rank]),recvbuf);
6988 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,AMPI_REQ_COMPLETED));
6991 // call irecv to post an IReq and process any pending messages
6992 ptr->irecv(recvbuf,recvcount,recvtype,root,MPI_SCATTER_TAG,comm,request);
6996 if(msgLogWrite && record_msglog(pptr->thisIndex)){
6997 (pptr->pupBytes) = getDDT()->getSize(recvtype) * recvcount;
6998 (*(pptr->toPUPer))|(pptr->pupBytes);
6999 PUParray(*(pptr->toPUPer), (char *)recvbuf, (pptr->pupBytes));
7007 int AMPI_Alltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
7008 void *recvbuf, int recvcount, MPI_Datatype recvtype,
7011 AMPIAPI("AMPI_Alltoall");
7013 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7014 handle_MPI_IN_PLACE_alltoall((void*&)sendbuf, recvbuf, sendcount, sendtype, recvcount, recvtype);
7016 #if AMPI_ERROR_CHECKING
7018 if (sendbuf != recvbuf) {
7019 ret = errorCheck("AMPI_Alltoall", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7020 if(ret != MPI_SUCCESS)
7023 ret = errorCheck("AMPI_Alltoall", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7024 if(ret != MPI_SUCCESS)
7028 ampi *ptr = getAmpiInstance(comm);
7030 if(getAmpiParent()->isInter(comm))
7031 CkAbort("AMPI does not implement MPI_Alltoall for Inter-communicators!");
7032 if(ptr->getSize() == 1)
7033 return copyDatatype(sendtype,sendcount,recvtype,recvcount,sendbuf,recvbuf);
7035 int itemsize = getDDT()->getSize(sendtype) * sendcount;
7036 int extent = getDDT()->getExtent(recvtype) * recvcount;
7037 int size = ptr->getSize();
7038 int rank = ptr->getRank();
7040 #if CMK_BIGSIM_CHARM
7041 TRACE_BG_AMPI_LOG(MPI_ALLTOALL, itemsize);
7044 /* For MPI_IN_PLACE (sendbuf==recvbuf), prevent using the algorithm for
7045 * large message sizes, since it might lead to overwriting data before
7046 * it gets sent in the non-power-of-two communicator size case. */
7047 if (recvbuf == sendbuf) {
7048 for (int i=0; i<size; i++) {
7049 for (int j=i; j<size; j++) {
7051 AMPI_Sendrecv_replace(((char *)recvbuf + j*recvcount*extent),
7052 recvcount, recvtype, j, MPI_ATA_TAG, j,
7053 MPI_ATA_TAG, comm, MPI_STATUS_IGNORE);
7055 else if (rank == j) {
7056 AMPI_Sendrecv_replace(((char *)recvbuf + i*recvcount*extent),
7057 recvcount, recvtype, i, MPI_ATA_TAG, i,
7058 MPI_ATA_TAG, comm, MPI_STATUS_IGNORE);
7063 else if (itemsize <= AMPI_ALLTOALL_LONG_MSG) {
7064 vector<MPI_Request> reqs(size*2);
7065 for (int i=0; i<size; i++) {
7066 int src = (rank+i) % size;
7067 ptr->irecv(((char*)recvbuf)+(extent*src), recvcount, recvtype,
7068 src, MPI_ATA_TAG, comm, &reqs[i]);
7070 for (int i=0; i<size; i++) {
7071 int dst = (rank+i) % size;
7072 reqs[size+i] = ptr->send(MPI_ATA_TAG, rank, ((char*)sendbuf)+(itemsize*dst),
7073 sendcount, sendtype, dst, comm, 0, I_SEND);
7075 AMPI_Waitall(reqs.size(), &reqs[0], MPI_STATUSES_IGNORE);
7078 /* Long message. Use pairwise exchange. If comm_size is a
7079 power-of-two, use exclusive-or to create pairs. Else send
7080 to rank+i, receive from rank-i. */
7083 /* Is comm_size a power-of-two? */
7087 bool isPof2 = (pof2 == size);
7089 /* The i=0 case takes care of moving local data into recvbuf */
7090 for (int i=0; i<size; i++) {
7092 /* use exclusive-or algorithm */
7093 src = dst = rank ^ i;
7096 src = (rank - i + size) % size;
7097 dst = (rank + i) % size;
7100 ptr->sendrecv(((char *)sendbuf + dst*itemsize), sendcount, sendtype, dst, MPI_ATA_TAG,
7101 ((char *)recvbuf + src*extent), recvcount, recvtype, src, MPI_ATA_TAG,
7102 comm, MPI_STATUS_IGNORE);
7103 } // end of large message
7110 int AMPI_Alltoall_iget(void *sendbuf, int sendcount, MPI_Datatype sendtype,
7111 void *recvbuf, int recvcount, MPI_Datatype recvtype,
7114 AMPIAPI("AMPI_Alltoall_iget");
7116 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
7118 #if AMPI_ERROR_CHECKING
7120 ret = errorCheck("AMPI_Alltoall_iget", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7121 if(ret != MPI_SUCCESS)
7123 ret = errorCheck("AMPI_Alltoall_iget", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7124 if(ret != MPI_SUCCESS)
7128 ampi *ptr = getAmpiInstance(comm);
7129 int size = ptr->getSize();
7131 if(getAmpiParent()->isInter(comm))
7132 CkAbort("AMPI does not implement MPI_Alltoall_iget for Inter-communicators!");
7134 return copyDatatype(sendtype,sendcount,recvtype,recvcount,sendbuf,recvbuf);
7135 if(sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7136 CkAbort("AMPI does not implement MPI_IN_PLACE for MPI_Alltoall_iget!");
7138 CProxy_ampi pa(ptr->ckGetArrayID());
7139 CkDDT_DataType *dttype;
7144 // Set flags for others to get
7145 ptr->setA2AIgetFlag((void*)sendbuf);
7146 MPI_Comm_rank(comm,&myrank);
7147 recvdisp = myrank*recvcount;
7151 vector<MPI_Request> reqs(size);
7152 for(i=0;i<size;i++) {
7153 reqs[i] = pa[i].Alltoall_RemoteIget(recvdisp, recvcount, recvtype, MPI_ATA_TAG);
7156 dttype = ptr->getDDT()->getType(recvtype) ;
7157 itemsize = dttype->getSize(recvcount) ;
7159 for(i=0;i<size;i++) {
7160 msg = (AmpiMsg*)CkWaitReleaseFuture(reqs[i]);
7161 memcpy((char*)recvbuf+(itemsize*i), msg->getData(),itemsize);
7168 ptr->resetA2AIgetFlag();
7174 int AMPI_Ialltoall(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
7175 void *recvbuf, int recvcount, MPI_Datatype recvtype,
7176 MPI_Comm comm, MPI_Request *request)
7178 AMPIAPI("AMPI_Ialltoall");
7180 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7181 handle_MPI_IN_PLACE_alltoall((void*&)sendbuf, recvbuf, sendcount, sendtype, recvcount, recvtype);
7183 #if AMPI_ERROR_CHECKING
7185 if (sendbuf != recvbuf) {
7186 ret = errorCheck("AMPI_Ialltoall", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7187 if(ret != MPI_SUCCESS){
7188 *request = MPI_REQUEST_NULL;
7192 ret = errorCheck("AMPI_Ialltoall", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7193 if(ret != MPI_SUCCESS){
7194 *request = MPI_REQUEST_NULL;
7199 ampi *ptr = getAmpiInstance(comm);
7200 int size = ptr->getSize();
7202 if(getAmpiParent()->isInter(comm))
7203 CkAbort("AMPI does not implement MPI_Ialltoall for Inter-communicators!");
7205 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,ptr->getRank(),MPI_ATA_TAG,comm,
7206 AMPI_REQ_COMPLETED));
7207 return copyDatatype(sendtype,sendcount,recvtype,recvcount,sendbuf,recvbuf);
7210 int rank = ptr->getRank();
7211 int itemsize = getDDT()->getSize(sendtype) * sendcount;
7212 int extent = getDDT()->getExtent(recvtype) * recvcount;
7214 // use an IATAReq to non-block the caller and get a request ptr
7215 AmpiRequestList* reqs = getReqs();
7216 IATAReq *newreq = new IATAReq(size);
7217 for (int i=0; i<size; i++) {
7218 if (newreq->addReq(((char*)recvbuf)+(extent*i),recvcount,recvtype,i,MPI_ATA_TAG,comm)!=(i+1))
7219 CkAbort("MPI_Ialltoall: Error adding requests into IATAReq!");
7221 *request = ptr->postReq(newreq);
7223 for (int i=0; i<size; i++) {
7224 int dst = (rank+i) % size;
7225 ptr->send(MPI_ATA_TAG, rank, ((char*)sendbuf)+(itemsize*dst), sendcount,
7226 sendtype, dst, comm);
7229 AMPI_DEBUG("MPI_Ialltoall: request=%d, reqs.size=%d, &reqs=%d\n",*request,reqs->size(),reqs);
7234 int AMPI_Alltoallv(const void *sendbuf, const int *sendcounts, const int *sdispls,
7235 MPI_Datatype sendtype, void *recvbuf, const int *recvcounts,
7236 const int *rdispls, MPI_Datatype recvtype, MPI_Comm comm)
7238 AMPIAPI("AMPI_Alltoallv");
7240 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7241 handle_MPI_IN_PLACE_alltoallv((void*&)sendbuf, recvbuf, (int*&)sendcounts, sendtype,
7242 (int*&)sdispls, recvcounts, recvtype, rdispls);
7244 #if AMPI_ERROR_CHECKING
7246 if (sendbuf != recvbuf) {
7247 ret = errorCheck("AMPI_Alltoallv", comm, 1, 0, 0, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7248 if(ret != MPI_SUCCESS)
7251 ret = errorCheck("AMPI_Alltoallv", comm, 1, 0, 0, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7252 if(ret != MPI_SUCCESS)
7256 ampi *ptr = getAmpiInstance(comm);
7257 int size = ptr->getSize();
7259 if(getAmpiParent()->isInter(comm))
7260 CkAbort("AMPI does not implement MPI_Alltoallv for Inter-communicators!");
7262 return copyDatatype(sendtype,sendcounts[0],recvtype,recvcounts[0],sendbuf,recvbuf);
7264 int rank = ptr->getRank();
7265 int itemsize = getDDT()->getSize(sendtype);
7266 int extent = getDDT()->getExtent(recvtype);
7268 vector<MPI_Request> reqs(size*2);
7269 for (int i=0; i<size; i++) {
7270 int src = (rank+i) % size;
7271 ptr->irecv(((char*)recvbuf)+(extent*rdispls[src]), recvcounts[src], recvtype,
7272 src, MPI_ATA_TAG, comm, &reqs[i]);
7274 for (int i=0; i<size; i++) {
7275 int dst = (rank+i) % size;
7276 reqs[size+i] = ptr->send(MPI_ATA_TAG, rank, ((char*)sendbuf)+(itemsize*sdispls[dst]),
7277 sendcounts[dst], sendtype, dst, comm, 0, I_SEND);
7279 AMPI_Waitall(reqs.size(), &reqs[0], MPI_STATUSES_IGNORE);
7285 int AMPI_Ialltoallv(void *sendbuf, int *sendcounts, int *sdispls, MPI_Datatype sendtype,
7286 void *recvbuf, int *recvcounts, int *rdispls, MPI_Datatype recvtype,
7287 MPI_Comm comm, MPI_Request *request)
7289 AMPIAPI("AMPI_Ialltoallv");
7291 handle_MPI_BOTTOM(sendbuf, sendtype, recvbuf, recvtype);
7292 handle_MPI_IN_PLACE_alltoallv((void*&)sendbuf, recvbuf, (int*&)sendcounts, sendtype,
7293 (int*&)sdispls, recvcounts, recvtype, rdispls);
7295 #if AMPI_ERROR_CHECKING
7297 if (sendbuf != recvbuf) {
7298 ret = errorCheck("AMPI_Ialltoallv", comm, 1, 0, 0, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7299 if(ret != MPI_SUCCESS){
7300 *request = MPI_REQUEST_NULL;
7304 ret = errorCheck("AMPI_Ialltoallv", comm, 1, 0, 0, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7305 if(ret != MPI_SUCCESS){
7306 *request = MPI_REQUEST_NULL;
7311 ampi *ptr = getAmpiInstance(comm);
7312 int size = ptr->getSize();
7314 if(getAmpiParent()->isInter(comm))
7315 CkAbort("AMPI does not implement MPI_Ialltoallv for Inter-communicators!");
7317 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtype,ptr->getRank(),MPI_ATA_TAG,comm,
7318 AMPI_REQ_COMPLETED));
7319 return copyDatatype(sendtype,sendcounts[0],recvtype,recvcounts[0],sendbuf,recvbuf);
7322 int rank = ptr->getRank();
7323 int itemsize = getDDT()->getSize(sendtype);
7324 int extent = getDDT()->getExtent(recvtype);
7326 // use an IATAReq to non-block the caller and get a request ptr
7327 AmpiRequestList* reqs = getReqs();
7328 IATAReq *newreq = new IATAReq(size);
7329 for (int i=0; i<size; i++) {
7330 if (newreq->addReq((void*)(((char*)recvbuf)+(extent*rdispls[i])),recvcounts[i],recvtype,i,MPI_ATA_TAG,comm)!=(i+1))
7331 CkAbort("MPI_Ialltoallv: Error adding requests into IATAReq!");
7333 *request = ptr->postReq(newreq);
7335 for (int i=0; i<size; i++) {
7336 int dst = (rank+i) % size;
7337 ptr->send(MPI_ATA_TAG, rank, ((char*)sendbuf)+(itemsize*sdispls[dst]), sendcounts[dst],
7338 sendtype, dst, comm);
7341 AMPI_DEBUG("MPI_Ialltoallv: request=%d, reqs.size=%d, &reqs=%d\n",*request,reqs->size(),reqs);
7347 int AMPI_Alltoallw(const void *sendbuf, const int *sendcounts, const int *sdispls,
7348 const MPI_Datatype *sendtypes, void *recvbuf, const int *recvcounts,
7349 const int *rdispls, const MPI_Datatype *recvtypes, MPI_Comm comm)
7351 AMPIAPI("AMPI_Alltoallw");
7353 handle_MPI_BOTTOM((void*&)sendbuf, sendtypes[0], recvbuf, recvtypes[0]);
7354 handle_MPI_IN_PLACE_alltoallw((void*&)sendbuf, recvbuf, (int*&)sendcounts,
7355 (MPI_Datatype*&)sendtypes, (int*&)sdispls,
7356 recvcounts, recvtypes, rdispls);
7358 #if AMPI_ERROR_CHECKING
7360 if (sendbuf != recvbuf) {
7361 ret = errorCheck("AMPI_Alltoallw", comm, 1, 0, 0, sendtypes[0], 1, 0, 0, 0, 0, sendbuf, 1);
7362 if(ret != MPI_SUCCESS)
7365 ret = errorCheck("AMPI_Alltoallw", comm, 1, 0, 0, recvtypes[0], 1, 0, 0, 0, 0, recvbuf, 1);
7366 if(ret != MPI_SUCCESS)
7370 ampi *ptr = getAmpiInstance(comm);
7371 int size = ptr->getSize();
7372 int rank = ptr->getRank();
7374 if(getAmpiParent()->isInter(comm))
7375 CkAbort("AMPI does not implement MPI_Alltoallw for Inter-communicators!");
7377 return copyDatatype(sendtypes[0],sendcounts[0],recvtypes[0],recvcounts[0],sendbuf,recvbuf);
7379 /* displs are in terms of bytes for Alltoallw (unlike Alltoallv) */
7380 vector<MPI_Request> reqs(size*2);
7381 for (int i=0; i<size; i++) {
7382 int src = (rank+i) % size;
7383 ptr->irecv(((char*)recvbuf)+rdispls[src], recvcounts[src], recvtypes[src],
7384 src, MPI_ATA_TAG, comm, &reqs[i]);
7386 for (int i=0; i<size; i++) {
7387 int dst = (rank+i) % size;
7388 reqs[size+i] = ptr->send(MPI_ATA_TAG, rank, ((char*)sendbuf)+sdispls[dst],
7389 sendcounts[dst], sendtypes[dst], dst, comm, 0, I_SEND);
7391 AMPI_Waitall(reqs.size(), &reqs[0], MPI_STATUSES_IGNORE);
7397 int AMPI_Ialltoallw(const void *sendbuf, const int *sendcounts, const int *sdispls,
7398 const MPI_Datatype *sendtypes, void *recvbuf, const int *recvcounts,
7399 const int *rdispls, const MPI_Datatype *recvtypes, MPI_Comm comm,
7400 MPI_Request *request)
7402 AMPIAPI("AMPI_Ialltoallw");
7404 handle_MPI_BOTTOM((void*&)sendbuf, sendtypes[0], recvbuf, recvtypes[0]);
7405 handle_MPI_IN_PLACE_alltoallw((void*&)sendbuf, recvbuf, (int*&)sendcounts,
7406 (MPI_Datatype*&)sendtypes, (int*&)sdispls,
7407 recvcounts, recvtypes, rdispls);
7409 #if AMPI_ERROR_CHECKING
7411 if (sendbuf != recvbuf) {
7412 ret = errorCheck("AMPI_Ialltoallw", comm, 1, 0, 0, sendtypes[0], 1, 0, 0, 0, 0, sendbuf, 1);
7413 if(ret != MPI_SUCCESS){
7414 *request = MPI_REQUEST_NULL;
7418 ret = errorCheck("AMPI_Ialltoallw", comm, 1, 0, 0, recvtypes[0], 1, 0, 0, 0, 0, recvbuf, 1);
7419 if(ret != MPI_SUCCESS){
7420 *request = MPI_REQUEST_NULL;
7425 ampi *ptr = getAmpiInstance(comm);
7426 int size = ptr->getSize();
7427 int rank = ptr->getRank();
7429 if(getAmpiParent()->isInter(comm))
7430 CkAbort("AMPI does not implement MPI_Ialltoallw for Inter-communicators!");
7432 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtypes[0],ptr->getRank(),MPI_ATA_TAG,comm,
7433 AMPI_REQ_COMPLETED));
7434 return copyDatatype(sendtypes[0],sendcounts[0],recvtypes[0],recvcounts[0],sendbuf,recvbuf);
7437 /* displs are in terms of bytes for Alltoallw (unlike Alltoallv) */
7438 for (int i=0; i<size; i++) {
7439 int dst = (rank+i) % size;
7440 ptr->send(MPI_ATA_TAG, rank, ((char*)sendbuf)+sdispls[dst],
7441 sendcounts[dst], sendtypes[dst], dst, comm);
7444 // use an IATAReq to non-block the caller and get a request ptr
7445 AmpiRequestList* reqs = getReqs();
7446 IATAReq *newreq = new IATAReq(size);
7447 for (int i=0; i<size; i++) {
7448 if (newreq->addReq((void*)(((char*)recvbuf)+rdispls[i]), recvcounts[i],
7449 recvtypes[i], i, MPI_ATA_TAG, comm) != (i+1))
7450 CkAbort("MPI_Ialltoallw: Error adding requests into IATAReq!");
7452 *request = ptr->postReq(newreq);
7458 int AMPI_Neighbor_alltoall(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
7459 void* recvbuf, int recvcount, MPI_Datatype recvtype,
7462 AMPIAPI("AMPI_Neighbor_alltoall");
7464 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7466 #if AMPI_ERROR_CHECKING
7467 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7468 CkAbort("MPI_Neighbor_alltoall does not accept MPI_IN_PLACE!");
7469 if (getAmpiParent()->isInter(comm))
7470 CkAbort("MPI_Neighbor_alltoall is not defined for Inter-communicators!");
7472 ret = errorCheck("AMPI_Neighbor_alltoall", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7473 if(ret != MPI_SUCCESS)
7475 ret = errorCheck("AMPI_Neighbor_alltoall", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7476 if(ret != MPI_SUCCESS)
7480 ampi *ptr = getAmpiInstance(comm);
7481 int rank_in_comm = ptr->getRank();
7483 if (ptr->getSize() == 1)
7484 return copyDatatype(sendtype, sendcount, recvtype, recvcount, sendbuf, recvbuf);
7486 const vector<int>& neighbors = ptr->getNeighbors();
7487 int num_neighbors = neighbors.size();
7488 int itemsize = getDDT()->getSize(sendtype) * sendcount;
7489 int extent = getDDT()->getExtent(recvtype) * recvcount;
7491 vector<MPI_Request> reqs(num_neighbors*2);
7492 for (int j=0; j<num_neighbors; j++) {
7493 ptr->irecv(((char*)recvbuf)+(extent*j), recvcount, recvtype,
7494 neighbors[j], MPI_NBOR_TAG, comm, &reqs[j]);
7497 for (int i=0; i<num_neighbors; i++) {
7498 reqs[num_neighbors+i] = ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+(itemsize*i)),
7499 sendcount, sendtype, neighbors[i], comm, 0, I_SEND);
7502 AMPI_Waitall(reqs.size(), &reqs[0], MPI_STATUSES_IGNORE);
7508 int AMPI_Ineighbor_alltoall(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
7509 void* recvbuf, int recvcount, MPI_Datatype recvtype,
7510 MPI_Comm comm, MPI_Request *request)
7512 AMPIAPI("AMPI_Ineighbor_alltoall");
7514 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7516 #if AMPI_ERROR_CHECKING
7517 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7518 CkAbort("MPI_Ineighbor_alltoall does not accept MPI_IN_PLACE!");
7519 if (getAmpiParent()->isInter(comm))
7520 CkAbort("MPI_Ineighbor_alltoall is not defined for Inter-communicators!");
7522 ret = errorCheck("AMPI_Ineighbor_alltoall", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7523 if(ret != MPI_SUCCESS){
7524 *request = MPI_REQUEST_NULL;
7527 ret = errorCheck("AMPI_Ineighbor_alltoall", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7528 if(ret != MPI_SUCCESS){
7529 *request = MPI_REQUEST_NULL;
7534 ampi *ptr = getAmpiInstance(comm);
7535 int rank_in_comm = ptr->getRank();
7537 if (ptr->getSize() == 1) {
7538 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,rank_in_comm,MPI_NBOR_TAG,comm,
7539 AMPI_REQ_COMPLETED));
7540 return copyDatatype(sendtype, sendcount, recvtype, recvcount, sendbuf, recvbuf);
7543 const vector<int>& neighbors = ptr->getNeighbors();
7544 int num_neighbors = neighbors.size();
7545 int itemsize = getDDT()->getSize(sendtype) * sendcount;
7546 int extent = getDDT()->getExtent(recvtype) * recvcount;
7548 // use an IATAReq to non-block the caller and get a request ptr
7549 AmpiRequestList* reqs = getReqs();
7550 IATAReq *newreq = new IATAReq(num_neighbors);
7551 for (int j=0; j<num_neighbors; j++) {
7552 if(newreq->addReq(((char*)recvbuf)+(extent*j), recvcount, recvtype,
7553 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7554 CkAbort("MPI_Ineighbor_alltoall: Error adding requests into IATAReq!");
7556 *request = ptr->postReq(newreq);
7558 for (int i=0; i<num_neighbors; i++) {
7559 ptr->send(MPI_ATA_TAG, rank_in_comm, ((char*)sendbuf)+(i*itemsize),
7560 sendcount, sendtype, neighbors[i], comm);
7567 int AMPI_Neighbor_alltoallv(const void* sendbuf, const int *sendcounts, const int *sdispls,
7568 MPI_Datatype sendtype, void* recvbuf, const int *recvcounts,
7569 const int *rdispls, MPI_Datatype recvtype, MPI_Comm comm)
7571 AMPIAPI("AMPI_Neighbor_alltoallv");
7573 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7575 #if AMPI_ERROR_CHECKING
7576 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7577 CkAbort("MPI_Neighbor_alltoallv does not accept MPI_IN_PLACE!");
7578 if (getAmpiParent()->isInter(comm))
7579 CkAbort("MPI_Neighbor_alltoallv is not defined for Inter-communicators!");
7581 ret = errorCheck("AMPI_Neighbor_alltoallv", comm, 1, sendcounts[0], 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7582 if(ret != MPI_SUCCESS)
7584 ret = errorCheck("AMPI_Neighbor_alltoallv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7585 if(ret != MPI_SUCCESS)
7589 ampi *ptr = getAmpiInstance(comm);
7590 int rank_in_comm = ptr->getRank();
7592 if (ptr->getSize() == 1)
7593 return copyDatatype(sendtype, sendcounts[0], recvtype, recvcounts[0], sendbuf, recvbuf);
7595 const vector<int>& neighbors = ptr->getNeighbors();
7596 int num_neighbors = neighbors.size();
7597 int itemsize = getDDT()->getSize(sendtype);
7598 int extent = getDDT()->getExtent(recvtype);
7600 vector<MPI_Request> reqs(num_neighbors*2);
7601 for (int j=0; j<num_neighbors; j++) {
7602 ptr->irecv(((char*)recvbuf)+(extent*rdispls[j]), recvcounts[j], recvtype,
7603 neighbors[j], MPI_NBOR_TAG, comm, &reqs[j]);
7606 for (int i=0; i<num_neighbors; i++) {
7607 reqs[num_neighbors+i] = ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+(itemsize*sdispls[i])),
7608 sendcounts[i], sendtype, neighbors[i], comm, 0, I_SEND);
7611 AMPI_Waitall(reqs.size(), &reqs[0], MPI_STATUSES_IGNORE);
7617 int AMPI_Ineighbor_alltoallv(const void* sendbuf, const int *sendcounts, const int *sdispls,
7618 MPI_Datatype sendtype, void* recvbuf, const int *recvcounts,
7619 const int *rdispls, MPI_Datatype recvtype, MPI_Comm comm,
7620 MPI_Request *request)
7622 AMPIAPI("AMPI_Ineighbor_alltoallv");
7624 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7626 #if AMPI_ERROR_CHECKING
7627 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7628 CkAbort("MPI_Ineighbor_alltoallv does not accept MPI_IN_PLACE!");
7629 if (getAmpiParent()->isInter(comm))
7630 CkAbort("MPI_Ineighbor_alltoallv is not defined for Inter-communicators!");
7632 ret = errorCheck("AMPI_Ineighbor_alltoallv", comm, 1, sendcounts[0], 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7633 if(ret != MPI_SUCCESS){
7634 *request = MPI_REQUEST_NULL;
7637 ret = errorCheck("AMPI_Ineighbor_alltoallv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7638 if(ret != MPI_SUCCESS){
7639 *request = MPI_REQUEST_NULL;
7644 ampi *ptr = getAmpiInstance(comm);
7645 int rank_in_comm = ptr->getRank();
7647 if (ptr->getSize() == 1) {
7648 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtype,rank_in_comm,MPI_NBOR_TAG,comm,
7649 AMPI_REQ_COMPLETED));
7650 return copyDatatype(sendtype, sendcounts[0], recvtype, recvcounts[0], sendbuf, recvbuf);
7653 const vector<int>& neighbors = ptr->getNeighbors();
7654 int num_neighbors = neighbors.size();
7655 int itemsize = getDDT()->getSize(sendtype);
7656 int extent = getDDT()->getExtent(recvtype);
7658 // use an IATAReq to non-block the caller and get a request ptr
7659 AmpiRequestList* reqs = getReqs();
7660 IATAReq *newreq = new IATAReq(num_neighbors);
7661 for (int j=0; j<num_neighbors; j++) {
7662 if(newreq->addReq(((char*)recvbuf)+(extent*rdispls[j]), recvcounts[j], recvtype,
7663 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7664 CkAbort("MPI_Ineighbor_alltoallv: Error adding requests into IATAReq!");
7666 *request = ptr->postReq(newreq);
7668 for (int i=0; i<num_neighbors; i++) {
7669 ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+(itemsize*sdispls[i])),
7670 sendcounts[i], sendtype, neighbors[i], comm);
7677 int AMPI_Neighbor_alltoallw(const void* sendbuf, const int *sendcounts, const MPI_Aint *sdispls,
7678 const MPI_Datatype *sendtypes, void* recvbuf, const int *recvcounts,
7679 const MPI_Aint *rdispls, const MPI_Datatype *recvtypes, MPI_Comm comm)
7681 AMPIAPI("AMPI_Neighbor_alltoallw");
7683 handle_MPI_BOTTOM((void*&)sendbuf, sendtypes[0], recvbuf, recvtypes[0]);
7685 #if AMPI_ERROR_CHECKING
7686 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7687 CkAbort("MPI_Neighbor_alltoallw does not accept MPI_IN_PLACE!");
7688 if (getAmpiParent()->isInter(comm))
7689 CkAbort("MPI_Neighbor_alltoallw is not defined for Inter-communicators!");
7691 ret = errorCheck("AMPI_Neighbor_alltoallw", comm, 1, sendcounts[0], 1, sendtypes[0], 1, 0, 0, 0, 0, sendbuf, 1);
7692 if(ret != MPI_SUCCESS)
7694 ret = errorCheck("AMPI_Neighbor_alltoallw", comm, 1, recvcounts[0], 1, recvtypes[0], 1, 0, 0, 0, 0, recvbuf, 1);
7695 if(ret != MPI_SUCCESS)
7699 ampi *ptr = getAmpiInstance(comm);
7700 int rank_in_comm = ptr->getRank();
7702 if (ptr->getSize() == 1)
7703 return copyDatatype(sendtypes[0], sendcounts[0], recvtypes[0], recvcounts[0], sendbuf, recvbuf);
7705 const vector<int>& neighbors = ptr->getNeighbors();
7706 int num_neighbors = neighbors.size();
7708 vector<MPI_Request> reqs(num_neighbors*2);
7709 for (int j=0; j<num_neighbors; j++) {
7710 ptr->irecv(((char*)recvbuf)+rdispls[j], recvcounts[j], recvtypes[j],
7711 neighbors[j], MPI_NBOR_TAG, comm, &reqs[j]);
7714 for (int i=0; i<num_neighbors; i++) {
7715 reqs[num_neighbors+i] = ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+sdispls[i]),
7716 sendcounts[i], sendtypes[i], neighbors[i], comm, 0, I_SEND);
7719 AMPI_Waitall(reqs.size(), &reqs[0], MPI_STATUSES_IGNORE);
7725 int AMPI_Ineighbor_alltoallw(const void* sendbuf, const int *sendcounts, const MPI_Aint *sdispls,
7726 const MPI_Datatype *sendtypes, void* recvbuf, const int *recvcounts,
7727 const MPI_Aint *rdispls, const MPI_Datatype *recvtypes, MPI_Comm comm,
7728 MPI_Request *request)
7730 AMPIAPI("AMPI_Ineighbor_alltoallw");
7732 handle_MPI_BOTTOM((void*&)sendbuf, sendtypes[0], recvbuf, recvtypes[0]);
7734 #if AMPI_ERROR_CHECKING
7735 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7736 CkAbort("MPI_Ineighbor_alltoallw does not accept MPI_IN_PLACE!");
7737 if (getAmpiParent()->isInter(comm))
7738 CkAbort("MPI_Ineighbor_alltoallw is not defined for Inter-communicators!");
7740 ret = errorCheck("AMPI_Ineighbor_alltoallw", comm, 1, sendcounts[0], 1, sendtypes[0], 1, 0, 0, 0, 0, sendbuf, 1);
7741 if(ret != MPI_SUCCESS){
7742 *request = MPI_REQUEST_NULL;
7745 ret = errorCheck("AMPI_Ineighbor_alltoallw", comm, 1, recvcounts[0], 1, recvtypes[0], 1, 0, 0, 0, 0, recvbuf, 1);
7746 if(ret != MPI_SUCCESS){
7747 *request = MPI_REQUEST_NULL;
7752 ampi *ptr = getAmpiInstance(comm);
7753 int rank_in_comm = ptr->getRank();
7755 if (ptr->getSize() == 1) {
7756 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtypes[0],rank_in_comm,MPI_NBOR_TAG,comm,
7757 AMPI_REQ_COMPLETED));
7758 return copyDatatype(sendtypes[0], sendcounts[0], recvtypes[0], recvcounts[0], sendbuf, recvbuf);
7761 const vector<int>& neighbors = ptr->getNeighbors();
7762 int num_neighbors = neighbors.size();
7764 // use an IATAReq to non-block the caller and get a request ptr
7765 AmpiRequestList* reqs = getReqs();
7766 IATAReq *newreq = new IATAReq(num_neighbors);
7767 for (int j=0; j<num_neighbors; j++) {
7768 if(newreq->addReq((char*)recvbuf+rdispls[j], recvcounts[j], recvtypes[j],
7769 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7770 CkAbort("MPI_Ineighbor_alltoallw: Error adding requests into IATAReq!");
7772 *request = ptr->postReq(newreq);
7774 for (int i=0; i<num_neighbors; i++) {
7775 ptr->send(MPI_NBOR_TAG, rank_in_comm, (void*)((char*)sendbuf+sdispls[i]),
7776 sendcounts[i], sendtypes[i], neighbors[i], comm);
7783 int AMPI_Neighbor_allgather(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
7784 void* recvbuf, int recvcount, MPI_Datatype recvtype,
7787 AMPIAPI("AMPI_Neighbor_allgather");
7789 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7791 #if AMPI_ERROR_CHECKING
7792 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7793 CkAbort("MPI_Neighbor_allgather does not accept MPI_IN_PLACE!");
7794 if (getAmpiParent()->isInter(comm))
7795 CkAbort("MPI_Neighbor_allgather is not defined for Inter-communicators!");
7797 ret = errorCheck("AMPI_Neighbor_allgather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7798 if(ret != MPI_SUCCESS)
7800 ret = errorCheck("AMPI_Neighbor_allgather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7801 if(ret != MPI_SUCCESS)
7805 ampi *ptr = getAmpiInstance(comm);
7806 int rank_in_comm = ptr->getRank();
7808 if (ptr->getSize() == 1)
7809 return copyDatatype(sendtype, sendcount, recvtype, recvcount, sendbuf, recvbuf);
7811 const vector<int>& neighbors = ptr->getNeighbors();
7812 int num_neighbors = neighbors.size();
7814 int extent = getDDT()->getExtent(recvtype) * recvcount;
7815 vector<MPI_Request> reqs(num_neighbors*2);
7816 for (int j=0; j<num_neighbors; j++) {
7817 ptr->irecv(((char*)recvbuf)+(extent*j), recvcount, recvtype,
7818 neighbors[j], MPI_NBOR_TAG, comm, &reqs[j]);
7821 for (int i=0; i<num_neighbors; i++) {
7822 reqs[num_neighbors+i] = ptr->send(MPI_NBOR_TAG, rank_in_comm, sendbuf, sendcount,
7823 sendtype, neighbors[i], comm, 0, I_SEND);
7826 AMPI_Waitall(reqs.size(), &reqs[0], MPI_STATUSES_IGNORE);
7832 int AMPI_Ineighbor_allgather(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
7833 void* recvbuf, int recvcount, MPI_Datatype recvtype,
7834 MPI_Comm comm, MPI_Request *request)
7836 AMPIAPI("AMPI_Ineighbor_allgather");
7838 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7840 #if AMPI_ERROR_CHECKING
7841 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7842 CkAbort("MPI_Ineighbor_allgather does not accept MPI_IN_PLACE!");
7843 if (getAmpiParent()->isInter(comm))
7844 CkAbort("MPI_Ineighbor_allgather is not defined for Inter-communicators!");
7846 ret = errorCheck("AMPI_Ineighbor_allgather", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7847 if(ret != MPI_SUCCESS){
7848 *request = MPI_REQUEST_NULL;
7851 ret = errorCheck("AMPI_Ineighbor_allgather", comm, 1, recvcount, 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7852 if(ret != MPI_SUCCESS){
7853 *request = MPI_REQUEST_NULL;
7858 ampi *ptr = getAmpiInstance(comm);
7859 int rank_in_comm = ptr->getRank();
7861 if (ptr->getSize() == 1) {
7862 *request = ptr->postReq(new IReq(recvbuf,recvcount,recvtype,rank_in_comm,MPI_NBOR_TAG,comm,
7863 AMPI_REQ_COMPLETED));
7864 return copyDatatype(sendtype, sendcount, recvtype, recvcount, sendbuf, recvbuf);
7867 const vector<int>& neighbors = ptr->getNeighbors();
7868 int num_neighbors = neighbors.size();
7870 // use an IATAReq to non-block the caller and get a request ptr
7871 AmpiRequestList* reqs = getReqs();
7872 IATAReq *newreq = new IATAReq(num_neighbors);
7873 int extent = getDDT()->getExtent(recvtype) * recvcount;
7874 for (int j=0; j<num_neighbors; j++) {
7875 if(newreq->addReq(((char*)recvbuf)+(extent*j), recvcount, recvtype,
7876 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7877 CkAbort("MPI_Ineighbor_allgather: Error adding requests into IATAReq!");
7879 *request = ptr->postReq(newreq);
7881 for (int i=0; i<num_neighbors; i++) {
7882 ptr->send(MPI_NBOR_TAG, rank_in_comm, sendbuf, sendcount, sendtype, neighbors[i], comm);
7889 int AMPI_Neighbor_allgatherv(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
7890 void* recvbuf, const int *recvcounts, const int *displs,
7891 MPI_Datatype recvtype, MPI_Comm comm)
7893 AMPIAPI("AMPI_Neighbor_allgatherv");
7895 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7897 #if AMPI_ERROR_CHECKING
7898 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7899 CkAbort("MPI_Neighbor_allgatherv does not accept MPI_IN_PLACE!");
7900 if (getAmpiParent()->isInter(comm))
7901 CkAbort("MPI_Neighbor_allgatherv is not defined for Inter-communicators!");
7903 ret = errorCheck("AMPI_Neighbor_allgatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7904 if(ret != MPI_SUCCESS)
7906 ret = errorCheck("AMPI_Neighbor_allgatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7907 if(ret != MPI_SUCCESS)
7911 ampi *ptr = getAmpiInstance(comm);
7912 int rank_in_comm = ptr->getRank();
7914 if (ptr->getSize() == 1)
7915 return copyDatatype(sendtype, sendcount, recvtype, recvcounts[0], sendbuf, recvbuf);
7917 const vector<int>& neighbors = ptr->getNeighbors();
7918 int num_neighbors = neighbors.size();
7919 int extent = getDDT()->getExtent(recvtype);
7920 vector<MPI_Request> reqs(num_neighbors*2);
7921 for (int j=0; j<num_neighbors; j++) {
7922 ptr->irecv(((char*)recvbuf)+(extent*displs[j]), recvcounts[j], recvtype,
7923 neighbors[j], MPI_NBOR_TAG, comm, &reqs[j]);
7925 for (int i=0; i<num_neighbors; i++) {
7926 reqs[num_neighbors+i] = ptr->send(MPI_NBOR_TAG, rank_in_comm, sendbuf, sendcount,
7927 sendtype, neighbors[i], comm, 0, I_SEND);
7930 AMPI_Waitall(reqs.size(), &reqs[0], MPI_STATUSES_IGNORE);
7936 int AMPI_Ineighbor_allgatherv(const void* sendbuf, int sendcount, MPI_Datatype sendtype,
7937 void* recvbuf, const int* recvcounts, const int* displs,
7938 MPI_Datatype recvtype, MPI_Comm comm, MPI_Request *request)
7940 AMPIAPI("AMPI_Ineighbor_allgatherv");
7942 handle_MPI_BOTTOM((void*&)sendbuf, sendtype, recvbuf, recvtype);
7944 #if AMPI_ERROR_CHECKING
7945 if (sendbuf == MPI_IN_PLACE || recvbuf == MPI_IN_PLACE)
7946 CkAbort("MPI_Ineighbor_allgatherv does not accept MPI_IN_PLACE!");
7947 if (getAmpiParent()->isInter(comm))
7948 CkAbort("MPI_Ineighbor_allgatherv is not defined for Inter-communicators!");
7950 ret = errorCheck("AMPI_Ineighbor_allgatherv", comm, 1, sendcount, 1, sendtype, 1, 0, 0, 0, 0, sendbuf, 1);
7951 if(ret != MPI_SUCCESS){
7952 *request = MPI_REQUEST_NULL;
7955 ret = errorCheck("AMPI_Ineighbor_allgatherv", comm, 1, recvcounts[0], 1, recvtype, 1, 0, 0, 0, 0, recvbuf, 1);
7956 if(ret != MPI_SUCCESS){
7957 *request = MPI_REQUEST_NULL;
7962 ampi *ptr = getAmpiInstance(comm);
7963 int rank_in_comm = ptr->getRank();
7965 if (ptr->getSize() == 1) {
7966 *request = ptr->postReq(new IReq(recvbuf,recvcounts[0],recvtype,rank_in_comm,MPI_NBOR_TAG,comm,
7967 AMPI_REQ_COMPLETED));
7968 return copyDatatype(sendtype, sendcount, recvtype, recvcounts[0], sendbuf, recvbuf);
7971 const vector<int>& neighbors = ptr->getNeighbors();
7972 int num_neighbors = neighbors.size();
7974 // use an IATAReq to non-block the caller and get a request ptr
7975 AmpiRequestList* reqs = getReqs();
7976 IATAReq *newreq = new IATAReq(num_neighbors);
7977 int extent = getDDT()->getExtent(recvtype);
7978 for (int j=0; j<num_neighbors; j++) {
7979 if(newreq->addReq(((char*)recvbuf)+(extent*displs[j]), recvcounts[j], recvtype,
7980 neighbors[j], MPI_NBOR_TAG, comm)!=(j+1))
7981 CkAbort("MPI_Ineighbor_allgatherv: Error adding requests into IATAReq!");
7983 *request = ptr->postReq(newreq);
7985 for (int i=0; i<num_neighbors; i++) {
7986 ptr->send(MPI_NBOR_TAG, rank_in_comm, sendbuf, sendcount, sendtype, neighbors[i], comm);
7993 int AMPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm)
7995 AMPIAPI("AMPI_Comm_dup");
7997 ampi *ptr = getAmpiInstance(comm);
7998 int rank = ptr->getRank();
8000 AMPI_Topo_test(comm, &topol);
8001 if (topol == MPI_CART) {
8002 ptr->split(0, rank, newcomm, MPI_CART);
8004 // duplicate cartesian topology info
8005 ampiCommStruct &c = getAmpiParent()->getCart(comm);
8006 ampiCommStruct &newc = getAmpiParent()->getCart(*newcomm);
8007 newc.setndims(c.getndims());
8008 newc.setdims(c.getdims());
8009 newc.setperiods(c.getperiods());
8010 newc.setnbors(c.getnbors());
8012 else if (topol == MPI_GRAPH) {
8013 ptr->split(0, rank, newcomm, MPI_GRAPH);
8015 // duplicate graph topology info
8016 ampiCommStruct &g = getAmpiParent()->getGraph(comm);
8017 ampiCommStruct &newg = getAmpiParent()->getGraph(*newcomm);
8018 newg.setnvertices(g.getnvertices());
8019 newg.setindex(g.getindex());
8020 newg.setedges(g.getedges());
8023 if (getAmpiParent()->isInter(comm)) {
8024 ptr->split(0,rank,newcomm, MPI_INTER);
8027 ptr->split(0, rank, newcomm, MPI_UNDEFINED /*not MPI_CART*/);
8031 getAmpiInstance(comm)->barrier();
8034 ampiParent* pptr = getAmpiParent();
8036 PUParray(*(pptr->fromPUPer), (char *)newcomm, sizeof(int));
8039 else if(msgLogWrite && record_msglog(pptr->thisIndex)){
8040 PUParray(*(pptr->toPUPer), (char *)newcomm, sizeof(int));
8048 int AMPI_Comm_dup_with_info(MPI_Comm comm, MPI_Info info, MPI_Comm *dest)
8050 AMPIAPI("AMPI_Comm_dup_with_info");
8051 AMPI_Comm_dup(comm, dest);
8052 AMPI_Comm_set_info(*dest, info);
8057 int AMPI_Comm_split(MPI_Comm src, int color, int key, MPI_Comm *dest)
8059 AMPIAPI("AMPI_Comm_split");
8061 ampi *ptr = getAmpiInstance(src);
8062 if (getAmpiParent()->isInter(src)) {
8063 ptr->split(color, key, dest, MPI_INTER);
8065 else if (getAmpiParent()->isCart(src)) {
8066 ptr->split(color, key, dest, MPI_CART);
8068 else if (getAmpiParent()->isGraph(src)) {
8069 ptr->split(color, key, dest, MPI_GRAPH);
8072 ptr->split(color, key, dest, MPI_UNDEFINED);
8075 if (color == MPI_UNDEFINED) *dest = MPI_COMM_NULL;
8078 ampiParent* pptr = getAmpiParent();
8080 PUParray(*(pptr->fromPUPer), (char *)dest, sizeof(int));
8083 else if(msgLogWrite && record_msglog(pptr->thisIndex)){
8084 PUParray(*(pptr->toPUPer), (char *)dest, sizeof(int));
8092 int AMPI_Comm_split_type(MPI_Comm src, int split_type, int key, MPI_Info info, MPI_Comm *dest)
8094 AMPIAPI("AMPI_Comm_split_type");
8096 if (src == MPI_COMM_SELF && split_type == MPI_UNDEFINED) {
8097 *dest = MPI_COMM_NULL;
8101 int color = MPI_UNDEFINED;
8103 if (split_type == MPI_COMM_TYPE_SHARED || split_type == AMPI_COMM_TYPE_HOST) {
8104 color = CmiPhysicalNodeID(CkMyPe());
8106 else if (split_type == AMPI_COMM_TYPE_PROCESS) {
8109 else if (split_type == AMPI_COMM_TYPE_WTH) {
8113 return AMPI_Comm_split(src, color, key, dest);
8117 int AMPI_Comm_free(MPI_Comm *comm)
8119 AMPIAPI("AMPI_Comm_free");
8120 *comm = MPI_COMM_NULL;
8125 int AMPI_Comm_test_inter(MPI_Comm comm, int *flag){
8126 AMPIAPI("AMPI_Comm_test_inter");
8127 *flag = getAmpiParent()->isInter(comm);
8132 int AMPI_Comm_remote_size(MPI_Comm comm, int *size){
8133 AMPIAPI("AMPI_Comm_remote_size");
8134 *size = getAmpiParent()->getRemoteSize(comm);
8139 int AMPI_Comm_remote_group(MPI_Comm comm, MPI_Group *group){
8140 AMPIAPI("AMPI_Comm_remote_group");
8141 *group = getAmpiParent()->getRemoteGroup(comm);
8146 int AMPI_Intercomm_create(MPI_Comm localComm, int localLeader, MPI_Comm peerComm, int remoteLeader,
8147 int tag, MPI_Comm *newintercomm)
8149 AMPIAPI("AMPI_Intercomm_create");
8151 #if AMPI_ERROR_CHECKING
8152 if (getAmpiParent()->isInter(localComm) || getAmpiParent()->isInter(peerComm))
8153 return ampiErrhandler("AMPI_Intercomm_create", MPI_ERR_COMM);
8156 ampi *localPtr = getAmpiInstance(localComm);
8157 ampi *peerPtr = getAmpiInstance(peerComm);
8158 int rootIndex = localPtr->getIndexForRank(localLeader);
8159 int localSize, localRank;
8161 localSize = localPtr->getSize();
8162 localRank = localPtr->getRank();
8164 vector<int> remoteVec;
8166 if (localRank == localLeader) {
8169 vector<int> localVec;
8170 localVec = localPtr->getIndices();
8171 // local leader exchanges groupStruct with remote leader
8172 peerPtr->send(tag, peerPtr->getRank(), &localVec[0], localVec.size(), MPI_INT, remoteLeader, peerComm);
8173 peerPtr->probe(tag, remoteLeader, peerComm, &sts);
8174 AMPI_Get_count(&sts, MPI_INT, &remoteSize);
8175 remoteVec.resize(remoteSize);
8176 if (-1==peerPtr->recv(tag, remoteLeader, &remoteVec[0], remoteSize, MPI_INT, peerComm))
8177 CkAbort("AMPI> Error in MPI_Intercomm_create");
8179 if (remoteSize==0) {
8180 AMPI_DEBUG("AMPI> In MPI_Intercomm_create, creating an empty communicator\n");
8181 *newintercomm = MPI_COMM_NULL;
8186 localPtr->intercommCreate(remoteVec,rootIndex,localComm,newintercomm);
8192 int AMPI_Intercomm_merge(MPI_Comm intercomm, int high, MPI_Comm *newintracomm){
8193 AMPIAPI("AMPI_Intercomm_merge");
8195 #if AMPI_ERROR_CHECKING
8196 if (!getAmpiParent()->isInter(intercomm))
8197 return ampiErrhandler("AMPI_Intercomm_merge", MPI_ERR_COMM);
8200 ampi *ptr = getAmpiInstance(intercomm);
8201 int lroot, rroot, lrank, lhigh, rhigh, first;
8202 lroot = ptr->getIndexForRank(0);
8203 rroot = ptr->getIndexForRemoteRank(0);
8205 lrank = ptr->getRank();
8209 MPI_Request req = ptr->send(MPI_ATA_TAG, ptr->getRank(), &lhigh, 1, MPI_INT, 0, intercomm, 0, I_SEND);
8210 if(-1==ptr->recv(MPI_ATA_TAG,0,&rhigh,1,MPI_INT,intercomm))
8211 CkAbort("AMPI> Error in MPI_Intercomm_create");
8212 AMPI_Wait(&req, MPI_STATUS_IGNORE);
8214 if((lhigh && rhigh) || (!lhigh && !rhigh)){ // same value: smaller root goes first (first=1 if local goes first)
8215 first = (lroot < rroot);
8216 }else{ // different values, then high=false goes first
8217 first = (lhigh == false);
8221 ptr->intercommMerge(first, newintracomm);
8226 int AMPI_Abort(MPI_Comm comm, int errorcode)
8228 AMPIAPI("AMPI_Abort");
8229 CkAbort("AMPI: Application called MPI_Abort()!\n");
8234 int AMPI_Get_count(const MPI_Status *sts, MPI_Datatype dtype, int *count){
8235 AMPIAPI("AMPI_Get_count");
8236 CkDDT_DataType* dttype = getDDT()->getType(dtype);
8237 int itemsize = dttype->getSize() ;
8238 if (itemsize == 0) {
8241 *count = sts->MPI_LENGTH/itemsize;
8247 int AMPI_Type_lb(MPI_Datatype dtype, MPI_Aint* displacement){
8248 AMPIAPI("AMPI_Type_lb");
8249 *displacement = getDDT()->getLB(dtype);
8254 int AMPI_Type_ub(MPI_Datatype dtype, MPI_Aint* displacement){
8255 AMPIAPI("AMPI_Type_ub");
8256 *displacement = getDDT()->getUB(dtype);
8261 int AMPI_Get_address(const void* location, MPI_Aint *address){
8262 AMPIAPI("AMPI_Get_address");
8263 *address = (MPI_Aint)location;
8268 int AMPI_Address(void* location, MPI_Aint *address){
8269 AMPIAPI("AMPI_Address");
8270 return AMPI_Get_address(location, address);
8274 int AMPI_Status_set_elements(MPI_Status *sts, MPI_Datatype dtype, int count){
8275 AMPIAPI("AMPI_Status_set_elements");
8276 if(sts == MPI_STATUS_IGNORE || sts == MPI_STATUSES_IGNORE)
8278 CkDDT_DataType* dttype = getDDT()->getType(dtype);
8279 int basesize = dttype->getBaseSize();
8280 if(basesize==0) basesize = dttype->getSize();
8281 sts->MPI_LENGTH = basesize * count;
8286 int AMPI_Get_elements(const MPI_Status *sts, MPI_Datatype dtype, int *count){
8287 AMPIAPI("AMPI_Get_elements");
8288 if (dtype <= MPI_MAX_PRIMITIVE_TYPE) { // Is it a basic datatype?
8289 CkDDT_DataType* dttype = getDDT()->getType(dtype);
8290 int itemsize = dttype->getSize();
8291 *count = itemsize==0 ? 0 : sts->MPI_LENGTH/itemsize;
8293 CkDDT_DataType* dttype = getDDT()->getType(dtype);
8294 *count = dttype->getNumElements();
8300 int AMPI_Get_elements_x(const MPI_Status *sts, MPI_Datatype dtype, MPI_Count *count){
8301 AMPIAPI("AMPI_Get_elements_x");
8302 if (dtype <= MPI_MAX_PRIMITIVE_TYPE) { // Is it a basic datatype?
8303 CkDDT_DataType* dttype = getDDT()->getType(dtype);
8304 int itemsize = dttype->getSize();
8305 *count = itemsize==0 ? 0 : sts->MPI_LENGTH/itemsize;
8307 CkDDT_DataType* dttype = getDDT()->getType(dtype);
8308 *count = dttype->getNumElements();
8314 int AMPI_Pack(const void *inbuf, int incount, MPI_Datatype dtype, void *outbuf,
8315 int outsize, int *position, MPI_Comm comm)
8317 AMPIAPI("AMPI_Pack");
8318 CkDDT_DataType* dttype = getDDT()->getType(dtype) ;
8319 int itemsize = dttype->getSize();
8320 dttype->serialize((char*)inbuf, ((char*)outbuf)+(*position), incount, 1);
8321 *position += (itemsize*incount);
8326 int AMPI_Unpack(const void *inbuf, int insize, int *position, void *outbuf,
8327 int outcount, MPI_Datatype dtype, MPI_Comm comm)
8329 AMPIAPI("AMPI_Unpack");
8330 CkDDT_DataType* dttype = getDDT()->getType(dtype) ;
8331 int itemsize = dttype->getSize();
8332 dttype->serialize((char*)outbuf, ((char*)inbuf+(*position)), outcount, -1);
8333 *position += (itemsize*outcount);
8338 int AMPI_Pack_size(int incount,MPI_Datatype datatype,MPI_Comm comm,int *sz)
8340 AMPIAPI("AMPI_Pack_size");
8341 CkDDT_DataType* dttype = getDDT()->getType(datatype) ;
8342 *sz = incount*dttype->getSize() ;
8347 int AMPI_Get_version(int *version, int *subversion){
8348 AMPIAPI("AMPI_Get_version");
8349 *version = MPI_VERSION;
8350 *subversion = MPI_SUBVERSION;
8355 int AMPI_Get_library_version(char *version, int *resultlen){
8356 AMPIAPI("AMPI_Get_library_version");
8357 const char *ampiNameStr = "Adaptive MPI ";
8358 strncpy(version, ampiNameStr, MPI_MAX_LIBRARY_VERSION_STRING);
8359 strncat(version, CmiCommitID, MPI_MAX_LIBRARY_VERSION_STRING - strlen(version));
8360 *resultlen = strlen(version);
8365 int AMPI_Get_processor_name(char *name, int *resultlen){
8366 AMPIAPI("AMPI_Get_processor_name");
8367 ampiParent *ptr = getAmpiParent();
8368 sprintf(name,"AMPI_RANK[%d]_WTH[%d]",ptr->thisIndex,ptr->getMyPe());
8369 *resultlen = strlen(name);
8373 /* Error handling */
8374 #if defined(USE_STDARG)
8375 void error_handler(MPI_Comm *, int *, ...);
8377 void error_handler ( MPI_Comm *, int * );
8381 int AMPI_Comm_call_errhandler(MPI_Comm comm, int errorcode){
8382 AMPIAPI("AMPI_Comm_call_errhandler");
8387 int AMPI_Comm_create_errhandler(MPI_Comm_errhandler_fn *function, MPI_Errhandler *errhandler){
8388 AMPIAPI("AMPI_Comm_create_errhandler");
8393 int AMPI_Comm_set_errhandler(MPI_Comm comm, MPI_Errhandler errhandler){
8394 AMPIAPI("AMPI_Comm_set_errhandler");
8399 int AMPI_Comm_get_errhandler(MPI_Comm comm, MPI_Errhandler *errhandler){
8400 AMPIAPI("AMPI_Comm_get_errhandler");
8405 int AMPI_Comm_free_errhandler(MPI_Errhandler *errhandler){
8406 AMPIAPI("AMPI_Comm_free_errhandler");
8407 *errhandler = MPI_ERRHANDLER_NULL;
8412 int AMPI_Errhandler_create(MPI_Handler_function *function, MPI_Errhandler *errhandler){
8413 AMPIAPI("AMPI_Errhandler_create");
8414 return AMPI_Comm_create_errhandler(function, errhandler);
8418 int AMPI_Errhandler_set(MPI_Comm comm, MPI_Errhandler errhandler){
8419 AMPIAPI("AMPI_Errhandler_set");
8420 return AMPI_Comm_set_errhandler(comm, errhandler);
8424 int AMPI_Errhandler_get(MPI_Comm comm, MPI_Errhandler *errhandler){
8425 AMPIAPI("AMPI_Errhandler_get");
8426 return AMPI_Comm_get_errhandler(comm, errhandler);
8430 int AMPI_Errhandler_free(MPI_Errhandler *errhandler){
8431 AMPIAPI("AMPI_Errhandler_free");
8432 return AMPI_Comm_free_errhandler(errhandler);
8436 int AMPI_Add_error_code(int errorclass, int *errorcode){
8437 AMPIAPI("AMPI_Add_error_code");
8442 int AMPI_Add_error_class(int *errorclass){
8443 AMPIAPI("AMPI_Add_error_class");
8448 int AMPI_Add_error_string(int errorcode, const char *errorstring){
8449 AMPIAPI("AMPI_Add_error_string");
8454 int AMPI_Error_class(int errorcode, int *errorclass){
8455 AMPIAPI("AMPI_Error_class");
8456 *errorclass = errorcode;
8461 int AMPI_Error_string(int errorcode, char *errorstring, int *resultlen)
8463 AMPIAPI("AMPI_Error_string");
8467 r="MPI_SUCCESS: no errors"; break;
8468 case MPI_ERR_BUFFER:
8469 r="MPI_ERR_BUFFER: invalid buffer pointer"; break;
8471 r="MPI_ERR_COUNT: invalid count argument"; break;
8473 r="MPI_ERR_TYPE: invalid datatype"; break;
8475 r="MPI_ERR_TAG: invalid tag"; break;
8477 r="MPI_ERR_COMM: invalid communicator"; break;
8479 r="MPI_ERR_RANK: invalid rank"; break;
8480 case MPI_ERR_REQUEST:
8481 r="MPI_ERR_REQUEST: invalid request (handle)"; break;
8483 r="MPI_ERR_ROOT: invalid root"; break;
8485 r="MPI_ERR_GROUP: invalid group"; break;
8487 r="MPI_ERR_OP: invalid operation"; break;
8488 case MPI_ERR_TOPOLOGY:
8489 r="MPI_ERR_TOPOLOGY: invalid communicator topology"; break;
8491 r="MPI_ERR_DIMS: invalid dimension argument"; break;
8493 r="MPI_ERR_ARG: invalid argument of some other kind"; break;
8494 case MPI_ERR_TRUNCATE:
8495 r="MPI_ERR_TRUNCATE: message truncated in receive"; break;
8497 r="MPI_ERR_OTHER: known error not in this list"; break;
8498 case MPI_ERR_INTERN:
8499 r="MPI_ERR_INTERN: internal MPI (implementation) error"; break;
8500 case MPI_ERR_IN_STATUS:
8501 r="MPI_ERR_IN_STATUS: error code in status"; break;
8502 case MPI_ERR_PENDING:
8503 r="MPI_ERR_PENDING: pending request"; break;
8504 case MPI_ERR_ACCESS:
8505 r="MPI_ERR_ACCESS: invalid access mode"; break;
8507 r="MPI_ERR_AMODE: invalid amode argument"; break;
8508 case MPI_ERR_ASSERT:
8509 r="MPI_ERR_ASSERT: invalid assert argument"; break;
8510 case MPI_ERR_BAD_FILE:
8511 r="MPI_ERR_BAD_FILE: bad file"; break;
8513 r="MPI_ERR_BASE: invalid base"; break;
8514 case MPI_ERR_CONVERSION:
8515 r="MPI_ERR_CONVERSION: error in data conversion"; break;
8517 r="MPI_ERR_DISP: invalid displacement"; break;
8518 case MPI_ERR_DUP_DATAREP:
8519 r="MPI_ERR_DUP_DATAREP: error duplicating data representation"; break;
8520 case MPI_ERR_FILE_EXISTS:
8521 r="MPI_ERR_FILE_EXISTS: file exists already"; break;
8522 case MPI_ERR_FILE_IN_USE:
8523 r="MPI_ERR_FILE_IN_USE: file in use already"; break;
8525 r="MPI_ERR_FILE: invalid file"; break;
8526 case MPI_ERR_INFO_KEY:
8527 r="MPI_ERR_INFO_KEY: invalid key argument for info object"; break;
8528 case MPI_ERR_INFO_NOKEY:
8529 r="MPI_ERR_INFO_NOKEY: unknown key for info object"; break;
8530 case MPI_ERR_INFO_VALUE:
8531 r="MPI_ERR_INFO_VALUE: invalid value argument for info object"; break;
8533 r="MPI_ERR_INFO: invalid info object"; break;
8535 r="MPI_ERR_IO: input/output error"; break;
8536 case MPI_ERR_KEYVAL:
8537 r="MPI_ERR_KEYVAL: invalid keyval"; break;
8538 case MPI_ERR_LOCKTYPE:
8539 r="MPI_ERR_LOCKTYPE: invalid locktype argument"; break;
8541 r="MPI_ERR_NAME: invalid name argument"; break;
8542 case MPI_ERR_NO_MEM:
8543 r="MPI_ERR_NO_MEM: out of memory"; break;
8544 case MPI_ERR_NOT_SAME:
8545 r="MPI_ERR_NOT_SAME: objects are not identical"; break;
8546 case MPI_ERR_NO_SPACE:
8547 r="MPI_ERR_NO_SPACE: no space left on device"; break;
8548 case MPI_ERR_NO_SUCH_FILE:
8549 r="MPI_ERR_NO_SUCH_FILE: no such file or directory"; break;
8551 r="MPI_ERR_PORT: invalid port"; break;
8553 r="MPI_ERR_QUOTA: out of quota"; break;
8554 case MPI_ERR_READ_ONLY:
8555 r="MPI_ERR_READ_ONLY: file is read only"; break;
8556 case MPI_ERR_RMA_CONFLICT:
8557 r="MPI_ERR_RMA_CONFLICT: rma conflict during operation"; break;
8558 case MPI_ERR_RMA_SYNC:
8559 r="MPI_ERR_RMA_SYNC: error executing rma sync"; break;
8560 case MPI_ERR_SERVICE:
8561 r="MPI_ERR_SERVICE: unknown service name"; break;
8563 r="MPI_ERR_SIZE: invalid size argument"; break;
8565 r="MPI_ERR_SPAWN: error in spawning processes"; break;
8566 case MPI_ERR_UNSUPPORTED_DATAREP:
8567 r="MPI_ERR_UNSUPPORTED_DATAREP: data representation not supported"; break;
8568 case MPI_ERR_UNSUPPORTED_OPERATION:
8569 r="MPI_ERR_UNSUPPORTED_OPERATION: operation not supported"; break;
8571 r="MPI_ERR_WIN: invalid win argument"; break;
8574 *resultlen=strlen(r);
8575 strcpy(errorstring,r);
8576 return MPI_ERR_UNKNOWN;
8578 *resultlen=strlen(r);
8579 strcpy(errorstring,r);
8583 /* Group operations */
8585 int AMPI_Comm_group(MPI_Comm comm, MPI_Group *group)
8587 AMPIAPI("AMPI_Comm_Group");
8588 *group = getAmpiParent()->comm2group(comm);
8593 int AMPI_Group_union(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
8595 AMPIAPI("AMPI_Group_union");
8596 groupStruct vec1, vec2, newvec;
8597 ampiParent *ptr = getAmpiParent();
8598 vec1 = ptr->group2vec(group1);
8599 vec2 = ptr->group2vec(group2);
8600 newvec = unionOp(vec1,vec2);
8601 *newgroup = ptr->saveGroupStruct(newvec);
8606 int AMPI_Group_intersection(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
8608 AMPIAPI("AMPI_Group_intersection");
8609 groupStruct vec1, vec2, newvec;
8610 ampiParent *ptr = getAmpiParent();
8611 vec1 = ptr->group2vec(group1);
8612 vec2 = ptr->group2vec(group2);
8613 newvec = intersectOp(vec1,vec2);
8614 *newgroup = ptr->saveGroupStruct(newvec);
8619 int AMPI_Group_difference(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
8621 AMPIAPI("AMPI_Group_difference");
8622 groupStruct vec1, vec2, newvec;
8623 ampiParent *ptr = getAmpiParent();
8624 vec1 = ptr->group2vec(group1);
8625 vec2 = ptr->group2vec(group2);
8626 newvec = diffOp(vec1,vec2);
8627 *newgroup = ptr->saveGroupStruct(newvec);
8632 int AMPI_Group_size(MPI_Group group, int *size)
8634 AMPIAPI("AMPI_Group_size");
8635 *size = (getAmpiParent()->group2vec(group)).size();
8640 int AMPI_Group_rank(MPI_Group group, int *rank)
8642 AMPIAPI("AMPI_Group_rank");
8643 *rank = getAmpiParent()->getRank(group);
8648 int AMPI_Group_translate_ranks (MPI_Group group1, int n, const int *ranks1, MPI_Group group2, int *ranks2)
8650 AMPIAPI("AMPI_Group_translate_ranks");
8651 ampiParent *ptr = getAmpiParent();
8652 groupStruct vec1, vec2;
8653 vec1 = ptr->group2vec(group1);
8654 vec2 = ptr->group2vec(group2);
8655 translateRanksOp(n, vec1, ranks1, vec2, ranks2);
8660 int AMPI_Group_compare(MPI_Group group1,MPI_Group group2, int *result)
8662 AMPIAPI("AMPI_Group_compare");
8663 ampiParent *ptr = getAmpiParent();
8664 groupStruct vec1, vec2;
8665 vec1 = ptr->group2vec(group1);
8666 vec2 = ptr->group2vec(group2);
8667 *result = compareVecOp(vec1, vec2);
8672 int AMPI_Group_incl(MPI_Group group, int n, const int *ranks, MPI_Group *newgroup)
8674 AMPIAPI("AMPI_Group_incl");
8675 groupStruct vec, newvec;
8676 ampiParent *ptr = getAmpiParent();
8677 vec = ptr->group2vec(group);
8678 newvec = inclOp(n,ranks,vec);
8679 *newgroup = ptr->saveGroupStruct(newvec);
8684 int AMPI_Group_excl(MPI_Group group, int n, const int *ranks, MPI_Group *newgroup)
8686 AMPIAPI("AMPI_Group_excl");
8687 groupStruct vec, newvec;
8688 ampiParent *ptr = getAmpiParent();
8689 vec = ptr->group2vec(group);
8690 newvec = exclOp(n,ranks,vec);
8691 *newgroup = ptr->saveGroupStruct(newvec);
8696 int AMPI_Group_range_incl(MPI_Group group, int n, int ranges[][3], MPI_Group *newgroup)
8698 AMPIAPI("AMPI_Group_range_incl");
8699 groupStruct vec, newvec;
8701 ampiParent *ptr = getAmpiParent();
8702 vec = ptr->group2vec(group);
8703 newvec = rangeInclOp(n,ranges,vec,&ret);
8704 if(ret != MPI_SUCCESS){
8705 *newgroup = MPI_GROUP_EMPTY;
8706 return ampiErrhandler("AMPI_Group_range_incl", ret);
8708 *newgroup = ptr->saveGroupStruct(newvec);
8714 int AMPI_Group_range_excl(MPI_Group group, int n, int ranges[][3], MPI_Group *newgroup)
8716 AMPIAPI("AMPI_Group_range_excl");
8717 groupStruct vec, newvec;
8719 ampiParent *ptr = getAmpiParent();
8720 vec = ptr->group2vec(group);
8721 newvec = rangeExclOp(n,ranges,vec,&ret);
8722 if(ret != MPI_SUCCESS){
8723 *newgroup = MPI_GROUP_EMPTY;
8724 return ampiErrhandler("AMPI_Group_range_excl", ret);
8726 *newgroup = ptr->saveGroupStruct(newvec);
8732 int AMPI_Group_free(MPI_Group *group)
8734 AMPIAPI("AMPI_Group_free");
8739 int AMPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm* newcomm)
8741 AMPIAPI("AMPI_Comm_create");
8742 int rank_in_group, key, color, zero;
8743 MPI_Group group_of_comm;
8745 groupStruct vec = getAmpiParent()->group2vec(group);
8747 AMPI_DEBUG("AMPI> In MPI_Comm_create, creating an empty communicator");
8748 *newcomm = MPI_COMM_NULL;
8752 if(getAmpiParent()->isInter(comm)){
8753 /* inter-communicator: create a single new comm. */
8754 ampi *ptr = getAmpiInstance(comm);
8755 ptr->commCreate(vec, newcomm);
8759 /* intra-communicator: create comm's for disjoint subgroups,
8760 * by calculating (color, key) and splitting comm. */
8761 AMPI_Group_rank(group, &rank_in_group);
8762 if(rank_in_group == MPI_UNDEFINED){
8763 color = MPI_UNDEFINED;
8767 /* use rank in 'comm' of the 0th rank in 'group'
8768 * as identical 'color' of all ranks in 'group' */
8769 AMPI_Comm_group(comm, &group_of_comm);
8771 AMPI_Group_translate_ranks(group, 1, &zero, group_of_comm, &color);
8772 key = rank_in_group;
8774 return AMPI_Comm_split(comm, color, key, newcomm);
8780 int AMPI_Comm_set_name(MPI_Comm comm, const char *comm_name){
8781 AMPIAPI("AMPI_Comm_set_name");
8782 getAmpiInstance(comm)->setCommName(comm_name);
8787 int AMPI_Comm_get_name(MPI_Comm comm, char *comm_name, int *resultlen){
8788 AMPIAPI("AMPI_Comm_get_name");
8789 getAmpiInstance(comm)->getCommName(comm_name, resultlen);
8794 int AMPI_Comm_set_info(MPI_Comm comm, MPI_Info info){
8795 AMPIAPI("AMPI_Comm_set_info");
8796 /* FIXME: no-op implementation */
8801 int AMPI_Comm_get_info(MPI_Comm comm, MPI_Info *info){
8802 AMPIAPI("AMPI_Comm_get_info");
8803 /* FIXME: no-op implementation */
8804 *info = MPI_INFO_NULL;
8809 int AMPI_Comm_create_keyval(MPI_Comm_copy_attr_function *copy_fn,
8810 MPI_Comm_delete_attr_function *delete_fn,
8811 int *keyval, void* extra_state){
8812 AMPIAPI("AMPI_Comm_create_keyval");
8813 int ret = getAmpiParent()->createKeyval(copy_fn,delete_fn,keyval,extra_state);
8814 return ampiErrhandler("AMPI_Comm_create_keyval", ret);
8818 int AMPI_Comm_free_keyval(int *keyval){
8819 AMPIAPI("AMPI_Comm_free_keyval");
8820 int ret = getAmpiParent()->freeKeyval(keyval);
8821 return ampiErrhandler("AMPI_Comm_free_keyval", ret);
8825 int AMPI_Comm_set_attr(MPI_Comm comm, int keyval, void* attribute_val){
8826 AMPIAPI("AMPI_Comm_set_attr");
8827 int ret = getAmpiParent()->setCommAttr(comm,keyval,attribute_val);
8828 return ampiErrhandler("AMPI_Comm_set_attr", ret);
8832 int AMPI_Comm_get_attr(MPI_Comm comm, int keyval, void *attribute_val, int *flag){
8833 AMPIAPI("AMPI_Comm_get_attr");
8834 int ret = getAmpiParent()->getCommAttr(comm,keyval,attribute_val,flag);
8835 return ampiErrhandler("AMPI_Comm_get_attr", ret);
8839 int AMPI_Comm_delete_attr(MPI_Comm comm, int keyval){
8840 AMPIAPI("AMPI_Comm_delete_attr");
8841 int ret = getAmpiParent()->deleteCommAttr(comm,keyval);
8842 return ampiErrhandler("AMPI_Comm_delete_attr", ret);
8846 int AMPI_Keyval_create(MPI_Copy_function *copy_fn, MPI_Delete_function *delete_fn,
8847 int *keyval, void* extra_state){
8848 AMPIAPI("AMPI_Keyval_create");
8849 return AMPI_Comm_create_keyval(copy_fn, delete_fn, keyval, extra_state);
8853 int AMPI_Keyval_free(int *keyval){
8854 AMPIAPI("AMPI_Keyval_free");
8855 return AMPI_Comm_free_keyval(keyval);
8859 int AMPI_Attr_put(MPI_Comm comm, int keyval, void* attribute_val){
8860 AMPIAPI("AMPI_Attr_put");
8861 return AMPI_Comm_set_attr(comm, keyval, attribute_val);
8865 int AMPI_Attr_get(MPI_Comm comm, int keyval, void *attribute_val, int *flag){
8866 AMPIAPI("AMPI_Attr_get");
8867 return AMPI_Comm_get_attr(comm, keyval, attribute_val, flag);
8871 int AMPI_Attr_delete(MPI_Comm comm, int keyval){
8872 AMPIAPI("AMPI_Attr_delete");
8873 return AMPI_Comm_delete_attr(comm, keyval);
8877 int AMPI_Cart_map(MPI_Comm comm, int ndims, const int *dims, const int *periods, int *newrank) {
8878 AMPIAPI("AMPI_Cart_map");
8880 ampi* ptr = getAmpiInstance(comm);
8887 for (int i=1; i<ndims; i++) {
8892 int rank = ptr->getRank();
8893 if (rank < nranks) {
8896 *newrank = MPI_UNDEFINED;
8902 int AMPI_Graph_map(MPI_Comm comm, int nnodes, const int *index, const int *edges, int *newrank) {
8903 AMPIAPI("AMPI_Graph_map");
8905 ampi* ptr = getAmpiInstance(comm);
8907 if (ptr->getRank() < nnodes) {
8908 *newrank = ptr->getRank();
8910 *newrank = MPI_UNDEFINED;
8916 int AMPI_Cart_create(MPI_Comm comm_old, int ndims, const int *dims, const int *periods,
8917 int reorder, MPI_Comm *comm_cart) {
8919 AMPIAPI("AMPI_Cart_create");
8921 /* Create new cartesian communicator. No attention is being paid to mapping
8922 virtual processes to processors, which ideally should be handled by the
8923 load balancer with input from virtual topology information.
8925 No reorder done here. reorder input is ignored, but still stored in the
8926 communicator with other VT info.
8930 AMPI_Cart_map(comm_old, ndims, dims, periods, &newrank);//no change in rank
8932 ampiParent *ptr = getAmpiParent();
8933 groupStruct vec = ptr->group2vec(ptr->comm2group(comm_old));
8934 *comm_cart = getAmpiInstance(comm_old)->cartCreate(vec, ndims, dims);
8936 if (*comm_cart != MPI_COMM_NULL) {
8937 ampiCommStruct &c = ptr->getCart(*comm_cart);
8940 vector<int> dimsv(ndims), periodsv(ndims);
8941 for (int i = 0; i < ndims; i++) {
8943 periodsv[i] = periods[i];
8946 c.setperiods(periodsv);
8949 getAmpiInstance(*comm_cart)->findNeighbors(*comm_cart, newrank, nborsv);
8957 int AMPI_Graph_create(MPI_Comm comm_old, int nnodes, const int *index, const int *edges,
8958 int reorder, MPI_Comm *comm_graph) {
8959 AMPIAPI("AMPI_Graph_create");
8962 *comm_graph = MPI_COMM_NULL;
8966 /* No mapping done */
8968 AMPI_Graph_map(comm_old, nnodes, index, edges, &newrank);
8970 ampiParent *ptr = getAmpiParent();
8971 groupStruct vec = ptr->group2vec(ptr->comm2group(comm_old));
8972 getAmpiInstance(comm_old)->graphCreate(vec, comm_graph);
8974 ampiCommStruct &c = ptr->getGraph(*comm_graph);
8975 c.setnvertices(nnodes);
8981 for (i = 0; i < nnodes; i++)
8982 index_.push_back(index[i]);
8986 for (i = 0; i < index[nnodes - 1]; i++)
8987 edges_.push_back(edges[i]);
8992 getAmpiInstance(*comm_graph)->findNeighbors(*comm_graph, newrank, nborsv);
8999 int AMPI_Topo_test(MPI_Comm comm, int *status) {
9000 AMPIAPI("AMPI_Topo_test");
9002 ampiParent *ptr = getAmpiParent();
9004 if (ptr->isCart(comm))
9006 else if (ptr->isGraph(comm))
9007 *status = MPI_GRAPH;
9008 else *status = MPI_UNDEFINED;
9014 int AMPI_Cartdim_get(MPI_Comm comm, int *ndims) {
9015 AMPIAPI("AMPI_Cartdim_get");
9017 #if AMPI_ERROR_CHECKING
9018 if (!getAmpiParent()->isCart(comm))
9019 return ampiErrhandler("AMPI_Cartdim_get", MPI_ERR_TOPOLOGY);
9022 *ndims = getAmpiParent()->getCart(comm).getndims();
9028 int AMPI_Cart_get(MPI_Comm comm, int maxdims, int *dims, int *periods, int *coords){
9031 AMPIAPI("AMPI_Cart_get");
9033 #if AMPI_ERROR_CHECKING
9034 if (!getAmpiParent()->isCart(comm))
9035 return ampiErrhandler("AMPI_Cart_get", MPI_ERR_TOPOLOGY);
9038 ampiCommStruct &c = getAmpiParent()->getCart(comm);
9039 ndims = c.getndims();
9040 int rank = getAmpiInstance(comm)->getRank();
9042 const vector<int> &dims_ = c.getdims();
9043 const vector<int> &periods_ = c.getperiods();
9045 for (i = 0; i < maxdims; i++) {
9047 periods[i] = periods_[i];
9050 for (i = ndims - 1; i >= 0; i--) {
9052 coords[i] = rank % dims_[i];
9053 rank = (int) (rank / dims_[i]);
9060 int AMPI_Cart_rank(MPI_Comm comm, const int *coords, int *rank) {
9061 AMPIAPI("AMPI_Cart_rank");
9063 #if AMPI_ERROR_CHECKING
9064 if (!getAmpiParent()->isCart(comm))
9065 return ampiErrhandler("AMPI_Cart_rank", MPI_ERR_TOPOLOGY);
9068 ampiCommStruct &c = getAmpiParent()->getCart(comm);
9069 int ndims = c.getndims();
9070 const vector<int> &dims = c.getdims();
9071 const vector<int> &periods = c.getperiods();
9073 //create a copy of coords since we are not allowed to modify it
9074 vector<int> ncoords(coords, coords+ndims);
9079 for (int i = ndims - 1; i >= 0; i--) {
9080 if ((ncoords[i] < 0) || (ncoords[i] >= dims[i])) {
9081 if (periods[i] != 0) {
9082 if (ncoords[i] > 0) {
9083 ncoords[i] %= dims[i];
9085 while (ncoords[i] < 0) ncoords[i]+=dims[i];
9089 r += prod * ncoords[i];
9099 int AMPI_Cart_coords(MPI_Comm comm, int rank, int maxdims, int *coords) {
9100 AMPIAPI("AMPI_Cart_coords");
9102 #if AMPI_ERROR_CHECKING
9103 if (!getAmpiParent()->isCart(comm))
9104 return ampiErrhandler("AMPI_Cart_coorts", MPI_ERR_TOPOLOGY);
9107 ampiCommStruct &c = getAmpiParent()->getCart(comm);
9108 int ndims = c.getndims();
9109 const vector<int> &dims = c.getdims();
9111 for (int i = ndims - 1; i >= 0; i--) {
9113 coords[i] = rank % dims[i];
9114 rank = (int) (rank / dims[i]);
9120 // Offset coords[direction] by displacement, and set the rank that
9122 static void cart_clamp_coord(MPI_Comm comm, const vector<int> &dims,
9123 const vector<int> &periodicity, int *coords,
9124 int direction, int displacement, int *rank_out)
9126 int base_coord = coords[direction];
9127 coords[direction] += displacement;
9129 if (periodicity[direction] != 0) {
9130 while (coords[direction] < 0)
9131 coords[direction] += dims[direction];
9132 while (coords[direction] >= dims[direction])
9133 coords[direction] -= dims[direction];
9136 if (coords[direction]<0 || coords[direction]>= dims[direction])
9137 *rank_out = MPI_PROC_NULL;
9139 AMPI_Cart_rank(comm, coords, rank_out);
9141 coords[direction] = base_coord;
9145 int AMPI_Cart_shift(MPI_Comm comm, int direction, int disp,
9146 int *rank_source, int *rank_dest) {
9147 AMPIAPI("AMPI_Cart_shift");
9149 #if AMPI_ERROR_CHECKING
9150 if (!getAmpiParent()->isCart(comm))
9151 return ampiErrhandler("AMPI_Cart_shift", MPI_ERR_TOPOLOGY);
9154 ampiCommStruct &c = getAmpiParent()->getCart(comm);
9155 int ndims = c.getndims();
9157 #if AMPI_ERROR_CHECKING
9158 if ((direction < 0) || (direction >= ndims))
9159 return ampiErrhandler("AMPI_Cart_shift", MPI_ERR_DIMS);
9162 const vector<int> &dims = c.getdims();
9163 const vector<int> &periods = c.getperiods();
9164 vector<int> coords(ndims);
9166 int mype = getAmpiInstance(comm)->getRank();
9167 AMPI_Cart_coords(comm, mype, ndims, &coords[0]);
9169 cart_clamp_coord(comm, dims, periods, &coords[0], direction, disp, rank_dest);
9170 cart_clamp_coord(comm, dims, periods, &coords[0], direction, -disp, rank_source);
9176 int AMPI_Graphdims_get(MPI_Comm comm, int *nnodes, int *nedges) {
9177 AMPIAPI("AMPI_Graphdim_get");
9179 ampiCommStruct &c = getAmpiParent()->getGraph(comm);
9180 *nnodes = c.getnvertices();
9181 const vector<int> &index = c.getindex();
9182 *nedges = index[(*nnodes) - 1];
9188 int AMPI_Graph_get(MPI_Comm comm, int maxindex, int maxedges, int *index, int *edges) {
9189 AMPIAPI("AMPI_Graph_get");
9191 #if AMPI_ERROR_CHECKING
9192 if (!getAmpiParent()->isGraph(comm))
9193 return ampiErrhandler("AMPI_Graph_get", MPI_ERR_TOPOLOGY);
9196 ampiCommStruct &c = getAmpiParent()->getGraph(comm);
9197 const vector<int> &index_ = c.getindex();
9198 const vector<int> &edges_ = c.getedges();
9200 if (maxindex > index_.size())
9201 maxindex = index_.size();
9204 for (i = 0; i < maxindex; i++)
9205 index[i] = index_[i];
9207 for (i = 0; i < maxedges; i++)
9208 edges[i] = edges_[i];
9214 int AMPI_Graph_neighbors_count(MPI_Comm comm, int rank, int *nneighbors) {
9215 AMPIAPI("AMPI_Graph_neighbors_count");
9217 #if AMPI_ERROR_CHECKING
9218 if (!getAmpiParent()->isGraph(comm))
9219 return ampiErrhandler("AMPI_Graph_neighbors_count", MPI_ERR_TOPOLOGY);
9222 ampiCommStruct &c = getAmpiParent()->getGraph(comm);
9223 const vector<int> &index = c.getindex();
9225 #if AMPI_ERROR_CHECKING
9226 if ((rank >= index.size()) || (rank < 0))
9227 return ampiErrhandler("AMPI_Graph_neighbors_count", MPI_ERR_RANK);
9231 *nneighbors = index[rank];
9233 *nneighbors = index[rank] - index[rank - 1];
9239 int AMPI_Graph_neighbors(MPI_Comm comm, int rank, int maxneighbors, int *neighbors) {
9240 AMPIAPI("AMPI_Graph_neighbors");
9242 #if AMPI_ERROR_CHECKING
9243 if (!getAmpiParent()->isGraph(comm))
9244 return ampiErrhandler("AMPI_Graph_neighbors", MPI_ERR_TOPOLOGY);
9247 ampiCommStruct &c = getAmpiParent()->getGraph(comm);
9248 const vector<int> &index = c.getindex();
9249 const vector<int> &edges = c.getedges();
9251 int numneighbors = (rank == 0) ? index[rank] : index[rank] - index[rank - 1];
9252 if (maxneighbors > numneighbors)
9253 maxneighbors = numneighbors;
9255 #if AMPI_ERROR_CHECKING
9256 if (maxneighbors < 0)
9257 return ampiErrhandler("AMPI_Graph_neighbors", MPI_ERR_ARG);
9258 if ((rank >= index.size()) || (rank < 0))
9259 return ampiErrhandler("AMPI_Graph_neighbors", MPI_ERR_RANK);
9263 for (int i = 0; i < maxneighbors; i++)
9264 neighbors[i] = edges[i];
9266 for (int i = 0; i < maxneighbors; i++)
9267 neighbors[i] = edges[index[rank - 1] + i];
9272 /* Used by MPI_Cart_create & MPI_Graph_create */
9273 void ampi::findNeighbors(MPI_Comm comm, int rank, vector<int>& neighbors) const {
9274 int max_neighbors = 0;
9275 ampiParent *ptr = getAmpiParent();
9276 if (ptr->isGraph(comm)) {
9277 AMPI_Graph_neighbors_count(comm, rank, &max_neighbors);
9278 neighbors.resize(max_neighbors);
9279 AMPI_Graph_neighbors(comm, rank, max_neighbors, &neighbors[0]);
9281 else if (ptr->isCart(comm)) {
9283 AMPI_Cartdim_get(comm, &num_dims);
9284 max_neighbors = 2*num_dims;
9285 for (int i=0; i<max_neighbors; i++) {
9287 AMPI_Cart_shift(comm, i/2, (i%2==0)?1:-1, &src, &dest);
9288 if (dest != MPI_PROC_NULL)
9289 neighbors.push_back(dest);
9294 /* Factorization code by Orion. Idea thrashed out by Orion and Prakash */
9297 Return the integer "d'th root of n"-- the largest
9301 int integerRoot(int n,int d) {
9302 double epsilon=0.001; /* prevents roundoff in "floor" */
9303 return (int)floor(pow(n+epsilon,1.0/d));
9307 Factorize "n" into "d" factors, stored in "dims[0..d-1]".
9308 All the factors must be greater than or equal to m.
9309 The factors are chosen so that they are all as near together
9310 as possible (technically, chosen so that the increasing-size
9311 ordering is lexicagraphically as large as possible).
9314 bool factors(int n, int d, int *dims, int m) {
9317 if (n>=m) { /* n is an acceptable factor */
9322 else { /* induction case */
9323 int k_up=integerRoot(n,d);
9324 for (int k=k_up;k>=m;k--) {
9325 if (n%k==0) { /* k divides n-- try it as a factor */
9327 if (factors(n/k,d-1,&dims[1],k))
9332 /* If we fall out here, there were no factors available */
9337 int AMPI_Dims_create(int nnodes, int ndims, int *dims) {
9338 AMPIAPI("AMPI_Dims_create");
9345 for (i = 0; i < ndims; i++) {
9347 if (n % dims[i] != 0) {
9348 return ampiErrhandler("AMPI_Dims_create", MPI_ERR_DIMS);
9357 vector<int> pdims(d);
9359 if (!factors(n, d, &pdims[0], 1))
9360 CkAbort("MPI_Dims_create: factorization failed!\n");
9363 for (i = 0; i < ndims; i++) {
9370 // Sort the factors in non-increasing order.
9371 // Bubble sort because dims is always small.
9372 for (int i=0; i<d-1; i++) {
9373 for (int j=i+1; j<d; j++) {
9374 if (dims[j] > dims[i]) {
9386 /* Implemented with call to MPI_Comm_Split. Color and key are single integer
9387 encodings of the lost and preserved dimensions, respectively,
9391 int AMPI_Cart_sub(MPI_Comm comm, const int *remain_dims, MPI_Comm *newcomm) {
9392 AMPIAPI("AMPI_Cart_sub");
9395 int color = 1, key = 1;
9397 #if AMPI_ERROR_CHECKING
9398 if (!getAmpiParent()->isCart(comm))
9399 return ampiErrhandler("AMPI_Cart_sub", MPI_ERR_TOPOLOGY);
9402 int rank = getAmpiInstance(comm)->getRank();
9403 ampiCommStruct &c = getAmpiParent()->getCart(comm);
9404 ndims = c.getndims();
9405 const vector<int> &dims = c.getdims();
9406 int num_remain_dims = 0;
9408 vector<int> coords(ndims);
9409 AMPI_Cart_coords(comm, rank, ndims, &coords[0]);
9411 for (i = 0; i < ndims; i++) {
9412 if (remain_dims[i]) {
9413 /* key single integer encoding*/
9414 key = key * dims[i] + coords[i];
9419 color = color * dims[i] + coords[i];
9423 if (num_remain_dims == 0) {
9424 *newcomm = getAmpiInstance(comm)->cartCreate0D();
9428 getAmpiInstance(comm)->split(color, key, newcomm, MPI_CART);
9430 ampiCommStruct &newc = getAmpiParent()->getCart(*newcomm);
9431 newc.setndims(num_remain_dims);
9433 const vector<int> &periods = c.getperiods();
9434 vector<int> periodsv;
9436 for (i = 0; i < ndims; i++) {
9437 if (remain_dims[i]) {
9438 dimsv.push_back(dims[i]);
9439 periodsv.push_back(periods[i]);
9442 newc.setdims(dimsv);
9443 newc.setperiods(periodsv);
9446 getAmpiInstance(*newcomm)->findNeighbors(*newcomm, getAmpiParent()->getRank(*newcomm), nborsv);
9447 newc.setnbors(nborsv);
9453 int AMPI_Type_get_envelope(MPI_Datatype datatype, int *ni, int *na, int *nd, int *combiner){
9454 AMPIAPI("AMPI_Type_get_envelope");
9455 return getDDT()->getEnvelope(datatype,ni,na,nd,combiner);
9459 int AMPI_Type_get_contents(MPI_Datatype datatype, int ni, int na, int nd, int i[],
9460 MPI_Aint a[], MPI_Datatype d[]){
9461 AMPIAPI("AMPI_Type_get_contents");
9462 return getDDT()->getContents(datatype,ni,na,nd,i,a,d);
9466 int AMPI_Pcontrol(const int level, ...) {
9467 //AMPIAPI("AMPI_Pcontrol");
9471 /******** AMPI Extensions to the MPI standard *********/
9474 int AMPI_Migrate(MPI_Info hints)
9476 AMPIAPI("AMPI_Migrate");
9478 char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
9480 AMPI_Info_get_nkeys(hints, &nkeys);
9482 for (int i=0; i<nkeys; i++) {
9483 AMPI_Info_get_nthkey(hints, i, key);
9484 AMPI_Info_get(hints, key, MPI_MAX_INFO_VAL, value, &exists);
9488 else if (strncmp(key, "ampi_load_balance", MPI_MAX_INFO_KEY) == 0) {
9490 if (strncmp(value, "sync", MPI_MAX_INFO_VAL) == 0) {
9493 else if (strncmp(value, "async", MPI_MAX_INFO_VAL) == 0) {
9494 TCHARM_Async_Migrate();
9496 else if (strncmp(value, "false", MPI_MAX_INFO_VAL) == 0) {
9500 CkPrintf("WARNING: Unknown MPI_Info value (%s) given to AMPI_Migrate for key: %s\n", value, key);
9503 else if (strncmp(key, "ampi_checkpoint", MPI_MAX_INFO_KEY) == 0) {
9505 if (strncmp(value, "true", MPI_MAX_INFO_VAL) == 0) {
9506 CkAbort("AMPI> Error: Value \"true\" is not supported for AMPI_Migrate key \"ampi_checkpoint\"!\n");
9508 else if (strncmp(value, "to_file=", strlen("to_file=")) == 0) {
9509 int offset = strlen("to_file=");
9510 int restart_dir_name_len = 0;
9511 AMPI_Info_get_valuelen(hints, key, &restart_dir_name_len, &exists);
9512 if (restart_dir_name_len > offset) {
9513 value[restart_dir_name_len] = '\0';
9516 CkAbort("AMPI> Error: No checkpoint directory name given to AMPI_Migrate\n");
9518 getAmpiInstance(MPI_COMM_WORLD)->barrier();
9519 getAmpiParent()->startCheckpoint(&value[offset]);
9521 else if (strncmp(value, "in_memory", MPI_MAX_INFO_VAL) == 0) {
9522 #if CMK_MEM_CHECKPOINT
9523 getAmpiInstance(MPI_COMM_WORLD)->barrier();
9524 getAmpiParent()->startCheckpoint("");
9526 CkPrintf("AMPI> Error: In-memory checkpoint/restart is not enabled!\n");
9527 CkAbort("AMPI> Error: Recompile Charm++/AMPI with CMK_MEM_CHECKPOINT.\n");
9530 else if (strncmp(value, "message_logging", MPI_MAX_INFO_VAL) == 0) {
9531 #if CMK_MESSAGE_LOGGING
9534 CkPrintf("AMPI> Error: Message logging is not enabled!\n");
9535 CkAbort("AMPI> Error: Recompile Charm++/AMPI with CMK_MESSAGE_LOGGING.\n");
9538 else if (strncmp(value, "false", MPI_MAX_INFO_VAL) == 0) {
9542 CkPrintf("WARNING: Unknown MPI_Info value (%s) given to AMPI_Migrate for key: %s\n", value, key);
9546 CkPrintf("WARNING: Unknown MPI_Info key given to AMPI_Migrate: %s\n", key);
9550 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
9551 ampi *currentAmpi = getAmpiInstance(MPI_COMM_WORLD);
9552 CpvAccess(_currentObj) = currentAmpi;
9555 #if CMK_BIGSIM_CHARM
9556 TRACE_BG_ADD_TAG("AMPI_MIGRATE");
9562 int AMPI_Evacuate(void)
9564 //AMPIAPI("AMPI_Evacuate");
9570 int AMPI_Migrate_to_pe(int dest)
9572 AMPIAPI("AMPI_Migrate_to_pe");
9573 TCHARM_Migrate_to(dest);
9574 #if CMK_BIGSIM_CHARM
9575 TRACE_BG_ADD_TAG("AMPI_MIGRATE_TO_PE");
9581 int AMPI_Set_migratable(int mig)
9583 AMPIAPI("AMPI_Set_migratable");
9585 getAmpiParent()->setMigratable((mig!=0));
9587 CkPrintf("WARNING: MPI_Set_migratable is not supported in this build of Charm++/AMPI.\n");
9593 int AMPI_Load_start_measure(void)
9595 AMPIAPI("AMPI_Load_start_measure");
9596 LBTurnInstrumentOn();
9601 int AMPI_Load_stop_measure(void)
9603 AMPIAPI("AMPI_Load_stop_measure");
9604 LBTurnInstrumentOff();
9609 int AMPI_Load_reset_measure(void)
9611 AMPIAPI("AMPI_Load_reset_measure");
9617 int AMPI_Load_set_value(double value)
9619 AMPIAPI("AMPI_Load_set_value");
9620 ampiParent *ptr = getAmpiParent();
9621 ptr->setObjTime(value);
9625 void _registerampif(void) {
9630 int AMPI_Register_main(MPI_MainFn mainFn,const char *name)
9632 AMPIAPI("AMPI_Register_main");
9633 if (TCHARM_Element()==0)
9634 { // I'm responsible for building the TCHARM threads:
9635 ampiCreateMain(mainFn,name,strlen(name));
9641 void FTN_NAME(MPI_REGISTER_MAIN,mpi_register_main)
9642 (MPI_MainFn mainFn,const char *name,int nameLen)
9644 AMPIAPI("AMPI_register_main");
9645 if (TCHARM_Element()==0)
9646 { // I'm responsible for building the TCHARM threads:
9647 ampiCreateMain(mainFn,name,nameLen);
9652 int AMPI_Register_pup(MPI_PupFn fn, void *data, int *idx)
9654 AMPIAPI("AMPI_Register_pup");
9655 *idx = TCHARM_Register(data, fn);
9660 int AMPI_Register_about_to_migrate(MPI_MigrateFn fn)
9662 AMPIAPI("AMPI_Register_about_to_migrate");
9663 ampiParent *thisParent = getAmpiParent();
9664 thisParent->setUserAboutToMigrateFn(fn);
9669 int AMPI_Register_just_migrated(MPI_MigrateFn fn)
9671 AMPIAPI("AMPI_Register_just_migrated");
9672 ampiParent *thisParent = getAmpiParent();
9673 thisParent->setUserJustMigratedFn(fn);
9678 int AMPI_Get_pup_data(int idx, void *data)
9680 AMPIAPI("AMPI_Get_pup_data");
9681 data = TCHARM_Get_userdata(idx);
9686 int AMPI_Type_is_contiguous(MPI_Datatype datatype, int *flag)
9688 AMPIAPI("AMPI_Type_is_contiguous");
9689 *flag = getDDT()->isContig(datatype);
9694 int AMPI_Print(const char *str)
9696 AMPIAPI("AMPI_Print");
9697 ampiParent *ptr = getAmpiParent();
9698 CkPrintf("[%d] %s\n", ptr->thisIndex, str);
9703 int AMPI_Suspend(void)
9705 AMPIAPI("AMPI_Suspend");
9706 getAmpiParent()->block();
9711 int AMPI_Yield(void)
9713 AMPIAPI("AMPI_Yield");
9714 getAmpiParent()->yield();
9719 int AMPI_Resume(int dest, MPI_Comm comm)
9721 AMPIAPI("AMPI_Resume");
9722 getAmpiInstance(comm)->getProxy()[dest].unblock();
9727 int AMPI_System(const char *cmd)
9729 return TCHARM_System(cmd);
9733 int AMPI_Trace_begin(void)
9740 int AMPI_Trace_end(void)
9746 int AMPI_Install_idle_timer(void)
9749 beginHandle = CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)BeginIdle,NULL);
9750 endHandle = CcdCallOnConditionKeep(CcdPROCESSOR_END_IDLE,(CcdVoidFn)EndIdle,NULL);
9755 int AMPI_Uninstall_idle_timer(void)
9758 CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,beginHandle);
9759 CcdCancelCallOnConditionKeep(CcdPROCESSOR_BEGIN_BUSY,endHandle);
9764 #if CMK_BIGSIM_CHARM
9765 extern "C" void startCFnCall(void *param,void *msg)
9768 ampi *ptr = (ampi*)param;
9769 ampi::bcastraw(NULL, 0, ptr->getProxy());
9770 delete (CkReductionMsg*)msg;
9774 int AMPI_Set_start_event(MPI_Comm comm)
9776 AMPIAPI("AMPI_Set_start_event");
9777 CkAssert(comm == MPI_COMM_WORLD);
9779 ampi *ptr = getAmpiInstance(comm);
9781 CkDDT_DataType *ddt_type = ptr->getDDT()->getType(MPI_INT);
9783 CkReductionMsg *msg=makeRednMsg(ddt_type, NULL, 0, MPI_INT, ptr->getRank(), MPI_SUM);
9784 if (CkMyPe() == 0) {
9785 CkCallback allreduceCB(startCFnCall, ptr);
9786 msg->setCallback(allreduceCB);
9788 ptr->contribute(msg);
9790 /*HACK: Use recv() to block until the reduction data comes back*/
9791 if(-1==ptr->recv(MPI_BCAST_TAG, -1, NULL, 0, MPI_INT, MPI_COMM_WORLD))
9792 CkAbort("AMPI> MPI_Allreduce called with different values on different processors!");
9798 int AMPI_Set_end_event(void)
9800 AMPIAPI("AMPI_Set_end_event");
9803 #endif // CMK_BIGSIM_CHARM
9808 comm = MPI_COMM_SELF;
9810 AMPI_Comm_rank(comm, &src);
9811 buf = getAmpiInstance(comm);
9814 bool GPUReq::test(void)
9819 int GPUReq::wait(MPI_Status *sts)
9822 while (!statusIreq) {
9823 getAmpiParent()->block();
9828 void GPUReq::receive(ampi *ptr, AmpiMsg *msg)
9830 CkAbort("GPUReq::receive should never be called");
9833 void GPUReq::setComplete()
9838 class workRequestQueue;
9839 extern workRequestQueue *wrQueue;
9840 void enqueue(workRequestQueue *q, workRequest *wr);
9841 extern "C++" void setWRCallback(workRequest *wr, void *cb);
9843 void AMPI_GPU_complete(void *request, void* dummy)
9845 GPUReq *req = static_cast<GPUReq *>(request);
9847 ampi *ptr = static_cast<ampi *>(req->buf);
9852 int AMPI_GPU_Iinvoke(workRequest *to_call, MPI_Request *request)
9854 AMPIAPI("AMPI_GPU_Iinvoke");
9856 *request = ptr->postReq(new GPUReq());
9858 // A callback that completes the corresponding request
9859 CkCallback *cb = new CkCallback(&I_GPU_complete, newreq);
9860 setWRCallback(to_call, cb);
9862 enqueue(wrQueue, to_call);
9866 int AMPI_GPU_Invoke(workRequest *to_call)
9868 AMPIAPI("AMPI_GPU_Invoke");
9871 AMPI_GPU_Iinvoke(to_call, &req);
9872 AMPI_Wait(&req, MPI_STATUS_IGNORE);
9878 #include "ampi.def.h"