/************************************************************************** * * Subroutine C11 checks the result matrix C for accuracy. * * Parameters: * * Provided by calling routine: * C = Matrix of multiple precision numbers * MODULUS = Large integer modulus, expressed as an array of integers * N = The size of the matrices * M = The size of the sub-matrices on each PE * NUMSIZE = The number of words to store an MP integer * MODBITS = The number of bits in MODULUS * * The routine returns a value: * -1 Results for given input parameters are unknown * 0 No errors found * 1 Results do not agree with previous results * 2 MPI_GATHER failed, can't calc global hash * *************************************************************************** * * First determine if N and MODULUS are checkable. * The array NVAL has the 8 checkable values of N. * The array MODVAL has the hashes of the 10 checkable values of MODULUS. * (The hash is the low-order 40 bits added to the number of bits in MODULUS.) * * To check a result, sum all the entries in the matrix C, * reduce the sum mod MODULUS, and take the low order 40 bits. * This hash is compared with the value stored in the array HASHVAL. * c If running on more than 1 PE, each PE sums the entries of its subblock of C, c and reduces by MODULUS. Then gather all the local sums to PE0, which c adds them up, mods again, and then takes the low 40 bits. * **************************************************************************/ /* CVS info */ /* $Date: 2005/09/19 18:45:08 $ */ /* $Revision: 1.3 $ */ /* $RCSfile: c11.c,v $ */ /* $Name: rel_5 $ */ #include "bench11.h" #include static char cvs_info[] = "BMARKGRP $Date: 2005/09/19 18:45:08 $ $Revision: 1.3 $ $RCSfile: c11.c,v $ $Name: rel_5 $"; #define maxpes 256 /* these are here to make them non-stack, hence symmetric for shmem ops */ /* An array to accumulate the hash value on each PE */ mplong hash [ maxnumsize + 2 ]; /* An array to gather the hash values of the sub-matrices */ mplong hashes [maxpes][maxnumsize + 1]; /* This conditional compile flag (if set to *0*) lets us compute new check values for additional dimension or modulus */ #define CHECKVALS 1 /* macro to address 3-dim array with variable dimension */ #define c(I,J,K) c[ K + numsize * ( (J) + m * (I) ) ] int c11 ( mplong c[], mplong modulus[], mplong * checksum, int n, int m, int numsize, int modbits ) { int i, j, matsizeind = -1, modvalind = -1; int retval = 0; int mpierr; mplong hashmod; /* The checkable values for N */ const int matsize[8] = { 5, 25, 100, 225, 256, 512, 640, 1024 }; /* The hashes of the checkable values for the modulus (defined in m11.c) */ const unsigned mplong modval[10] = { 769620223922, 1099511627864, 1099511627902, 837833903585, 437966830978, 662963509255, 1099511628287, 905988786803, 235144688006, 773679418188 }; /* The check values for the 8 choices of N and 10 choices of Modulus */ const mplong hashval[10][8] = { { 196701556000, 43947186305, 415954941181, 431191719692, 75966428156, 212736108236, 581788714223, 930414141506 }, { 339405043757, 854026220207, 596320431790, 1011062447332, 1081646558404, 17515865229, 944700882948, 900606735395 }, { 970101264310, 1015647515594, 604848150241, 321147114478, 1072606644286, 324925765912, 479507642392, 824083076377 }, { 128205667170, 413366486950, 255765451886, 413706993346, 173612401038, 221996879184, 524037383687, 547023462324 }, { 997398669265, 643552455682, 214037984995, 109566680042, 644894836631, 172264824793, 797513203513, 1083418379931 }, { 697693377693, 859802640872, 67608713549, 335746255143, 569373860052, 655903367024, 361907535629, 550547090012 }, { 182948179528, 1006573637617, 1053609606664, 79021183210, 988912737077, 523823096749, 218881285726, 793488743659 }, { 645006580755, 82070920319, 830040110368, 565923891462, 642105336411, 1030224153636, 953815689861, 152957459606 }, { 597097122329, 318139893111, 905362215347, 474532250137, 638324121124, 702180515800, 41936885391, 491109852649 }, { 719199877913, 925428265878, 549095547958, 28967597754, 747817176566, 820228776254, 678070998066, 980791895706 } }; const mplong hashmask = 0xFFFFFFFFFF; // 40 bits extern int npes, mype, verbose; if (verbose) { printf( "CALL C11(%d, MODULUS, -, -) \n", n ); printf( " (Check the results) \n" ); } /* This conditional compile (if 0) lets us compute new check values for additional dimension or modulus */ #if CHECKVALS /* Check to see if the size of the matrices can be checked */ for ( i = 0; i < 8; i++ ) { if (n == matsize[i]) { matsizeind = i; break; } } if (matsizeind == -1) { if (verbose) printf( "Matrix Size not found. Cannot check results.\n" ); retval = -1; } /* Hash the MODULUS - add low order 40 bits to number of bits */ hashmod = modulus[MPDATA]; #if (BITSPERWORD != 64) if ( MPGETSIZE ( modulus ) > 1 ) hashmod += modulus[MPDATA+1] << BITSPERWORD; #endif hashmod = ( hashmod & hashmask ) + modbits; /* Check to see if the modulus can be checked */ for ( i = 0; i < 10; i++ ) { if (hashmod == modval[i]) { modvalind = i; break; } } if (modvalind == -1) { if (verbose) printf( "Modulus not found. Cannot check results.\n" ); retval += -2; } #endif /* CHECKVALS */ /* * Compute the hash used to verify the accuracy of the answer. * The hash function adds all of the elements of the product matrix C, * reduces mod MODULUS, and uses the low order 40 bits as the hash. * * Here each PE adds and reduces its submatrix of C to get a sub-hash. */ /* First initialize HASH */ MPINIT ( hash, maxnumsize-1, 0 ); hash[MPDATA] = 0; /* Now add them all up */ for ( i = 0; i < m; i++) for ( j = 0; j < m; j++) { mpadd( hash, hash, &c(i,j,0) ); } /* Now reduce mod MODULUS */ mpmod( hash, hash, modulus ); /* If many PEs, gather all the sub-hashes to PE 0, add them up, mod again */ if (npes > 1) { int gathersize = (maxnumsize + 1) * intspermplong; mpierr = MPI_Gather ( hash, gathersize, MPI_INT, hashes, gathersize, MPI_INT, 0, MPI_COMM_WORLD ); if (mpierr) { if (verbose) printf( "MPI_GATHER failed, cannot check results.\n" ); return(2); } if (mype == 0) { for ( i = 1; i < npes; i++ ) { #ifdef GMP hashes[i][MPPTR] = (mplong) & hashes[i][MPDATA]; /*moved, fix ptr*/ #endif mpadd ( hash, hash, hashes[i] ); } mpmod( hash, hash, modulus ); } } /* npes > 1 */ /* Only PE0 does and checks final 40-bit hash */ if (mype == 0) { hashmod = hash[MPDATA]; #if (BITSPERWORD != 64) if ( MPGETSIZE ( hash ) > 1 ) hashmod += hash[MPDATA+1] << BITSPERWORD; #endif hashmod = hashmod & hashmask; *checksum = hashmod; /* return for printing */ #if CHECKVALS if (retval == 0) { if ( hashmod == hashval[modvalind][matsizeind] ) { if (verbose) printf( "Check successful \n" ); retval = 0; } else { if (verbose) printf( "Check not successful \n" ); retval = 1; } } #else /* print hash = new check value for new N or MODULUS */ printf( "HASH = %ld \n", hashmod ); #endif } /* mype == 0 */ return( retval ); }