📄 mtest.c
字号:
MTestError( "Out of memory in type buffer init\n" ); } for (i=0; i<totsize; i++) { p[i] = 0xff; } } else { /* count == 0 */ if (mtype->buf) { free( mtype->buf ); } mtype->buf = 0; } return mtype->buf;}static void *MTestTypeIndexedFree( MTestDatatype *mtype ){ if (mtype->buf) { free( mtype->buf ); free( mtype->displs ); free( mtype->index ); mtype->buf = 0; mtype->displs = 0; mtype->index = 0; } return 0;}static int MTestTypeIndexedCheckbuf( MTestDatatype *mtype ){ unsigned char *p; unsigned char expected; int i, err = 0, merr; MPI_Aint totsize; p = (unsigned char *)mtype->buf; if (p) { int j, k, offset; merr = MPI_Type_extent( mtype->datatype, &totsize ); if (merr) MTestPrintError( merr ); k = 0; for (i=0; i<mtype->nelm; i++) { int b; /* Compute the offset: */ offset = mtype->displs[i] * mtype->basesize; for (b=0; b<mtype->index[i]; b++) { for (j=0; j<mtype->basesize; j++) { expected = (0xff ^ (k & 0xff)); if (p[offset+j] != expected) { err++; if (mtype->printErrors && err < 10) { printf( "Data expected = %x but got %x for %dth entry\n", expected, p[offset+j], k ); fflush( stdout ); } } k++; } offset += mtype->basesize; } } } return err;}/* ------------------------------------------------------------------------ *//* Routines to select a datatype and associated buffer create/fill/check *//* routines *//* ------------------------------------------------------------------------ *//* Create a range of datatypes with a given count elements. This uses a selection of types, rather than an exhaustive collection. It allocates both send and receive types so that they can have the same type signature (collection of basic types) but different type maps (layouts in memory) */int MTestGetDatatypes( MTestDatatype *sendtype, MTestDatatype *recvtype, int count ){ int merr; int i; sendtype->InitBuf = 0; sendtype->FreeBuf = 0; sendtype->CheckBuf = 0; sendtype->datatype = 0; sendtype->isBasic = 0; sendtype->printErrors = 0; recvtype->InitBuf = 0; recvtype->FreeBuf = 0; recvtype->CheckBuf = 0; recvtype->datatype = 0; recvtype->isBasic = 0; recvtype->printErrors = 0; sendtype->buf = 0; recvtype->buf = 0; /* Set the defaults for the message lengths */ sendtype->count = count; recvtype->count = count; /* Use datatype_index to choose a datatype to use. If at the end of the list, return 0 */ switch (datatype_index) { case 0: sendtype->datatype = MPI_INT; sendtype->isBasic = 1; recvtype->datatype = MPI_INT; recvtype->isBasic = 1; break; case 1: sendtype->datatype = MPI_DOUBLE; sendtype->isBasic = 1; recvtype->datatype = MPI_DOUBLE; recvtype->isBasic = 1; break; case 2: sendtype->datatype = MPI_INT; sendtype->isBasic = 1; recvtype->datatype = MPI_BYTE; recvtype->isBasic = 1; recvtype->count *= sizeof(int); break; case 3: sendtype->datatype = MPI_FLOAT_INT; sendtype->isBasic = 1; recvtype->datatype = MPI_FLOAT_INT; recvtype->isBasic = 1; break; case 4: merr = MPI_Type_dup( MPI_INT, &sendtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_set_name( sendtype->datatype, "dup of MPI_INT" ); if (merr) MTestPrintError( merr ); merr = MPI_Type_dup( MPI_INT, &recvtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_set_name( recvtype->datatype, "dup of MPI_INT" ); if (merr) MTestPrintError( merr ); /* dup'ed types are already committed if the original type was committed (MPI-2, section 8.8) */ break; case 5: /* vector send type and contiguous receive type */ /* These sizes are in bytes (see the VectorInit code) */ sendtype->stride = 3 * sizeof(int); sendtype->blksize = sizeof(int); sendtype->nelm = recvtype->count; merr = MPI_Type_vector( recvtype->count, 1, 3, MPI_INT, &sendtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_commit( &sendtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_set_name( sendtype->datatype, "int-vector" ); if (merr) MTestPrintError( merr ); sendtype->count = 1; recvtype->datatype = MPI_INT; recvtype->isBasic = 1; sendtype->InitBuf = MTestTypeVectorInit; recvtype->InitBuf = MTestTypeContigInitRecv; sendtype->FreeBuf = MTestTypeVectorFree; recvtype->FreeBuf = MTestTypeContigFree; sendtype->CheckBuf = 0; recvtype->CheckBuf = MTestTypeContigCheckbuf; break; case 6: /* Indexed send using many small blocks and contig receive */ sendtype->blksize = sizeof(int); sendtype->nelm = recvtype->count; sendtype->basesize = sizeof(int); sendtype->displs = (int *)malloc( sendtype->nelm * sizeof(int) ); sendtype->index = (int *)malloc( sendtype->nelm * sizeof(int) ); if (!sendtype->displs || !sendtype->index) { MTestError( "Out of memory in type init\n" ); } /* Make the sizes larger (4 ints) to help push the total size to over 256k in some cases, as the MPICH2 code as of 10/1/06 used large internal buffers for packing non-contiguous messages */ for (i=0; i<sendtype->nelm; i++) { sendtype->index[i] = 4; sendtype->displs[i] = 5*i; } merr = MPI_Type_indexed( sendtype->nelm, sendtype->index, sendtype->displs, MPI_INT, &sendtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_commit( &sendtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_set_name( sendtype->datatype, "int-indexed(4-int)" ); if (merr) MTestPrintError( merr ); sendtype->count = 1; sendtype->InitBuf = MTestTypeIndexedInit; sendtype->FreeBuf = MTestTypeIndexedFree; sendtype->CheckBuf = 0; recvtype->datatype = MPI_INT; recvtype->isBasic = 1; recvtype->count = count * 4; recvtype->InitBuf = MTestTypeContigInitRecv; recvtype->FreeBuf = MTestTypeContigFree; recvtype->CheckBuf = MTestTypeContigCheckbuf; break; case 7: /* Indexed send using 2 large blocks and contig receive */ sendtype->blksize = sizeof(int); sendtype->nelm = 2; sendtype->basesize = sizeof(int); sendtype->displs = (int *)malloc( sendtype->nelm * sizeof(int) ); sendtype->index = (int *)malloc( sendtype->nelm * sizeof(int) ); if (!sendtype->displs || !sendtype->index) { MTestError( "Out of memory in type init\n" ); } sendtype->index[0] = (recvtype->count + 1) / 2; sendtype->displs[0] = 0; sendtype->index[1] = (recvtype->count + 1) / 2; sendtype->displs[1] = sendtype->index[0] + 1; merr = MPI_Type_indexed( sendtype->nelm, sendtype->index, sendtype->displs, MPI_INT, &sendtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_commit( &sendtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_set_name( sendtype->datatype, "int-indexed(2 blocks)" ); if (merr) MTestPrintError( merr ); sendtype->count = 1; sendtype->InitBuf = MTestTypeIndexedInit; sendtype->FreeBuf = MTestTypeIndexedFree; sendtype->CheckBuf = 0; recvtype->datatype = MPI_INT; recvtype->isBasic = 1; recvtype->count = sendtype->index[0] + sendtype->index[1]; recvtype->InitBuf = MTestTypeContigInitRecv; recvtype->FreeBuf = MTestTypeContigFree; recvtype->CheckBuf = MTestTypeContigCheckbuf; break; case 8: /* Indexed receive using many small blocks and contig send */ recvtype->blksize = sizeof(int); recvtype->nelm = recvtype->count; recvtype->basesize = sizeof(int); recvtype->displs = (int *)malloc( recvtype->nelm * sizeof(int) ); recvtype->index = (int *)malloc( recvtype->nelm * sizeof(int) ); if (!recvtype->displs || !recvtype->index) { MTestError( "Out of memory in type recv init\n" ); } /* Make the sizes larger (4 ints) to help push the total size to over 256k in some cases, as the MPICH2 code as of 10/1/06 used large internal buffers for packing non-contiguous messages */ for (i=0; i<recvtype->nelm; i++) { recvtype->index[i] = 4; recvtype->displs[i] = 5*i; } merr = MPI_Type_indexed( recvtype->nelm, recvtype->index, recvtype->displs, MPI_INT, &recvtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_commit( &recvtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_set_name( recvtype->datatype, "recv-int-indexed(4-int)" ); if (merr) MTestPrintError( merr ); recvtype->count = 1; recvtype->InitBuf = MTestTypeIndexedInitRecv; recvtype->FreeBuf = MTestTypeIndexedFree; recvtype->CheckBuf = MTestTypeIndexedCheckbuf; sendtype->datatype = MPI_INT; sendtype->isBasic = 1; sendtype->count = count * 4; sendtype->InitBuf = MTestTypeContigInit; sendtype->FreeBuf = MTestTypeContigFree; sendtype->CheckBuf = 0; break;#if 0 case 9: /* vector recv type and contiguous send type */ /* These sizes are in bytes (see the VectorInit code) */ recvtype->stride = 4 * sizeof(int); recvtype->blksize = sizeof(int); recvtype->nelm = recvtype->count; merr = MPI_Type_vector( sendtype->count, 1, 4, MPI_INT, &recvtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_commit( &recvtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_set_name( recvtype->datatype, "int-vector" ); if (merr) MTestPrintError( merr ); recvtype->count = 1; sendtype->datatype = MPI_INT; sendtype->isBasic = 1; recvtype->InitBuf = MTestTypeVectorInit; sendtype->InitBuf = MTestTypeContigInitRecv; recvtype->FreeBuf = MTestTypeVectorFree; sendtype->FreeBuf = MTestTypeContigFree; recvtype->CheckBuf = MTestTypeVectorCheckbuf; sendtype->CheckBuf = 0; break; case 10: /* contig send and block indexed recv */ /* Make indexes 5*((count-1) - i), for i=0, ..., count-1, i.e., every 5th element, but starting from the end. */ recvtype->blksize = sizeof(int); recvtype->nelm = recvtype->count; sendtype->displs = (int *) malloc( sendtype->count ); if (!sendtype->displs) { MTestError( "Out of memory in indexed block" ); } for (i=0; i<sendtype->count; i++) { sendtype->displs[i] = 5 * ( (count-1) - i ); } sendtype->basesize = sizeof(int); sendtype->nelm = sendtype->count; merr = MPI_Type_create_index_block( sendtype->count, 1, sendtype->displs, MPI_INT, &recvtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_commit( &recvtype->datatype ); if (merr) MTestPrintError( merr ); merr = MPI_Type_set_name( recvtype->datatype, "int-decreasing-indexed" ); if (merr) MTestPrintError( merr ); recvtype->count = 1; sendtype->datatype = MPI_INT; sendtype->isBasic = 1; recvtype->InitBuf = MTestTypeIndexedInit; sendtype->InitBuf = MTestTypeContigInitRecv; recvtype->FreeBuf = MTestTypeIndexedFree; sendtype->FreeBuf = MTestTypeContigFree; recvtype->CheckBuf = MTestTypeIndexedCheckBuf; sendtype->CheckBuf = 0; break; case 11: /* index send and vector recv (using shorts) */ break;#endif default: datatype_index = -1; } if (!sendtype->InitBuf) { sendtype->InitBuf = MTestTypeContigInit; recvtype->InitBuf = MTestTypeContigInitRecv; sendtype->FreeBuf = MTestTypeContigFree; recvtype->FreeBuf = MTestTypeContigFree; sendtype->CheckBuf = MTestTypeContigCheckbuf; recvtype->CheckBuf = MTestTypeContigCheckbuf; } datatype_index++; if (dbgflag && datatype_index > 0) { int typesize; fprintf( stderr, "%d: sendtype is %s\n", wrank, MTestGetDatatypeName( sendtype ) ); merr = MPI_Type_size( sendtype->datatype, &typesize ); if (merr) MTestPrintError( merr ); fprintf( stderr, "%d: sendtype size = %d\n", wrank, typesize ); fprintf( stderr, "%d: recvtype is %s\n", wrank, MTestGetDatatypeName( recvtype ) ); merr = MPI_Type_size( recvtype->datatype, &typesize ); if (merr) MTestPrintError( merr ); fprintf( stderr, "%d: recvtype size = %d\n", wrank, typesize ); fflush( stderr ); } return datatype_index;}/* Reset the datatype index (start from the initial data type. Note: This routine is rarely needed; MTestGetDatatypes automatically starts over after the last available datatype is used.*/void MTestResetDatatypes( void ){ datatype_index = 0;}/* Return the index of the current datatype. This is rarely needed and is provided mostly to enable debugging of the MTest package itself */int MTestGetDatatypeIndex( void ){ return datatype_index;}/* Free the storage associated with a datatype */void MTestFreeDatatype( MTestDatatype *mtype ){ int merr; /* Invoke a datatype-specific free function to handle both the datatype and the send/receive buffers */ if (mtype->FreeBuf) { (mtype->FreeBuf)( mtype ); } /* Free the datatype itself if it was created */ if (!mtype->isBasic) { merr = MPI_Type_free( &mtype->datatype ); if (merr) MTestPrintError( merr ); }}/* Check that a message was received correctly. Returns the number of errors detected. Status may be NULL or MPI_STATUS_IGNORE */int MTestCheckRecv( MPI_Status *status, MTestDatatype *recvtype ){ int count; int errs = 0, merr; if (status && status != MPI_STATUS_IGNORE) { merr = MPI_Get_count( status, recvtype->datatype, &count ); if (merr) MTestPrintError( merr ); /* Check count against expected count */ if (count != recvtype->count) { errs ++; } } /* Check received data */ if (!errs && recvtype->CheckBuf( recvtype )) { errs++; } return errs;}/* This next routine uses a circular buffer of static name arrays just to simplify the use of the routine */const char *MTestGetDatatypeName( MTestDatatype *dtype ){ static char name[4][MPI_MAX_OBJECT_NAME]; static int sp=0; int rlen, merr; if (sp >= 4) sp = 0; merr = MPI_Type_get_name( dtype->datatype, name[sp], &rlen ); if (merr) MTestPrintError( merr ); return (const char *)name[sp++];}/* ----------------------------------------------------------------------- *//* * Create communicators. Use separate routines for inter and intra * communicators (there is a routine to give both) * Note that the routines may return MPI_COMM_NULL, so code should test for * that return value as well. * */static int interCommIdx = 0;static int intraCommIdx = 0;static const char *intraCommName = 0;static const char *interCommName = 0;/* * Get an intracommunicator with at least min_size members. If "allowSmaller" * is true, allow the communicator to be smaller than MPI_COMM_WORLD and * for this routine to return MPI_COMM_NULL for some values. Returns 0 if * no more communicators are available. */int MTestGetIntracommGeneral( MPI_Comm *comm, int min_size, int allowSmaller ){ int size, rank, merr; int done=0; int isBasic = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -