|
Packit |
857059 |
/* BEGIN_ICS_COPYRIGHT7 ****************************************
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Copyright (c) 2015, Intel Corporation
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
857059 |
modification, are permitted provided that the following conditions are met:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
* Redistributions of source code must retain the above copyright notice,
|
|
Packit |
857059 |
this list of conditions and the following disclaimer.
|
|
Packit |
857059 |
* Redistributions in binary form must reproduce the above copyright
|
|
Packit |
857059 |
notice, this list of conditions and the following disclaimer in the
|
|
Packit |
857059 |
documentation and/or other materials provided with the distribution.
|
|
Packit |
857059 |
* Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
857059 |
may be used to endorse or promote products derived from this software
|
|
Packit |
857059 |
without specific prior written permission.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
857059 |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
857059 |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
Packit |
857059 |
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
Packit |
857059 |
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit |
857059 |
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
Packit |
857059 |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
Packit |
857059 |
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
Packit |
857059 |
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
857059 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
** END_ICS_COPYRIGHT7 ****************************************/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* [ICS VERSION STRING: unknown] */
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* The purpose of this application is to do some simple validations of MPI
|
|
Packit |
857059 |
* communications. Unlike other benchmark apps is is not intended to run
|
|
Packit |
857059 |
* quickly, but to validate the results of each transfer to ensure the
|
|
Packit |
857059 |
* correct operation of MPI.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* The code is deliberately written to be inefficient; in order to (hopefully)
|
|
Packit |
857059 |
* expose communication errors and memory corruption issues.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#include <stdio.h>
|
|
Packit |
857059 |
#include <string.h>
|
|
Packit |
857059 |
#include <stdlib.h>
|
|
Packit |
857059 |
#include <unistd.h>
|
|
Packit |
857059 |
#include <getopt.h>
|
|
Packit |
857059 |
#include <mpi.h>
|
|
Packit |
857059 |
#include <time.h>
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Defines used by randomize test.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
#define SHUFFLERATE 64
|
|
Packit |
857059 |
#define MINRANDXFER 1024
|
|
Packit |
857059 |
#define MAXRANDXFER 32768
|
|
Packit |
857059 |
#define NUMRANDXFERS 65536
|
|
Packit |
857059 |
#define RANDOMLEN() (MINRANDXFER + (random() % (MAXRANDXFER-MINRANDXFER)))
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#define MAX(a,b) ((a>b)?a:b)
|
|
Packit |
857059 |
#define MIN(a,b) ((a
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Prints the message if nodes rank is 0.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
#define ROOTPRINT(format,args...) { if (myid == 0) fprintf(stderr,format,##args); }
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Prints an error, including node rank and line of code.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
#define ERRPRINT(format,args...) { fprintf(stderr,"[%d/%d]: ERROR: ",myid,__LINE__); fprintf(stderr,format,##args); }
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Prints a message if and only if verbose mode is on. Includes
|
|
Packit |
857059 |
* rank and line of code.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
#define NODEPRINT(format,args...) if (verboseMode) { fflush(stdout); printf("[%d/%d]: ",myid,__LINE__); printf(format,##args); }
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Force a core dump.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
#define ERRABORT(retCode) if (retCode != MPI_SUCCESS) { fprintf(stderr,"MPI Failure: %d at line %d\n",retCode,__LINE__); abort(); }
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Padding used to look for corruption before or after a read
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
#define BARRIERSIZE 4096
|
|
Packit |
857059 |
unsigned int minSize = 16384; /* Default smallest message size */
|
|
Packit |
857059 |
unsigned int maxSize = 65536; /* Default largest message size */
|
|
Packit |
857059 |
unsigned int maxIters = 1000; /* Default # of rounds */
|
|
Packit |
857059 |
int useSendOffset = 0; /* Default - don't do offest sends. */
|
|
Packit |
857059 |
unsigned int rawBufferCount = 1;
|
|
Packit |
857059 |
unsigned int barrierSize = 4096; /* Default - 4k protection areas. */
|
|
Packit |
857059 |
|
|
Packit |
857059 |
int verboseMode = 0;
|
|
Packit |
857059 |
int doFast = 0;
|
|
Packit |
857059 |
int doSlow = 1;
|
|
Packit |
857059 |
int doRandom = 1;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
struct option options[] = {
|
|
Packit |
857059 |
{"min", required_argument, NULL, '<'},
|
|
Packit |
857059 |
{"max", required_argument, NULL, '>'},
|
|
Packit |
857059 |
{"rounds", required_argument, NULL, 'i'},
|
|
Packit |
857059 |
{"buffers", required_argument, NULL, 'b'},
|
|
Packit |
857059 |
{"barrier", required_argument, NULL, 'B'},
|
|
Packit |
857059 |
{"verbose", no_argument, &verboseMode, 1},
|
|
Packit |
857059 |
{"fast", no_argument, &doFast, 1},
|
|
Packit |
857059 |
{"nofast", no_argument, &doFast, 0},
|
|
Packit |
857059 |
{"slow", no_argument, &doSlow, 1},
|
|
Packit |
857059 |
{"noslow", no_argument, &doSlow, 0},
|
|
Packit |
857059 |
{"random", no_argument, &doRandom, 1},
|
|
Packit |
857059 |
{"norandom", no_argument, &doRandom, 0},
|
|
Packit |
857059 |
{"sendoffset", no_argument, &useSendOffset, 1},
|
|
Packit |
857059 |
{NULL, 0, NULL, 0}
|
|
Packit |
857059 |
};
|
|
Packit |
857059 |
|
|
Packit |
857059 |
void
|
|
Packit |
857059 |
usage( )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int i = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
fprintf( stderr, "Usage: mpicheck " );
|
|
Packit |
857059 |
for ( i = 0; options[i].name != NULL; i++ ) {
|
|
Packit |
857059 |
if ( options[i].has_arg == required_argument ) {
|
|
Packit |
857059 |
fprintf( stderr, "[--%s ###] ", options[i].name );
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
fprintf( stderr, "[--%s] ", options[i].name );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
fprintf( stderr, "\n" );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Writes a transfer buffer to disk for post-mortem analysis.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
void
|
|
Packit |
857059 |
dumpbuffer( int myid, char *name, char *buffer, int size )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
char fname[1024];
|
|
Packit |
857059 |
FILE *f;
|
|
Packit |
857059 |
size_t s;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
sprintf( fname, "%s.%03d", name, myid );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
f = fopen( fname, "w" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( !f ) {
|
|
Packit |
857059 |
ERRPRINT( "Failed to open %s\n", fname );
|
|
Packit |
857059 |
return;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
s = fwrite( buffer, 1, size, f );
|
|
Packit |
857059 |
if ( s != size ) {
|
|
Packit |
857059 |
ERRPRINT( "Failed to write %s\n", fname );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
fclose( f );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
typedef struct {
|
|
Packit |
857059 |
unsigned int start;
|
|
Packit |
857059 |
unsigned int length;
|
|
Packit |
857059 |
} RandomRecord;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
static void
|
|
Packit |
857059 |
initrandom( )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
unsigned int seed;
|
|
Packit |
857059 |
FILE *f = fopen( "/dev/random", "r" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( f ) {
|
|
Packit |
857059 |
fread( &seed, sizeof( seed ), 1, f );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
fclose( f );
|
|
Packit |
857059 |
srandom( seed );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Randomize mode pairs up the nodes and performs a "drunkards" walk
|
|
Packit |
857059 |
* between them - it performs a large number of sends and receives
|
|
Packit |
857059 |
* designed to stress operations when asynchronous messages overlap.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Note that randomize does not use the "rounds" setting that the
|
|
Packit |
857059 |
* other tests use.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
int
|
|
Packit |
857059 |
randomize( int myid, int numProcs, int minSize, int maxSize, int maxIters )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int i, size, partner, sendMode, numRecords, iters;
|
|
Packit |
857059 |
int retCode = MPI_SUCCESS;
|
|
Packit |
857059 |
RandomRecord records[NUMRANDXFERS];
|
|
Packit |
857059 |
MPI_Request request[NUMRANDXFERS];
|
|
Packit |
857059 |
MPI_Status status[NUMRANDXFERS];
|
|
Packit |
857059 |
unsigned char *rawBuffer = NULL; /* Array of buffer+barrier memory
|
|
Packit |
857059 |
* regions. */
|
|
Packit |
857059 |
unsigned char *buffer = NULL; /* Pointer into rawBuffer. */
|
|
Packit |
857059 |
unsigned int totalBufferSize = BARRIERSIZE * 2 + maxSize;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ROOTPRINT( "Beginning Randomize Test Section\n" );
|
|
Packit |
857059 |
ROOTPRINT( "(Node sends random length messages to each other.)\n" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
initrandom( );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
memset( request, 0, sizeof( MPI_Request ) * NUMRANDXFERS );
|
|
Packit |
857059 |
memset( status, 0, sizeof( MPI_Status ) * NUMRANDXFERS );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
sendMode = ( myid % 2 ) == 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( sendMode ) {
|
|
Packit |
857059 |
partner = myid + 1;
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
partner = myid - 1;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
rawBuffer = malloc( totalBufferSize );
|
|
Packit |
857059 |
if ( !rawBuffer ) {
|
|
Packit |
857059 |
ERRPRINT( "Failed to allocate buffers.\n" );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
buffer = rawBuffer + BARRIERSIZE;
|
|
Packit |
857059 |
size = minSize;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
while ( size <= maxSize ) {
|
|
Packit |
857059 |
int round = 0;
|
|
Packit |
857059 |
iters = maxIters;
|
|
Packit |
857059 |
while ( iters > 0 ) {
|
|
Packit |
857059 |
/* Initialize the buffer to our rank as a pad value. */
|
|
Packit |
857059 |
memset( rawBuffer, myid, totalBufferSize );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( sendMode ) {
|
|
Packit |
857059 |
/* Initialize the buffer with some random data. */
|
|
Packit |
857059 |
/* Every 4th byte is a check sum of the previous 3. */
|
|
Packit |
857059 |
for ( i = 0; i < ( size - 3 ); i += 4 ) {
|
|
Packit |
857059 |
buffer[i] = random( ) % 256;
|
|
Packit |
857059 |
buffer[i + 1] = random( ) % 256;
|
|
Packit |
857059 |
buffer[i + 2] = random( ) % 256;
|
|
Packit |
857059 |
buffer[i + 3] =
|
|
Packit |
857059 |
( buffer[i] + buffer[i + 1] + buffer[i + 2] ) % 256;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Build a list of randomly sized messages to send. */
|
|
Packit |
857059 |
/* Note that we effectively "null terminate" the list. */
|
|
Packit |
857059 |
memset( records, 0, sizeof( RandomRecord ) * NUMRANDXFERS );
|
|
Packit |
857059 |
i = 0;
|
|
Packit |
857059 |
numRecords = 0;
|
|
Packit |
857059 |
while ( i < size ) {
|
|
Packit |
857059 |
records[numRecords].start = i;
|
|
Packit |
857059 |
records[numRecords].length = RANDOMLEN( );
|
|
Packit |
857059 |
if ( records[numRecords].length + i > size ) {
|
|
Packit |
857059 |
records[numRecords].length = size - i;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
i += records[numRecords].length;
|
|
Packit |
857059 |
numRecords++;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Note that numRecords is now the length of records. */
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Swap a few records, for extra evil. */
|
|
Packit |
857059 |
i = random( ) % SHUFFLERATE;
|
|
Packit |
857059 |
while ( i < NUMRANDXFERS && records[i].length ) {
|
|
Packit |
857059 |
unsigned int j;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
j = i + ( random( ) % SHUFFLERATE );
|
|
Packit |
857059 |
if ( ( j != i ) && ( j < NUMRANDXFERS )
|
|
Packit |
857059 |
&& ( records[j].length ) ) {
|
|
Packit |
857059 |
RandomRecord r;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
r.start = records[j].start;
|
|
Packit |
857059 |
r.length = records[j].length;
|
|
Packit |
857059 |
records[j].start = records[i].start;
|
|
Packit |
857059 |
records[j].length = records[i].length;
|
|
Packit |
857059 |
records[i].start = r.start;
|
|
Packit |
857059 |
records[i].length = r.length;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
i = j;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Dump a list of the records. */
|
|
Packit |
857059 |
if ( verboseMode ) {
|
|
Packit |
857059 |
for ( i = 0; ( i < NUMRANDXFERS ) && ( records[i].length );
|
|
Packit |
857059 |
i++ ) {
|
|
Packit |
857059 |
NODEPRINT( "X %d - %d\n", records[i].start,
|
|
Packit |
857059 |
records[i].length );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Send the record list to our partner. */
|
|
Packit |
857059 |
retCode = MPI_Send( records,
|
|
Packit |
857059 |
NUMRANDXFERS * sizeof( RandomRecord ),
|
|
Packit |
857059 |
MPI_BYTE, partner, 0, MPI_COMM_WORLD );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for ( i = 0; ( i < NUMRANDXFERS ) && ( records[i].length );
|
|
Packit |
857059 |
i++ ) {
|
|
Packit |
857059 |
NODEPRINT( "S %d - %x\n", records[i].start,
|
|
Packit |
857059 |
records[i].length );
|
|
Packit |
857059 |
retCode = MPI_Isend( &buffer[records[i].start],
|
|
Packit |
857059 |
records[i].length,
|
|
Packit |
857059 |
MPI_BYTE, partner, i, MPI_COMM_WORLD,
|
|
Packit |
857059 |
&request[i] );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
round++;
|
|
Packit |
857059 |
if (!verboseMode && (round % 100) == 0)
|
|
Packit |
857059 |
ROOTPRINT(".");
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
/* Get the record list from our partner. */
|
|
Packit |
857059 |
retCode = MPI_Recv( records,
|
|
Packit |
857059 |
NUMRANDXFERS * sizeof( RandomRecord ),
|
|
Packit |
857059 |
MPI_BYTE,
|
|
Packit |
857059 |
partner, 0, MPI_COMM_WORLD, &status[0] );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for ( i = 0; ( i < NUMRANDXFERS ) && ( records[i].length );
|
|
Packit |
857059 |
i++ ) {
|
|
Packit |
857059 |
NODEPRINT( "R %d - %x\n", records[i].start,
|
|
Packit |
857059 |
records[i].length );
|
|
Packit |
857059 |
retCode = MPI_Irecv( &buffer[records[i].start],
|
|
Packit |
857059 |
records[i].length,
|
|
Packit |
857059 |
MPI_BYTE, partner, i, MPI_COMM_WORLD,
|
|
Packit |
857059 |
&request[i] );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
numRecords = i; /* Save the # of records. */
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
retCode = MPI_Waitall( numRecords, request, status );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
for ( i = 0; i < numRecords; i++ ) {
|
|
Packit |
857059 |
ERRABORT( status[i].MPI_ERROR );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Check for corruption. */
|
|
Packit |
857059 |
if ( !sendMode ) {
|
|
Packit |
857059 |
for ( i = 0; i < ( size - 3 ); i += 4 ) {
|
|
Packit |
857059 |
unsigned char c =
|
|
Packit |
857059 |
( buffer[i] + buffer[i + 1] + buffer[i + 2] ) % 256;
|
|
Packit |
857059 |
if ( c != buffer[i + 3] ) {
|
|
Packit |
857059 |
ERRPRINT( "Corruption in the buffer @ %d\n", i );
|
|
Packit |
857059 |
dumpbuffer( myid, "rawBuffer", (char*)rawBuffer,
|
|
Packit |
857059 |
size + 2 * BARRIERSIZE );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
iters -= numRecords;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ROOTPRINT( "\t%8d\n", size );
|
|
Packit |
857059 |
size *= 2;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Barrier( MPI_COMM_WORLD );
|
|
Packit |
857059 |
ROOTPRINT( "Completed Randomize Test Section.\n\n" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
done:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( rawBuffer )
|
|
Packit |
857059 |
free( rawBuffer );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return retCode;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Calculate the average time to complete MPI_Init.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
#define HOSTNAMELEN 32
|
|
Packit |
857059 |
#define HOSTOFFSET 8
|
|
Packit |
857059 |
int
|
|
Packit |
857059 |
calc_init_time( int myid, int numProcs, time_t t_start, time_t t_end,
|
|
Packit |
857059 |
time_t * t_avg )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
time_t t_delta, t_min, t_max, t_temp;
|
|
Packit |
857059 |
int i, retCode = MPI_SUCCESS;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( myid != 0 ) {
|
|
Packit |
857059 |
/* Send our time to init back to the 0 node. */
|
|
Packit |
857059 |
char mydata[HOSTNAMELEN + HOSTOFFSET];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Build a buffer containing our host name and the elapsed time. */
|
|
Packit |
857059 |
t_delta = t_end - t_start;
|
|
Packit |
857059 |
*( ( time_t * ) mydata ) = t_delta;
|
|
Packit |
857059 |
gethostname( &mydata[HOSTOFFSET], HOSTNAMELEN );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
mydata[HOSTOFFSET + HOSTNAMELEN - 1] = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
retCode = MPI_Send( mydata,
|
|
Packit |
857059 |
HOSTNAMELEN + HOSTOFFSET, MPI_CHAR, 0, 0,
|
|
Packit |
857059 |
MPI_COMM_WORLD );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
/* Collect time to init data. */
|
|
Packit |
857059 |
MPI_Status status;
|
|
Packit |
857059 |
char curdata[HOSTNAMELEN + HOSTOFFSET];
|
|
Packit |
857059 |
char min_host[HOSTNAMELEN];
|
|
Packit |
857059 |
char max_host[HOSTNAMELEN];
|
|
Packit |
857059 |
double avg;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Initially the root is both best and worst. */
|
|
Packit |
857059 |
gethostname( min_host, HOSTNAMELEN );
|
|
Packit |
857059 |
gethostname( max_host, HOSTNAMELEN );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
t_delta = t_end - t_start;
|
|
Packit |
857059 |
t_min = t_delta;
|
|
Packit |
857059 |
t_max = t_delta;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* We don't care what order the replies come in,
|
|
Packit |
857059 |
* as long as we get them all.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
for ( i = 0; i < numProcs - 1; i++ ) {
|
|
Packit |
857059 |
memset( &status, 0, sizeof( status ) );
|
|
Packit |
857059 |
retCode = MPI_Recv( curdata,
|
|
Packit |
857059 |
HOSTNAMELEN + HOSTOFFSET, MPI_CHAR,
|
|
Packit |
857059 |
MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
t_temp = *( ( time_t * ) curdata );
|
|
Packit |
857059 |
t_delta += t_temp;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( t_temp < t_min ) {
|
|
Packit |
857059 |
t_min = t_temp;
|
|
Packit |
857059 |
strcpy( min_host, &curdata[HOSTOFFSET] );
|
|
Packit |
857059 |
} else if ( t_temp > t_max ) {
|
|
Packit |
857059 |
t_max = t_temp;
|
|
Packit |
857059 |
strcpy( max_host, &curdata[HOSTOFFSET] );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
avg = ( double ) t_delta / ( double ) numProcs;
|
|
Packit |
857059 |
ROOTPRINT( "Maximum time to init was: %8ld seconds (%s).\n",
|
|
Packit |
857059 |
t_max, max_host );
|
|
Packit |
857059 |
ROOTPRINT( "Minimum time to init was: %8ld seconds (%s).\n",
|
|
Packit |
857059 |
t_min, min_host );
|
|
Packit |
857059 |
ROOTPRINT( "Average time to init was: %8.2lf seconds.\n", avg );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return retCode;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Simple whisper down the lane test. Rank 0 sends a message to rank 1,
|
|
Packit |
857059 |
* who passes it to 2, etc., till rank N returns it to rank 0. At that
|
|
Packit |
857059 |
* point, it is compared against what was sent.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* This code is made more complicated by the desire to mangle memory
|
|
Packit |
857059 |
* usage in order to uncover possible corruption issues. If useSendOffset
|
|
Packit |
857059 |
* is specified, each successive round moves the buffer one byte higher
|
|
Packit |
857059 |
* in memory. In addition, if rawBufferCount is > 1, the code will use
|
|
Packit |
857059 |
* multiple buffers in a ring. This is primarily to cause an increase in
|
|
Packit |
857059 |
* total memory consumption to induce paging operations, which can affect
|
|
Packit |
857059 |
* memory transfers to/from the HCA.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
int
|
|
Packit |
857059 |
slowRing( int myid, int numProcs, int minSize, int maxSize, int maxIters )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
unsigned int i, size, iters, round;
|
|
Packit |
857059 |
int retCode = MPI_SUCCESS;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Request *request = NULL;
|
|
Packit |
857059 |
MPI_Status *status = NULL;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
char **rawSendBuffer = NULL;
|
|
Packit |
857059 |
char **rawRecvBuffer = NULL;
|
|
Packit |
857059 |
char *sendBuffer, *recvBuffer;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
request = malloc( sizeof( MPI_Request ) );
|
|
Packit |
857059 |
status = malloc( sizeof( MPI_Status ) );
|
|
Packit |
857059 |
if ( !request || !status ) {
|
|
Packit |
857059 |
ERRPRINT( "Failed to allocate requests and status.\n" );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
memset( request, 0, sizeof( MPI_Request ) );
|
|
Packit |
857059 |
memset( status, 0, sizeof( MPI_Status ) );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
rawSendBuffer = malloc( sizeof( char * ) * rawBufferCount );
|
|
Packit |
857059 |
rawRecvBuffer = malloc( sizeof( char * ) * rawBufferCount );
|
|
Packit |
857059 |
memset( rawSendBuffer, 0, sizeof( char * ) * rawBufferCount );
|
|
Packit |
857059 |
memset( rawRecvBuffer, 0, sizeof( char * ) * rawBufferCount );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ROOTPRINT( "Beginning Slow Ring Test Section\n" );
|
|
Packit |
857059 |
ROOTPRINT( "(This test passes messages from node to node in a ring\n"
|
|
Packit |
857059 |
"and validates that the end result matches the original\n"
|
|
Packit |
857059 |
"message.)\n" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
size = minSize;
|
|
Packit |
857059 |
iters = maxIters;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
while ( size <= maxSize ) {
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for ( round = 0; round < iters; round++ ) {
|
|
Packit |
857059 |
size_t rawBufferSize =
|
|
Packit |
857059 |
( barrierSize * 2 ) + ( size + ( useSendOffset ? round : 0 ) );
|
|
Packit |
857059 |
char *currentRawSendBuffer;
|
|
Packit |
857059 |
char *currentRawRecvBuffer;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* If we already had a buffer here, we free it then
|
|
Packit |
857059 |
* reallocate it. In a sane world, we will normally
|
|
Packit |
857059 |
* get the same memory back again, but this could also
|
|
Packit |
857059 |
* trigger various "optimizations" in malloc's handling
|
|
Packit |
857059 |
* of the heap and the operating system's handling of
|
|
Packit |
857059 |
* the page table - and it stresses any malloc management
|
|
Packit |
857059 |
* magic in MPI itself...
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
if ( rawSendBuffer[round % rawBufferCount] != NULL ) {
|
|
Packit |
857059 |
free( rawSendBuffer[round % rawBufferCount] );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
rawSendBuffer[round % rawBufferCount] = malloc( rawBufferSize );
|
|
Packit |
857059 |
if ( rawRecvBuffer[round % rawBufferCount] != NULL ) {
|
|
Packit |
857059 |
free( rawRecvBuffer[round % rawBufferCount] );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
rawRecvBuffer[round % rawBufferCount] = malloc( rawBufferSize );
|
|
Packit |
857059 |
if ( !rawRecvBuffer[round % rawBufferCount]
|
|
Packit |
857059 |
|| !rawSendBuffer[round % rawBufferCount] ) {
|
|
Packit |
857059 |
ERRPRINT( "Failed to allocate buffers.\n" );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
currentRawSendBuffer = rawSendBuffer[round % rawBufferCount];
|
|
Packit |
857059 |
currentRawRecvBuffer = rawRecvBuffer[round % rawBufferCount];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
sendBuffer =
|
|
Packit |
857059 |
currentRawSendBuffer + barrierSize +
|
|
Packit |
857059 |
( useSendOffset ? round : 0 );
|
|
Packit |
857059 |
recvBuffer =
|
|
Packit |
857059 |
currentRawRecvBuffer + barrierSize +
|
|
Packit |
857059 |
( useSendOffset ? round : 0 );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Setting up guard areas to check for corruption.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
memset( currentRawSendBuffer, myid, rawBufferSize );
|
|
Packit |
857059 |
memset( currentRawRecvBuffer, myid, rawBufferSize );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Create some data to send and validate against. */
|
|
Packit |
857059 |
for ( i = 0; i < size; i++ )
|
|
Packit |
857059 |
sendBuffer[i] = ( unsigned char ) ( i % 256 );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( myid == 0 ) {
|
|
Packit |
857059 |
/* Root initiates the loop and vets the results. */
|
|
Packit |
857059 |
NODEPRINT( "S node 1\n" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
retCode =
|
|
Packit |
857059 |
MPI_Send( sendBuffer, size, MPI_CHAR, 1, round,
|
|
Packit |
857059 |
MPI_COMM_WORLD );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
NODEPRINT( "W node %d\n", numProcs - 1 );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
retCode = MPI_Recv( recvBuffer,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
numProcs - 1,
|
|
Packit |
857059 |
round, MPI_COMM_WORLD, status );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( memcmp( currentRawSendBuffer,
|
|
Packit |
857059 |
currentRawRecvBuffer, rawBufferSize ) ) {
|
|
Packit |
857059 |
ERRPRINT( "%d byte messages do not match!\n", size );
|
|
Packit |
857059 |
dumpbuffer( myid, "rawSendBuffer", currentRawSendBuffer,
|
|
Packit |
857059 |
rawBufferSize );
|
|
Packit |
857059 |
dumpbuffer( myid, "rawRecvBuffer", currentRawRecvBuffer,
|
|
Packit |
857059 |
rawBufferSize );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
/* Everyone else waits for a message and then repeats it to
|
|
Packit |
857059 |
* their neighbor. */
|
|
Packit |
857059 |
NODEPRINT( "W node %d\n", myid - 1 );
|
|
Packit |
857059 |
retCode = MPI_Recv( recvBuffer,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
myid - 1, round, MPI_COMM_WORLD, status );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
NODEPRINT( "S node %d\n", myid + 1 );
|
|
Packit |
857059 |
retCode = MPI_Send( recvBuffer,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
( myid + 1 ) % numProcs,
|
|
Packit |
857059 |
round, MPI_COMM_WORLD );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Note that we never sent SendBuffer but it should still
|
|
Packit |
857059 |
* be a correct model of what we actually received then
|
|
Packit |
857059 |
* sent.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
if ( memcmp( currentRawSendBuffer,
|
|
Packit |
857059 |
currentRawRecvBuffer, rawBufferSize ) ) {
|
|
Packit |
857059 |
ERRPRINT( "%d byte messages do not match!\n", size );
|
|
Packit |
857059 |
dumpbuffer( myid, "rawSendBuffer", currentRawSendBuffer,
|
|
Packit |
857059 |
rawBufferSize );
|
|
Packit |
857059 |
dumpbuffer( myid, "rawRecvBuffer", currentRawRecvBuffer,
|
|
Packit |
857059 |
rawBufferSize );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( !verboseMode && ( round % 100 ) == 0 )
|
|
Packit |
857059 |
ROOTPRINT( "." );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
ROOTPRINT( "\t%8d\n", size );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
size *= 2;
|
|
Packit |
857059 |
iters = ( iters > 1 ) ? iters / 2 : 1;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ROOTPRINT( "Completed Slow Ring Test Section.\n\n" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
done:
|
|
Packit |
857059 |
if ( rawRecvBuffer ) {
|
|
Packit |
857059 |
for ( i = 0; i < rawBufferCount; i++ ) {
|
|
Packit |
857059 |
if ( rawRecvBuffer[i] ) {
|
|
Packit |
857059 |
free( rawRecvBuffer[i] );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
free( rawRecvBuffer );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( rawSendBuffer ) {
|
|
Packit |
857059 |
for ( i = 0; i < rawBufferCount; i++ ) {
|
|
Packit |
857059 |
if ( rawSendBuffer[i] ) {
|
|
Packit |
857059 |
free( rawSendBuffer[i] );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
free( rawSendBuffer );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( request )
|
|
Packit |
857059 |
free( request );
|
|
Packit |
857059 |
if ( status )
|
|
Packit |
857059 |
free( status );
|
|
Packit |
857059 |
return retCode;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Fast whisper down the lane test. Rank 0 sends many messages to rank 1,
|
|
Packit |
857059 |
* who passes them to 2, etc., till rank N returns them to rank 0. At that
|
|
Packit |
857059 |
* point, the messages are compared against what was sent.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
int
|
|
Packit |
857059 |
fastRing( int myid, int numProcs, int minSize, int maxSize, int maxIters )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
unsigned int i, j, size, iters, round;
|
|
Packit |
857059 |
int retCode = MPI_SUCCESS;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
MPI_Request *request = NULL;
|
|
Packit |
857059 |
MPI_Status *status = NULL;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
char **rawSendBuffer = NULL;
|
|
Packit |
857059 |
char **rawRecvBuffer = NULL;
|
|
Packit |
857059 |
char *sendBuffer, *recvBuffer;
|
|
Packit |
857059 |
size_t rawBufferSize =
|
|
Packit |
857059 |
( barrierSize * 2 ) + ( maxSize + ( useSendOffset ? maxIters : 0 ) );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
request = malloc( (rawBufferCount+maxIters) * sizeof( MPI_Request ) );
|
|
Packit |
857059 |
status = malloc( (rawBufferCount+maxIters) * sizeof( MPI_Status ) );
|
|
Packit |
857059 |
if ( !request || !status ) {
|
|
Packit |
857059 |
ERRPRINT( "Failed to allocate requests and status.\n" );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
memset( request, 0, (rawBufferCount+maxIters) * sizeof( MPI_Request ) );
|
|
Packit |
857059 |
memset( status, 0, (rawBufferCount+maxIters) * sizeof( MPI_Status ) );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
rawSendBuffer = malloc( sizeof( char * ) * rawBufferCount );
|
|
Packit |
857059 |
rawRecvBuffer = malloc( sizeof( char * ) * rawBufferCount );
|
|
Packit |
857059 |
memset( rawSendBuffer, 0, sizeof( char * ) * rawBufferCount );
|
|
Packit |
857059 |
memset( rawRecvBuffer, 0, sizeof( char * ) * rawBufferCount );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for ( i = 0; i < rawBufferCount; i++ ) {
|
|
Packit |
857059 |
rawSendBuffer[i] = malloc( rawBufferSize );
|
|
Packit |
857059 |
rawRecvBuffer[i] = malloc( rawBufferSize );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( !rawRecvBuffer[i] || !rawSendBuffer[i] ) {
|
|
Packit |
857059 |
ERRPRINT( "Failed to allocate buffers.\n" );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ROOTPRINT( "Beginning Fast Ring Test Section\n" );
|
|
Packit |
857059 |
ROOTPRINT( "(This test passes multiple messages from node to node in a\n"
|
|
Packit |
857059 |
"ring and validates that the end result matches the original\n"
|
|
Packit |
857059 |
"message.)\n" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
size = minSize;
|
|
Packit |
857059 |
iters = maxIters;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
while ( size <= maxSize ) {
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( myid == 0 ) {
|
|
Packit |
857059 |
for ( j = 0; j < rawBufferCount; j++) {
|
|
Packit |
857059 |
char *currentRawSendBuffer = rawSendBuffer[j];
|
|
Packit |
857059 |
char *currentRawRecvBuffer = rawRecvBuffer[j];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Setting up guard areas to check for corruption.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
memset( currentRawSendBuffer, myid, rawBufferSize );
|
|
Packit |
857059 |
memset( currentRawRecvBuffer, myid, rawBufferSize );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
sendBuffer = currentRawSendBuffer + barrierSize;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Create some data to send and validate against. */
|
|
Packit |
857059 |
for ( i = 0; i < size; i++ )
|
|
Packit |
857059 |
sendBuffer[i] = ( unsigned char ) ( i % 256 );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for ( round = 0; round < iters; round+= rawBufferCount ) {
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Fire in the hole! */
|
|
Packit |
857059 |
for (j = 0; j
|
|
Packit |
857059 |
char *currentRawSendBuffer = rawSendBuffer[j];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
sendBuffer = currentRawSendBuffer + barrierSize;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
NODEPRINT( "S node 1\n" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
retCode = MPI_Isend( sendBuffer, size, MPI_CHAR, 1,
|
|
Packit |
857059 |
round + j,
|
|
Packit |
857059 |
MPI_COMM_WORLD,
|
|
Packit |
857059 |
&request[round+j] );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Process the messages as they come home. */
|
|
Packit |
857059 |
for ( j = 0; j < rawBufferCount; j++ ) {
|
|
Packit |
857059 |
char *currentRawRecvBuffer = rawRecvBuffer[j];
|
|
Packit |
857059 |
char *currentRawSendBuffer = rawSendBuffer[j];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
recvBuffer = currentRawRecvBuffer + barrierSize +
|
|
Packit |
857059 |
( useSendOffset ? (round + j) : 0 );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
NODEPRINT( "W node %d / %p \n", numProcs - 1, recvBuffer );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
retCode = MPI_Recv( recvBuffer,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
numProcs - 1,
|
|
Packit |
857059 |
round+j,
|
|
Packit |
857059 |
MPI_COMM_WORLD,
|
|
Packit |
857059 |
&(status[round+j]) );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( memcmp( currentRawSendBuffer, currentRawRecvBuffer,
|
|
Packit |
857059 |
rawBufferSize ) ) {
|
|
Packit |
857059 |
ERRPRINT( "%d byte messages do not match!\n", size );
|
|
Packit |
857059 |
dumpbuffer( myid, "rawSendBuffer", currentRawSendBuffer,
|
|
Packit |
857059 |
rawBufferSize );
|
|
Packit |
857059 |
dumpbuffer( myid, "rawRecvBuffer", currentRawRecvBuffer,
|
|
Packit |
857059 |
rawBufferSize );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( !verboseMode && ( (round+j) % 100 ) == 0 )
|
|
Packit |
857059 |
ROOTPRINT( "." );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
unsigned iters2 = iters;
|
|
Packit |
857059 |
if ((iters % rawBufferCount) != 0)
|
|
Packit |
857059 |
iters2 += (rawBufferCount - (iters % rawBufferCount));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Everyone else waits for a message and then repeats it to their
|
|
Packit |
857059 |
* neighbor. */
|
|
Packit |
857059 |
for ( round = 0; round < iters2; round++ ) {
|
|
Packit |
857059 |
char *currentRawSendBuffer =
|
|
Packit |
857059 |
rawSendBuffer[round % rawBufferCount];
|
|
Packit |
857059 |
char *currentRawRecvBuffer =
|
|
Packit |
857059 |
rawRecvBuffer[round % rawBufferCount];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
sendBuffer = currentRawSendBuffer + barrierSize;
|
|
Packit |
857059 |
recvBuffer = currentRawRecvBuffer + barrierSize;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Setting up guard areas to check for corruption.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
memset( currentRawSendBuffer, myid, rawBufferSize );
|
|
Packit |
857059 |
memset( currentRawRecvBuffer, myid, rawBufferSize );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* Create some data to send and validate against. */
|
|
Packit |
857059 |
for ( i = 0; i < size; i++ )
|
|
Packit |
857059 |
sendBuffer[i] = ( unsigned char ) ( i % 256 );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
NODEPRINT( "W node %d\n", myid - 1 );
|
|
Packit |
857059 |
retCode = MPI_Recv( recvBuffer,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
myid - 1, round, MPI_COMM_WORLD, status );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
NODEPRINT( "S node %d\n", myid + 1 );
|
|
Packit |
857059 |
retCode = MPI_Send( recvBuffer,
|
|
Packit |
857059 |
size,
|
|
Packit |
857059 |
MPI_CHAR,
|
|
Packit |
857059 |
( myid + 1 ) % numProcs,
|
|
Packit |
857059 |
round, MPI_COMM_WORLD );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
* Note that we never sent SendBuffer but it should still
|
|
Packit |
857059 |
* be a correct model of what we actually received then
|
|
Packit |
857059 |
* sent.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
if ( memcmp( currentRawSendBuffer,
|
|
Packit |
857059 |
currentRawRecvBuffer, rawBufferSize ) ) {
|
|
Packit |
857059 |
ERRPRINT( "%d byte messages do not match!\n", size );
|
|
Packit |
857059 |
dumpbuffer( myid, "rawSendBuffer", currentRawSendBuffer,
|
|
Packit |
857059 |
rawBufferSize );
|
|
Packit |
857059 |
dumpbuffer( myid, "rawRecvBuffer", currentRawRecvBuffer,
|
|
Packit |
857059 |
rawBufferSize );
|
|
Packit |
857059 |
retCode = ~MPI_SUCCESS;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
ROOTPRINT( "\t%8d\n", size );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
size *= 2;
|
|
Packit |
857059 |
iters = ( iters > 1 ) ? iters / 2 : 1;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ROOTPRINT( "Completed Fast Ring Test Section.\n\n" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
done:
|
|
Packit |
857059 |
if ( rawRecvBuffer ) {
|
|
Packit |
857059 |
for ( i = 0; i < rawBufferCount; i++ ) {
|
|
Packit |
857059 |
if ( rawRecvBuffer[i] ) {
|
|
Packit |
857059 |
free( rawRecvBuffer[i] );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
free( rawRecvBuffer );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( rawSendBuffer ) {
|
|
Packit |
857059 |
for ( i = 0; i < rawBufferCount; i++ ) {
|
|
Packit |
857059 |
if ( rawSendBuffer[i] ) {
|
|
Packit |
857059 |
free( rawSendBuffer[i] );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
free( rawSendBuffer );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( request )
|
|
Packit |
857059 |
free( request );
|
|
Packit |
857059 |
if ( status )
|
|
Packit |
857059 |
free( status );
|
|
Packit |
857059 |
return retCode;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
int
|
|
Packit |
857059 |
main( int argc, char *argv[] )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int retCode, myid, numProcs, i;
|
|
Packit |
857059 |
time_t t1, t2, t3;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
t1 = time( NULL );
|
|
Packit |
857059 |
MPI_Init( &argc, &argv );
|
|
Packit |
857059 |
MPI_Comm_size( MPI_COMM_WORLD, &numProcs );
|
|
Packit |
857059 |
MPI_Comm_rank( MPI_COMM_WORLD, &myid );
|
|
Packit |
857059 |
t2 = time( NULL );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
while ( -1 !=
|
|
Packit |
857059 |
( retCode = getopt_long_only( argc, argv, "", options, &i ) ) ) {
|
|
Packit |
857059 |
switch ( retCode ) {
|
|
Packit |
857059 |
case '<':
|
|
Packit |
857059 |
minSize = strtoul( optarg, NULL, 0 );
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
case '>':
|
|
Packit |
857059 |
maxSize = strtoul( optarg, NULL, 0 );
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
case 'i':
|
|
Packit |
857059 |
maxIters = strtoul( optarg, NULL, 0 );
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
case 'b':
|
|
Packit |
857059 |
rawBufferCount = strtoul( optarg, NULL, 0 );
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
case 'B':
|
|
Packit |
857059 |
barrierSize = strtoul( optarg, NULL, 0 );
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
case '?':
|
|
Packit |
857059 |
usage( );
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ROOTPRINT( "-----------------------------\n" );
|
|
Packit |
857059 |
ROOTPRINT( "-----------------------------\n" );
|
|
Packit |
857059 |
ROOTPRINT( "Initialization complete.\n" );
|
|
Packit |
857059 |
MPI_Barrier( MPI_COMM_WORLD );
|
|
Packit |
857059 |
retCode = calc_init_time( myid, numProcs, t1, t2, &t3 );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ROOTPRINT( "--------------------------\n" );
|
|
Packit |
857059 |
ROOTPRINT( "--------------------------\n" );
|
|
Packit |
857059 |
ROOTPRINT( "Number of nodes = %d\n", numProcs );
|
|
Packit |
857059 |
ROOTPRINT( "Minimum message size = %d\n", minSize );
|
|
Packit |
857059 |
ROOTPRINT( "Maximum message size = %d\n", maxSize );
|
|
Packit |
857059 |
ROOTPRINT( "Maximum # of rounds = %d\n\n", maxIters );
|
|
Packit |
857059 |
ROOTPRINT( "Use Message Send Offset = %s\n", useSendOffset ? "ON" : "OFF" );
|
|
Packit |
857059 |
ROOTPRINT( "Message Buffer Count = %d\n", rawBufferCount );
|
|
Packit |
857059 |
ROOTPRINT( "Message Barrier Size = %d\n\n", barrierSize );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( doSlow ) {
|
|
Packit |
857059 |
MPI_Barrier( MPI_COMM_WORLD );
|
|
Packit |
857059 |
retCode = slowRing( myid, numProcs, minSize, maxSize, maxIters );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if ( doFast ) {
|
|
Packit |
857059 |
MPI_Barrier( MPI_COMM_WORLD );
|
|
Packit |
857059 |
retCode = fastRing( myid, numProcs, minSize, maxSize, maxIters );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if ( doRandom ) {
|
|
Packit |
857059 |
MPI_Barrier( MPI_COMM_WORLD );
|
|
Packit |
857059 |
retCode = randomize( myid, numProcs, minSize, maxSize, maxIters );
|
|
Packit |
857059 |
ERRABORT( retCode );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ROOTPRINT( "--------------------------\n" );
|
|
Packit |
857059 |
ROOTPRINT( "--------------------------\n" );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
done:
|
|
Packit |
857059 |
MPI_Finalize( );
|
|
Packit |
857059 |
return retCode;
|
|
Packit |
857059 |
}
|