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

📄 dtpack.c

📁 fortran并行计算包
💻 C
字号:
/* * This code may be used to test the performance of some of the  * noncontiguous datatype operations, including vector and indexed * pack and unpack operations.  To simplify the use of this code for  * tuning an MPI implementation, it uses no communication, just the * MPI_Pack and MPI_Unpack routines.  In addition, the individual tests are * in separate routines, making it easier to compare the compiler-generated * code for the user (manual) pack/unpack with the code used by  * the MPI implementation.  Further, to be fair to the MPI implementation, * the routines are passed the source and destination buffers; this ensures * that the compiler can't optimize for statically allocated buffers. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "mpi.h"/* Needed for restrict and const definitions */#include "mpitestconf.h"static int verbose = 0;#define N_REPS 1000#define THRESHOLD 0.10#define VARIANCE_THRESHOLD ((THRESHOLD * THRESHOLD) / 2)#define NTRIALS 10double mean(double *list, int count){	double retval;	int i;	retval = 0;	for (i = 0; i < count; i++)		retval += list[i];	retval /= count;	return retval;}double noise(double *list, int count){	double *margin, retval;	int i;	if (!(margin = malloc(count * sizeof(double)))) {		printf("Unable to allocate memory\n");		return -1;	}	for (i = 0; i < count; i++)		margin[i] = list[i] / mean(list, count);	retval = 0;	for (i = 0; i < count; i++) {		retval += ((margin[i] - 1) * (margin[i] - 1));	}	retval /= count;	if (retval < 0) retval = -retval;	return retval;}/* Here are the tests *//* Test packing a vector of individual doubles */int TestVecPackDouble( int n, int stride, 		       double *avgTimeUser, double *avgTimeMPI,		       double * restrict dest, const double * restrict src ){	double *restrict d_dest;	const double *restrict d_src;	register int i, j;	int          rep, position;	double       t1, t2, t[NTRIALS];	MPI_Datatype vectype;	/* User code */	if (verbose) printf("TestVecPackDouble (USER): ");	for (j = 0; j < NTRIALS; j++) {		t1 = MPI_Wtime();		for (rep=0; rep<N_REPS; rep++) {			i = n;			d_dest = dest;			d_src  = src;			while (i--) {				*d_dest++ = *d_src;				d_src += stride;			}		}		t2 = MPI_Wtime() - t1;		t[j] = t2;		if (verbose) printf("%.3f ", t[j]);	}	if (verbose) printf("[%.3f]\n", noise(t, NTRIALS));	/* If there is too much noise, discard the test */	if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {		*avgTimeUser = 0;		*avgTimeMPI = 0;		if (verbose)			printf("Too much noise; discarding measurement\n");		return 0;	}	*avgTimeUser = mean(t, NTRIALS) / N_REPS;	/* MPI Vector code */	MPI_Type_vector( n, 1, stride, MPI_DOUBLE, &vectype );	MPI_Type_commit( &vectype );	if (verbose) printf("TestVecPackDouble (MPI): ");	for (j = 0; j < NTRIALS; j++) {		t1 = MPI_Wtime();		for (rep=0; rep<N_REPS; rep++) {			position = 0;			MPI_Pack( (void *)src, 1, vectype, dest, n*sizeof(double),				  &position, MPI_COMM_SELF );		}		t2 = MPI_Wtime() - t1;		t[j] = t2;		if (verbose) printf("%.3f ", t[j]);	}	if (verbose) printf("[%.3f]\n", noise(t, NTRIALS));	/* If there is too much noise, discard the test */	if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {		*avgTimeUser = 0;		*avgTimeMPI = 0;		if (verbose)			printf("Too much noise; discarding measurement\n");		return 0;	}	*avgTimeMPI = mean(t, NTRIALS) / N_REPS;	MPI_Type_free( &vectype );	return 0;}/* Test unpacking a vector of individual doubles */int TestVecUnPackDouble( int n, int stride, 		       double *avgTimeUser, double *avgTimeMPI,		       double * restrict dest, const double * restrict src ){	double *restrict d_dest;	const double *restrict d_src;	register int i, j;	int          rep, position;	double       t1, t2, t[NTRIALS];	MPI_Datatype vectype;	/* User code */	if (verbose) printf("TestVecUnPackDouble (USER): ");	for (j = 0; j < NTRIALS; j++) {		t1 = MPI_Wtime();		for (rep=0; rep<N_REPS; rep++) {			i = n;			d_dest = dest;			d_src  = src;			while (i--) {				*d_dest = *d_src++;				d_dest += stride;			}		}		t2 = MPI_Wtime() - t1;		t[j] = t2;		if (verbose) printf("%.3f ", t[j]);	}	if (verbose) printf("[%.3f]\n", noise(t, NTRIALS));	/* If there is too much noise, discard the test */	if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {		*avgTimeUser = 0;		*avgTimeMPI = 0;		if (verbose)			printf("Too much noise; discarding measurement\n");		return 0;	}	*avgTimeUser = mean(t, NTRIALS) / N_REPS;    	/* MPI Vector code */	MPI_Type_vector( n, 1, stride, MPI_DOUBLE, &vectype );	MPI_Type_commit( &vectype );	if (verbose) printf("TestVecUnPackDouble (MPI): ");	for (j = 0; j < NTRIALS; j++) {		t1 = MPI_Wtime();		for (rep=0; rep<N_REPS; rep++) {			position = 0;			MPI_Unpack( (void *)src, n*sizeof(double), 				    &position, dest, 1, vectype, MPI_COMM_SELF );		}		t2 = MPI_Wtime() - t1;		t[j] = t2;		if (verbose) printf("%.3f ", t[j]);	}	if (verbose) printf("[%.3f]\n", noise(t, NTRIALS));	/* If there is too much noise, discard the test */	if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {		*avgTimeUser = 0;		*avgTimeMPI = 0;		if (verbose)			printf("Too much noise; discarding measurement\n");		return 0;	}	*avgTimeMPI = mean(t, NTRIALS) / N_REPS;	MPI_Type_free( &vectype );	return 0;}/* Test packing a vector of 2-individual doubles */int TestVecPack2Double( int n, int stride, 			double *avgTimeUser, double *avgTimeMPI,			double * restrict dest, const double * restrict src ){	double *restrict d_dest;	const double *restrict d_src;	register int i, j;	int          rep, position;	double       t1, t2, t[NTRIALS];	MPI_Datatype vectype;	/* User code */	if (verbose) printf("TestVecPack2Double (USER): ");	for (j = 0; j < NTRIALS; j++) {		t1 = MPI_Wtime();		for (rep=0; rep<N_REPS; rep++) {			i = n;			d_dest = dest;			d_src  = src;			while (i--) {				*d_dest++ = d_src[0];				*d_dest++ = d_src[1];				d_src += stride;			}		}		t2 = MPI_Wtime() - t1;		t[j] = t2;		if (verbose) printf("%.3f ", t[j]);	}	if (verbose) printf("[%.3f]\n", noise(t, NTRIALS));	/* If there is too much noise, discard the test */	if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {		*avgTimeUser = 0;		*avgTimeMPI = 0;		if (verbose)			printf("Too much noise; discarding measurement\n");		return 0;	}	*avgTimeUser = mean(t, NTRIALS) / N_REPS;    	/* MPI Vector code */	MPI_Type_vector( n, 2, stride, MPI_DOUBLE, &vectype );	MPI_Type_commit( &vectype );    	if (verbose) printf("TestVecPack2Double (MPI): ");	for (j = 0; j < NTRIALS; j++) {		t1 = MPI_Wtime();		for (rep=0; rep<N_REPS; rep++) {			position = 0;			MPI_Pack( (void *)src, 1, vectype, dest, 2*n*sizeof(double),				  &position, MPI_COMM_SELF );		}		t2 = MPI_Wtime() - t1;		t[j] = t2;		if (verbose) printf("%.3f ", t[j]);	}	if (verbose) printf("[%.3f]\n", noise(t, NTRIALS));	/* If there is too much noise, discard the test */	if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {		*avgTimeUser = 0;		*avgTimeMPI = 0;		if (verbose)			printf("Too much noise; discarding measurement\n");		return 0;	}	*avgTimeMPI = mean(t, NTRIALS) / N_REPS;	MPI_Type_free( &vectype );	return 0;}/* This creates an indexed type that is like a vector (for simplicity   of construction).  There is a possibility that the MPI implementation    will recognize and simplify this (e.g., in MPI_Type_commit); if so,   let us know and we'll add a version that is not as regular */int TestIndexPackDouble( int n, int stride, 			 double *avgTimeUser, double *avgTimeMPI,			 double * restrict dest, const double * restrict src ){	double *restrict d_dest;	const double *restrict d_src;	register int i, j;	int          rep, position;	int          *restrict displs = 0;	double       t1, t2, t[NTRIALS];	MPI_Datatype indextype;	displs = (int *)malloc( n * sizeof(int) );	for (i=0; i<n; i++) displs[i] = i * stride;	/* User code */	if (verbose) printf("TestIndexPackDouble (USER): ");	for (j = 0; j < NTRIALS; j++) {		t1 = MPI_Wtime();		for (rep=0; rep<N_REPS; rep++) {			i = n;			d_dest = dest;			d_src  = src;			for (i=0; i<n; i++) {				*d_dest++ = d_src[displs[i]];			}		}		t2 = MPI_Wtime() - t1;		t[j] = t2;		if (verbose) printf("%.3f ", t[j]);	}	if (verbose) printf("[%.3f]\n", noise(t, NTRIALS));	/* If there is too much noise, discard the test */	if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {		*avgTimeUser = 0;		*avgTimeMPI = 0;		if (verbose)			printf("Too much noise; discarding measurement\n");		return 0;	}	*avgTimeUser = mean(t, NTRIALS) / N_REPS;    	/* MPI Index code */	MPI_Type_create_indexed_block( n, 1, displs, MPI_DOUBLE, &indextype );	MPI_Type_commit( &indextype );	free( displs );    	if (verbose) printf("TestIndexPackDouble (MPI): ");	for (j = 0; j < NTRIALS; j++) {		t1 = MPI_Wtime();		for (rep=0; rep<N_REPS; rep++) {			position = 0;			MPI_Pack( (void *)src, 1, indextype, dest, n*sizeof(double),				  &position, MPI_COMM_SELF );		}		t2 = MPI_Wtime() - t1;		t[j] = t2;		if (verbose) printf("%.3f ", t[j]);	}	if (verbose) printf("[%.3f]\n", noise(t, NTRIALS));	/* If there is too much noise, discard the test */	if (noise(t, NTRIALS) > VARIANCE_THRESHOLD) {		*avgTimeUser = 0;		*avgTimeMPI = 0;		if (verbose)			printf("Too much noise; discarding measurement\n");		return 0;	}	*avgTimeMPI = mean(t, NTRIALS) / N_REPS;	MPI_Type_free( &indextype );	return 0;}int Report( const char *name, const char *packname, 	    double avgTimeMPI, double avgTimeUser ){	double diffTime, maxTime;	int errs=0;	/* Move this into a common routine */	diffTime = avgTimeMPI - avgTimeUser;	if (diffTime < 0) diffTime = - diffTime;	if (avgTimeMPI > avgTimeUser) maxTime = avgTimeMPI;	else                          maxTime = avgTimeUser;	if (verbose) {		printf( "%-30s:\t%g\t%g\t(%g%%)\n", name, 			avgTimeMPI, avgTimeUser,			100 * (diffTime / maxTime) );		fflush(stdout);	}	if (avgTimeMPI > avgTimeUser && (diffTime > THRESHOLD * maxTime)) {		errs++;		printf( "%s:\tMPI %s code is too slow: MPI %g\t User %g\n",			name, packname, avgTimeMPI, avgTimeUser );	}	return errs;}/* Finally, here's the main program */int main( int argc, char *argv[] ){    int n, stride, err, errs = 0;    void *dest, *src;    double avgTimeUser, avgTimeMPI;    MPI_Init( &argc, &argv );    if (getenv("MPITEST_VERBOSE")) verbose = 1;    n      = 30000;    stride = 4;    dest = (void *)malloc( n * sizeof(double) );    src  = (void *)malloc( n * ((1+stride)*sizeof(double)) );    /* Touch the source and destination arrays */    memset( src, 0, n * (1+stride)*sizeof(double) );    memset( dest, 0, n * sizeof(double) );    err = TestVecPackDouble( n, stride, &avgTimeUser, &avgTimeMPI,			     dest, src );    errs += Report( "VecPackDouble", "Pack", avgTimeMPI, avgTimeUser );    err = TestVecUnPackDouble( n, stride, &avgTimeUser, &avgTimeMPI,			       src, dest );    errs += Report( "VecUnPackDouble", "Unpack", avgTimeMPI, avgTimeUser );    err = TestIndexPackDouble( n, stride, &avgTimeUser, &avgTimeMPI,			     dest, src );    errs += Report( "VecIndexDouble", "Pack", avgTimeMPI, avgTimeUser );    free(dest);    free(src);        dest = (void *)malloc( 2*n * sizeof(double) );    src  = (void *)malloc( (1 + n) * ((1+stride)*sizeof(double)) );    memset( dest, 0, 2*n * sizeof(double) );    memset( src, 0, (1+n) * (1+stride)*sizeof(double) );    err = TestVecPack2Double( n, stride, &avgTimeUser, &avgTimeMPI,			      dest, src );    errs += Report( "VecPack2Double", "Pack", avgTimeMPI, avgTimeUser );    free(dest);    free(src);        if (errs == 0) {	printf( " No Errors\n" );    }    else {	printf( " Found %d performance problems\n", errs );    }    fflush(stdout);    MPI_Finalize();    return 0;}

⌨️ 快捷键说明

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