📄 mtest.c
字号:
/* The while loop allows us to skip communicators that are too small. MPI_COMM_NULL is always considered large enough */ while (!done) { isBasic = 0; intraCommName = ""; switch (intraCommIdx) { case 0: *comm = MPI_COMM_WORLD; isBasic = 1; intraCommName = "MPI_COMM_WORLD"; break; case 1: /* dup of world */ merr = MPI_Comm_dup(MPI_COMM_WORLD, comm ); if (merr) MTestPrintError( merr ); intraCommName = "Dup of MPI_COMM_WORLD"; break; case 2: /* reverse ranks */ merr = MPI_Comm_size( MPI_COMM_WORLD, &size ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_split( MPI_COMM_WORLD, 0, size-rank, comm ); if (merr) MTestPrintError( merr ); intraCommName = "Rank reverse of MPI_COMM_WORLD"; break; case 3: /* subset of world, with reversed ranks */ merr = MPI_Comm_size( MPI_COMM_WORLD, &size ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_split( MPI_COMM_WORLD, (rank < size/2), size-rank, comm ); if (merr) MTestPrintError( merr ); intraCommName = "Rank reverse of half of MPI_COMM_WORLD"; break; case 4: *comm = MPI_COMM_SELF; isBasic = 1; intraCommName = "MPI_COMM_SELF"; break; /* These next cases are communicators that include some but not all of the processes */ case 5: case 6: case 7: case 8: { int newsize; merr = MPI_Comm_size( MPI_COMM_WORLD, &size ); if (merr) MTestPrintError( merr ); newsize = size - (intraCommIdx - 4); if (allowSmaller && newsize >= min_size) { merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_split( MPI_COMM_WORLD, rank < newsize, rank, comm ); if (merr) MTestPrintError( merr ); if (rank >= newsize) { merr = MPI_Comm_free( comm ); if (merr) MTestPrintError( merr ); *comm = MPI_COMM_NULL; } else { intraCommName = "Split of WORLD"; } } else { /* Act like default */ *comm = MPI_COMM_NULL; isBasic = 1; intraCommName = "MPI_COMM_NULL"; intraCommIdx = -1; } } break; /* Other ideas: dup of self, cart comm, graph comm */ default: *comm = MPI_COMM_NULL; isBasic = 1; intraCommName = "MPI_COMM_NULL"; intraCommIdx = -1; break; } if (*comm != MPI_COMM_NULL) { merr = MPI_Comm_size( *comm, &size ); if (merr) MTestPrintError( merr ); if (size >= min_size) done = 1; else { /* Try again */ if (!isBasic) { merr = MPI_Comm_free( comm ); if (merr) MTestPrintError( merr ); } intraCommIdx++; } } else done = 1; } intraCommIdx++; return intraCommIdx;}/* * Get an intracommunicator with at least min_size members. */int MTestGetIntracomm( MPI_Comm *comm, int min_size ) { return MTestGetIntracommGeneral( comm, min_size, 0 );}/* Return the name of an intra communicator */const char *MTestGetIntracommName( void ){ return intraCommName;}/* * Return an intercomm; set isLeftGroup to 1 if the calling process is * a member of the "left" group. */int MTestGetIntercomm( MPI_Comm *comm, int *isLeftGroup, int min_size ){ int size, rank, remsize, merr; int done=0; MPI_Comm mcomm; int rleader; /* The while loop allows us to skip communicators that are too small. MPI_COMM_NULL is always considered large enough. The size is the sum of the sizes of the local and remote groups */ while (!done) { switch (interCommIdx) { case 0: /* Split comm world in half */ merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_size( MPI_COMM_WORLD, &size ); if (merr) MTestPrintError( merr ); if (size > 1) { merr = MPI_Comm_split( MPI_COMM_WORLD, (rank < size/2), rank, &mcomm ); if (merr) MTestPrintError( merr ); if (rank == 0) { rleader = size/2; } else if (rank == size/2) { rleader = 0; } else { /* Remote leader is signficant only for the processes designated local leaders */ rleader = -1; } *isLeftGroup = rank < size/2; merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader, 12345, comm ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_free( &mcomm ); if (merr) MTestPrintError( merr ); interCommName = "Intercomm by splitting MPI_COMM_WORLD"; } else *comm = MPI_COMM_NULL; break; case 1: /* Split comm world in to 1 and the rest */ merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_size( MPI_COMM_WORLD, &size ); if (merr) MTestPrintError( merr ); if (size > 1) { merr = MPI_Comm_split( MPI_COMM_WORLD, rank == 0, rank, &mcomm ); if (merr) MTestPrintError( merr ); if (rank == 0) { rleader = 1; } else if (rank == 1) { rleader = 0; } else { /* Remote leader is signficant only for the processes designated local leaders */ rleader = -1; } *isLeftGroup = rank == 0; merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader, 12346, comm ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_free( &mcomm ); if (merr) MTestPrintError( merr ); interCommName = "Intercomm by splitting MPI_COMM_WORLD into 1, rest"; } else *comm = MPI_COMM_NULL; break; case 2: /* Split comm world in to 2 and the rest */ merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_size( MPI_COMM_WORLD, &size ); if (merr) MTestPrintError( merr ); if (size > 3) { merr = MPI_Comm_split( MPI_COMM_WORLD, rank < 2, rank, &mcomm ); if (merr) MTestPrintError( merr ); if (rank == 0) { rleader = 2; } else if (rank == 2) { rleader = 0; } else { /* Remote leader is signficant only for the processes designated local leaders */ rleader = -1; } *isLeftGroup = rank < 2; merr = MPI_Intercomm_create( mcomm, 0, MPI_COMM_WORLD, rleader, 12347, comm ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_free( &mcomm ); if (merr) MTestPrintError( merr ); interCommName = "Intercomm by splitting MPI_COMM_WORLD into 2, rest"; } else *comm = MPI_COMM_NULL; break; default: *comm = MPI_COMM_NULL; interCommName = "MPI_COMM_NULL"; interCommIdx = -1; break; } if (*comm != MPI_COMM_NULL) { merr = MPI_Comm_size( *comm, &size ); if (merr) MTestPrintError( merr ); merr = MPI_Comm_remote_size( *comm, &remsize ); if (merr) MTestPrintError( merr ); if (size + remsize >= min_size) done = 1; } else done = 1; } interCommIdx++; return interCommIdx;}/* Return the name of an intercommunicator */const char *MTestGetIntercommName( void ){ return interCommName;}/* Get a communicator of a given minimum size. Both intra and inter communicators are provided */int MTestGetComm( MPI_Comm *comm, int min_size ){ int idx=0; static int getinter = 0; if (!getinter) { idx = MTestGetIntracomm( comm, min_size ); if (idx == 0) { getinter = 1; } } if (getinter) { int isLeft; idx = MTestGetIntercomm( comm, &isLeft, min_size ); if (idx == 0) { getinter = 0; } } return idx;}/* Free a communicator. It may be called with a predefined communicator or MPI_COMM_NULL */void MTestFreeComm( MPI_Comm *comm ){ int merr; if (*comm != MPI_COMM_WORLD && *comm != MPI_COMM_SELF && *comm != MPI_COMM_NULL) { merr = MPI_Comm_free( comm ); if (merr) MTestPrintError( merr ); }}/* ------------------------------------------------------------------------ */void MTestPrintError( int errcode ){ int errclass, slen; char string[MPI_MAX_ERROR_STRING]; MPI_Error_class( errcode, &errclass ); MPI_Error_string( errcode, string, &slen ); printf( "Error class %d (%s)\n", errclass, string ); fflush( stdout );}void MTestPrintErrorMsg( const char msg[], int errcode ){ int errclass, slen; char string[MPI_MAX_ERROR_STRING]; MPI_Error_class( errcode, &errclass ); MPI_Error_string( errcode, string, &slen ); printf( "%s: Error class %d (%s)\n", msg, errclass, string ); fflush( stdout );}/* ------------------------------------------------------------------------ */void MTestPrintfMsg( int level, const char format[], ... ){ va_list list; int n; if (verbose && level >= verbose) { va_start(list,format); n = vprintf( format, list ); va_end(list); fflush(stdout); }}/* Fatal error. Report and exit */void MTestError( const char *msg ){ fprintf( stderr, "%s\n", msg ); fflush( stderr ); MPI_Abort( MPI_COMM_WORLD, 1 );}/* ------------------------------------------------------------------------ */#ifdef HAVE_MPI_WIN_CREATE/* * Create MPI Windows */static int win_index = 0;static const char *winName;/* Use an attribute to remember the type of memory allocation (static, malloc, or MPI_Alloc_mem) */static int mem_keyval = MPI_KEYVAL_INVALID;int MTestGetWin( MPI_Win *win, int mustBePassive ){ static char actbuf[1024]; static char *pasbuf; char *buf; int n, rank, merr; MPI_Info info; if (mem_keyval == MPI_KEYVAL_INVALID) { /* Create the keyval */ merr = MPI_Win_create_keyval( MPI_WIN_NULL_COPY_FN, MPI_WIN_NULL_DELETE_FN, &mem_keyval, 0 ); if (merr) MTestPrintError( merr ); } switch (win_index) { case 0: /* Active target window */ merr = MPI_Win_create( actbuf, 1024, 1, MPI_INFO_NULL, MPI_COMM_WORLD, win ); if (merr) MTestPrintError( merr ); winName = "active-window"; merr = MPI_Win_set_attr( *win, mem_keyval, (void *)0 ); if (merr) MTestPrintError( merr ); break; case 1: /* Passive target window */ merr = MPI_Alloc_mem( 1024, MPI_INFO_NULL, &pasbuf ); if (merr) MTestPrintError( merr ); merr = MPI_Win_create( pasbuf, 1024, 1, MPI_INFO_NULL, MPI_COMM_WORLD, win ); if (merr) MTestPrintError( merr ); winName = "passive-window"; merr = MPI_Win_set_attr( *win, mem_keyval, (void *)2 ); if (merr) MTestPrintError( merr ); break; case 2: /* Active target; all windows different sizes */ merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank ); if (merr) MTestPrintError( merr ); n = rank * 64; if (n) buf = (char *)malloc( n ); else buf = 0; merr = MPI_Win_create( buf, n, 1, MPI_INFO_NULL, MPI_COMM_WORLD, win ); if (merr) MTestPrintError( merr ); winName = "active-all-different-win"; merr = MPI_Win_set_attr( *win, mem_keyval, (void *)1 ); if (merr) MTestPrintError( merr ); break; case 3: /* Active target, no locks set */ merr = MPI_Comm_rank( MPI_COMM_WORLD, &rank ); if (merr) MTestPrintError( merr ); n = rank * 64; if (n) buf = (char *)malloc( n ); else buf = 0; merr = MPI_Info_create( &info ); if (merr) MTestPrintError( merr ); merr = MPI_Info_set( info, "nolocks", "true" ); if (merr) MTestPrintError( merr ); merr = MPI_Win_create( buf, n, 1, info, MPI_COMM_WORLD, win ); if (merr) MTestPrintError( merr ); merr = MPI_Info_free( &info ); if (merr) MTestPrintError( merr ); winName = "active-nolocks-all-different-win"; merr = MPI_Win_set_attr( *win, mem_keyval, (void *)1 ); if (merr) MTestPrintError( merr ); break; default: win_index = -1; } win_index++; return win_index;}/* Return a pointer to the name associated with a window object */const char *MTestGetWinName( void ){ return winName;}/* Free the storage associated with a window object */void MTestFreeWin( MPI_Win *win ){ void *addr; int flag, merr; merr = MPI_Win_get_attr( *win, MPI_WIN_BASE, &addr, &flag ); if (merr) MTestPrintError( merr ); if (!flag) { MTestError( "Could not get WIN_BASE from window" ); } if (addr) { void *val; merr = MPI_Win_get_attr( *win, mem_keyval, &val, &flag ); if (merr) MTestPrintError( merr ); if (flag) { if (val == (void *)1) { free( addr ); } else if (val == (void *)2) { merr = MPI_Free_mem( addr ); if (merr) MTestPrintError( merr ); } /* if val == (void *)0, then static data that must not be freed */ } } merr = MPI_Win_free(win); if (merr) MTestPrintError( merr );}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -