⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mtest.cxx

📁 fortran并行计算包
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C++; c-basic-offset:4 ; -*- *//* * *  (C) 2001 by Argonne National Laboratory. *      See COPYRIGHT in top-level directory. */#include "mpi.h"#include "mpitestconf.h"#ifdef HAVE_IOSTREAM// Not all C++ compilers have iostream instead of iostream.h#include <iostream>#ifdef HAVE_NAMESPACE_STD// Those that do often need the std namespace; otherwise, a bare "cout"// is likely to fail to compileusing namespace std;#endif#else#include <iostream.h>#endif#include "mpitestcxx.h"#include <stdlib.h>static int dbgflag = 0;         /* Flag used for debugging */static int wrank = -1;          /* World rank */static int verbose = 0;         /* Message level (0 is none) *//*  * Initialize and Finalize MTest *//*    Initialize MTest, initializing MPI if necessary.   Environment Variables:+ MPITEST_DEBUG - If set (to any value), turns on debugging output- MPITEST_VERBOSE - If set to a numeric value, turns on that level of  verbose output.  This is used by the routine 'MTestPrintfMsg' */void MTest_Init( void ){    bool flag;    char *envval = 0;    flag = MPI::Is_initialized( );    if (!flag) {	MPI::Init( );    }    /* Check for debugging control */    if (getenv( "MPITEST_DEBUG" )) {	dbgflag = 1;	wrank = MPI::COMM_WORLD.Get_rank();    }    /* Check for verbose control */    envval = getenv( "MPITEST_VERBOSE" );    if (envval) {	char *s;	long val = strtol( envval, &s, 0 );	if (s == envval) {	    /* This is the error case for strtol */	    cerr << "Warning: "<< envval << " not valid for MPITEST_VERBOSE\n";	    cerr.flush();	}	else {	    if (val >= 0) {		verbose = val;	    }	    else {		cerr << "Warning: " << envval << 		    " not valid for MPITEST_VERBOSE\n";		cerr.flush();	    }	}    }}/*  Finalize MTest.  errs is the number of errors on the calling process;   this routine will write the total number of errors over all of MPI_COMM_WORLD  to the process with rank zero, or " No Errors".  It does *not* finalize MPI. */void MTest_Finalize( int errs ){    int rank, toterrs;    rank = MPI::COMM_WORLD.Get_rank();    MPI::COMM_WORLD.Allreduce( &errs, &toterrs, 1, MPI::INT, MPI::SUM );    if (rank == 0) {	if (toterrs) {	    cout << " Found " << toterrs << " errors\n";	}	else {	    cout << " No Errors\n";	}	cout.flush();    }}/* * Datatypes * * Eventually, this could read a description of a file.  For now, we hard  * code the choices * */static int datatype_index = 0;/*  * Setup contiguous buffers of n copies of a datatype. */static void *MTestTypeContigInit( MTestDatatype *mtype ){    MPI::Aint size, lb;    if (mtype->count > 0) {	signed char *p;	int  i, totsize;	mtype->datatype.Get_extent( lb, size );	totsize = size * mtype->count;	if (!mtype->buf) {	    mtype->buf = (void *) malloc( totsize );	}	p = (signed char *)(mtype->buf);	if (!p) {	    /* Error - out of memory */	    MTestError( "Out of memory in type buffer init" );	}	for (i=0; i<totsize; i++) {	    p[i] = 0xff ^ (i & 0xff);	}    }    else {	mtype->buf = 0;    }    return mtype->buf;}/*  * Setup contiguous buffers of n copies of a datatype.  Initialize for * reception (e.g., set initial data to detect failure) */static void *MTestTypeContigInitRecv( MTestDatatype *mtype ){    MPI_Aint size;    if (mtype->count > 0) {	signed char *p;	int  i, totsize;	MPI_Type_extent( mtype->datatype, &size );	totsize = size * mtype->count;	if (!mtype->buf) {	    mtype->buf = (void *) malloc( totsize );	}	p = (signed char *)(mtype->buf);	if (!p) {	    /* Error - out of memory */	    MTestError( "Out of memory in type buffer init" );	}	for (i=0; i<totsize; i++) {	    p[i] = 0xff;	}    }    else {	if (mtype->buf) {	    free( mtype->buf );	}	mtype->buf = 0;    }    return mtype->buf;}static void *MTestTypeContigFree( MTestDatatype *mtype ){    if (mtype->buf) {	free( mtype->buf );	mtype->buf = 0;    }    return 0;}static int MTestTypeContigCheckbuf( MTestDatatype *mtype ){    unsigned char *p;    unsigned char expected;    int  i, totsize, err = 0;    MPI_Aint size;    p = (unsigned char *)mtype->buf;    if (p) {	MPI_Type_extent( mtype->datatype, &size );	totsize = size * mtype->count;	for (i=0; i<totsize; i++) {	    expected = (0xff ^ (i & 0xff));	    if (p[i] != expected) {		err++;		if (mtype->printErrors && err < 10) {		    cout << "Data expected = " << hex << expected << 			" but got " << p[i] << " for the " <<			 dec << i << "th entry\n";		    cout.flush();		}	    }	}    }    return err;}/* ------------------------------------------------------------------------ *//* Datatype routines for vector datatypes                                   *//* ------------------------------------------------------------------------ */static void *MTestTypeVectorInit( MTestDatatype *mtype ){    MPI::Aint size, lb;    if (mtype->count > 0) {	unsigned char *p;	int  i, j, k, nc, totsize;	mtype->datatype.Get_extent( lb, size );	totsize	   = mtype->count * size;	if (!mtype->buf) {	    mtype->buf = (void *) malloc( totsize );	}	p	   = (unsigned char *)(mtype->buf);	if (!p) {	    /* Error - out of memory */	    MTestError( "Out of memory in type buffer init" );	}	/* First, set to -1 */	for (i=0; i<totsize; i++) p[i] = 0xff;	/* Now, set the actual elements to the successive values.	   To do this, we need to run 3 loops */	nc = 0;	/* count is usually one for a vector type */	for (k=0; k<mtype->count; k++) {	    /* For each element (block) */	    for (i=0; i<mtype->nelm; i++) {		/* For each value */		for (j=0; j<mtype->blksize; j++) {		    p[j] = (0xff ^ (nc & 0xff));		    nc++;		}		p += mtype->stride;	    }	}    }    else {	mtype->buf = 0;    }    return mtype->buf;}static void *MTestTypeVectorFree( MTestDatatype *mtype ){    if (mtype->buf) {	free( mtype->buf );	mtype->buf = 0;    }    return 0;}/* ------------------------------------------------------------------------ *//* 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 ){    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:	sendtype->datatype = MPI::INT.Dup();	sendtype->datatype.Set_name( "dup of MPI::INT" );	recvtype->datatype = MPI::INT.Dup();	recvtype->datatype.Set_name( "dup of MPI::INT" );	/* 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;	sendtype->datatype = MPI::INT.Create_vector( recvtype->count, 1, sendtype->stride );        sendtype->datatype.Commit();	sendtype->datatype.Set_name( "int-vector" );	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;    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;	cout << wrank << ": sendtype is " << MTestGetDatatypeName( sendtype ) 	     << "\n";	typesize = sendtype->datatype.Get_size();	cout << wrank << ": sendtype size = " << typesize << "\n";	cout << wrank << ": recvtype is " << MTestGetDatatypeName( recvtype ) 	     << "\n";	typesize = recvtype->datatype.Get_size();	cout << wrank << ": recvtype size = " << typesize << "\n";	cout.flush();    }    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;}void MTestFreeDatatype( MTestDatatype *mtype ){    /* 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) {	mtype->datatype.Free();    }}/* 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;    if (status) {	count = status.Get_count( recvtype->datatype );		/* 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;    if (sp >= 4) sp = 0;    dtype->datatype.Get_name( name[sp], rlen );    return (const char *)name[sp++];}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -