|
PAPI
5.0.1.0
|
00001 /* 00002 * $Id$ 00003 * 00004 * Test example for multiplex functionality, originally 00005 * provided by Timothy Kaiser, SDSC. It was modified to fit the 00006 * PAPI test suite by Nils Smeds, <smeds@pdc.kth.se>. 00007 * 00008 * This example verifies the adding and removal of multiplexed 00009 * events in an event set. 00010 */ 00011 00012 #include "papi_test.h" 00013 #include <stdio.h> 00014 #include <math.h> 00015 #include <assert.h> 00016 00017 #define MAXEVENTS 9 00018 #define REPEATS (MAXEVENTS * 4) 00019 #define SLEEPTIME 100 00020 #define MINCOUNTS 100000 00021 00022 static double dummy3( double x, int iters ); 00023 00024 int 00025 main( int argc, char **argv ) 00026 { 00027 PAPI_event_info_t info; 00028 char name2[PAPI_MAX_STR_LEN]; 00029 int i, j, retval, idx, repeats; 00030 int iters = NUM_FLOPS; 00031 double x = 1.1, y, dtmp; 00032 long long t1, t2; 00033 long long values[MAXEVENTS], refvals[MAXEVENTS]; 00034 int nsamples[MAXEVENTS], truelist[MAXEVENTS], ntrue; 00035 #ifdef STARTSTOP 00036 long long dummies[MAXEVENTS]; 00037 #endif 00038 int sleep_time = SLEEPTIME; 00039 double valsample[MAXEVENTS][REPEATS]; 00040 double valsum[MAXEVENTS]; 00041 double avg[MAXEVENTS]; 00042 double spread[MAXEVENTS]; 00043 int nevents = MAXEVENTS, nev1; 00044 int eventset = PAPI_NULL; 00045 int events[MAXEVENTS]; 00046 int eventidx[MAXEVENTS]; 00047 int eventmap[MAXEVENTS]; 00048 int fails; 00049 00050 events[0] = PAPI_FP_INS; 00051 events[1] = PAPI_TOT_CYC; 00052 events[2] = PAPI_TOT_INS; 00053 events[3] = PAPI_TOT_IIS; 00054 events[4] = PAPI_INT_INS; 00055 events[5] = PAPI_STL_CCY; 00056 events[6] = PAPI_BR_INS; 00057 events[7] = PAPI_SR_INS; 00058 events[8] = PAPI_LD_INS; 00059 00060 for ( i = 0; i < MAXEVENTS; i++ ) { 00061 values[i] = 0; 00062 valsum[i] = 0; 00063 nsamples[i] = 0; 00064 } 00065 00066 if ( argc > 1 ) { 00067 if ( !strcmp( argv[1], "TESTS_QUIET" ) ) 00068 tests_quiet( argc, argv ); 00069 else { 00070 sleep_time = atoi( argv[1] ); 00071 if ( sleep_time <= 0 ) 00072 sleep_time = SLEEPTIME; 00073 } 00074 } 00075 00076 if ( !TESTS_QUIET ) { 00077 printf( "\nFunctional check of multiplexing routines.\n" ); 00078 printf( "Adding and removing events from an event set.\n\n" ); 00079 } 00080 00081 if ( ( retval = 00082 PAPI_library_init( PAPI_VER_CURRENT ) ) != PAPI_VER_CURRENT ) 00083 test_fail( __FILE__, __LINE__, "PAPI_library_init", retval ); 00084 00085 #ifdef MPX 00086 init_multiplex( ); 00087 #endif 00088 if ( ( retval = PAPI_create_eventset( &eventset ) ) ) 00089 test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval ); 00090 00091 #ifdef MPX 00092 00093 /* In Component PAPI, EventSets must be assigned a component index 00094 before you can fiddle with their internals. 00095 0 is always the cpu component */ 00096 retval = PAPI_assign_eventset_component( eventset, 0 ); 00097 if ( retval != PAPI_OK ) 00098 test_fail( __FILE__, __LINE__, "PAPI_assign_eventset_component", 00099 retval ); 00100 00101 if ( ( retval = PAPI_set_multiplex( eventset ) ) ) { 00102 if ( retval == PAPI_ENOSUPP) { 00103 test_skip(__FILE__, __LINE__, "Multiplex not supported", 1); 00104 } 00105 00106 test_fail( __FILE__, __LINE__, "PAPI_set_multiplex", retval ); 00107 } 00108 #endif 00109 00110 /* What does this code even do */ 00111 nevents = MAXEVENTS; 00112 for ( i = 0; i < nevents; i++ ) { 00113 if ( ( retval = PAPI_add_event( eventset, events[i] ) ) ) { 00114 for ( j = i; j < MAXEVENTS-1; j++ ) 00115 events[j] = events[j + 1]; 00116 nevents--; 00117 i--; 00118 } 00119 } 00120 if ( nevents < 3 ) 00121 test_skip( __FILE__, __LINE__, "Not enough events left...", 0 ); 00122 00123 /* Find a reasonable number of iterations (each 00124 * event active 20 times) during the measurement 00125 */ 00126 t2 = 10000 * 20 * nevents; /* Target: 10000 usec/multiplex, 20 repeats */ 00127 if ( t2 > 30e6 ) 00128 test_skip( __FILE__, __LINE__, "This test takes too much time", 00129 retval ); 00130 00131 /* Measure one run */ 00132 t1 = PAPI_get_real_usec( ); 00133 y = dummy3( x, iters ); 00134 t1 = PAPI_get_real_usec( ) - t1; 00135 00136 if ( t2 > t1 ) /* Scale up execution time to match t2 */ 00137 iters = iters * ( int ) ( t2 / t1 ); 00138 else if ( t1 > 30e6 ) /* Make sure execution time is < 30s per repeated test */ 00139 test_skip( __FILE__, __LINE__, "This test takes too much time", 00140 retval ); 00141 00142 j = nevents; 00143 for ( i = 1; i < nevents; i = i + 2 ) 00144 eventidx[--j] = i; 00145 for ( i = 0; i < nevents; i = i + 2 ) 00146 eventidx[--j] = i; 00147 assert( j == 0 ); 00148 for ( i = 0; i < nevents; i++ ) 00149 eventmap[i] = i; 00150 00151 x = 1.0; 00152 00153 if ( !TESTS_QUIET ) 00154 printf( "\nReference run:\n" ); 00155 00156 t1 = PAPI_get_real_usec( ); 00157 if ( ( retval = PAPI_start( eventset ) ) ) 00158 test_fail( __FILE__, __LINE__, "PAPI_start", retval ); 00159 y = dummy3( x, iters ); 00160 PAPI_read( eventset, refvals ); 00161 t2 = PAPI_get_real_usec( ); 00162 00163 ntrue = nevents; 00164 PAPI_list_events( eventset, truelist, &ntrue ); 00165 if ( !TESTS_QUIET ) { 00166 printf( "\tOperations= %.1f Mflop", y * 1e-6 ); 00167 printf( "\t(%g Mflop/s)\n\n", ( y / ( double ) ( t2 - t1 ) ) ); 00168 printf( "%20s %16s %-15s %-15s\n", "PAPI measurement:", 00169 "Acquired count", "Expected event", "PAPI_list_events" ); 00170 } 00171 00172 if ( !TESTS_QUIET ) { 00173 for ( j = 0; j < nevents; j++ ) { 00174 PAPI_get_event_info( events[j], &info ); 00175 PAPI_event_code_to_name( truelist[j], name2 ); 00176 if ( !TESTS_QUIET ) 00177 printf( "%20s = %16lld %-15s %-15s %s\n", info.short_descr, 00178 refvals[j], info.symbol, name2, strcmp( info.symbol, 00179 name2 ) ? 00180 "*** MISMATCH ***" : "" ); 00181 } 00182 printf( "\n" ); 00183 } 00184 00185 nev1 = nevents; 00186 repeats = nevents * 4; 00187 for ( i = 0; i < repeats; i++ ) { 00188 if ( ( i % nevents ) + 1 == nevents ) 00189 continue; 00190 00191 if ( !TESTS_QUIET ) 00192 printf( "\nTest %d (of %d):\n", i + 1 - i / nevents, repeats - 4 ); 00193 00194 if ( ( retval = PAPI_stop( eventset, values ) ) ) 00195 test_fail( __FILE__, __LINE__, "PAPI_stop", retval ); 00196 00197 j = eventidx[i % nevents]; 00198 00199 if ( ( i / nevents ) % 2 == 0 ) { 00200 PAPI_get_event_info( events[j], &info ); 00201 if ( !TESTS_QUIET ) 00202 printf( "Removing event[%d]: %s\n", j, info.short_descr ); 00203 if ( ( retval = PAPI_remove_event( eventset, events[j] ) ) ) 00204 test_fail( __FILE__, __LINE__, "PAPI_remove_event", retval ); 00205 nev1--; 00206 for ( idx = 0; eventmap[idx] != j; idx++ ); 00207 for ( j = idx; j < nev1; j++ ) 00208 eventmap[j] = eventmap[j + 1]; 00209 } else { 00210 PAPI_get_event_info( events[j], &info ); 00211 if ( !TESTS_QUIET ) 00212 printf( "Adding event[%d]: %s\n", j, info.short_descr ); 00213 if ( ( retval = PAPI_add_event( eventset, events[j] ) ) ) 00214 test_fail( __FILE__, __LINE__, "PAPI_add_event", retval ); 00215 eventmap[nev1] = j; 00216 nev1++; 00217 } 00218 if ( ( retval = PAPI_start( eventset ) ) ) 00219 test_fail( __FILE__, __LINE__, "PAPI_start", retval ); 00220 00221 x = 1.0; 00222 #ifndef STARTSTOP 00223 if ( ( retval = PAPI_reset( eventset ) ) ) 00224 test_fail( __FILE__, __LINE__, "PAPI_reset", retval ); 00225 #else 00226 if ( ( retval = PAPI_stop( eventset, dummies ) ) ) 00227 test_fail( __FILE__, __LINE__, "PAPI_stop", retval ); 00228 if ( ( retval = PAPI_start( eventset ) ) ) 00229 test_fail( __FILE__, __LINE__, "PAPI_start", retval ); 00230 #endif 00231 00232 t1 = PAPI_get_real_usec( ); 00233 y = dummy3( x, iters ); 00234 PAPI_read( eventset, values ); 00235 t2 = PAPI_get_real_usec( ); 00236 00237 if ( !TESTS_QUIET ) { 00238 printf( "\n(calculated independent of PAPI)\n" ); 00239 printf( "\tOperations= %.1f Mflop", y * 1e-6 ); 00240 printf( "\t(%g Mflop/s)\n\n", ( y / ( double ) ( t2 - t1 ) ) ); 00241 printf( "%20s %16s %-15s %-15s\n", "PAPI measurement:", 00242 "Acquired count", "Expected event", "PAPI_list_events" ); 00243 } 00244 00245 ntrue = nev1; 00246 PAPI_list_events( eventset, truelist, &ntrue ); 00247 for ( j = 0; j < nev1; j++ ) { 00248 idx = eventmap[j]; 00249 /* printf("Mapping: Counter %d -> slot %d.\n",j,idx); */ 00250 PAPI_get_event_info( events[idx], &info ); 00251 PAPI_event_code_to_name( truelist[j], name2 ); 00252 if ( !TESTS_QUIET ) 00253 printf( "%20s = %16lld %-15s %-15s %s\n", info.short_descr, 00254 values[j], info.symbol, name2, strcmp( info.symbol, 00255 name2 ) ? 00256 "*** MISMATCH ***" : "" ); 00257 dtmp = ( double ) values[j]; 00258 valsum[idx] += dtmp; 00259 valsample[idx][nsamples[idx]] = dtmp; 00260 nsamples[idx]++; 00261 } 00262 if ( !TESTS_QUIET ) 00263 printf( "\n" ); 00264 } 00265 00266 00267 if ( !TESTS_QUIET ) { 00268 printf( "\n\nEstimated variance relative to average counts:\n" ); 00269 for ( j = 0; j < nev1; j++ ) 00270 printf( " Event %.2d", j ); 00271 printf( "\n" ); 00272 } 00273 00274 fails = nevents; 00275 /* Due to limited precision of floating point cannot really use 00276 typical standard deviation compuation for large numbers with 00277 very small variations. Instead compute the std devation 00278 problems with precision. 00279 */ 00280 for ( j = 0; j < nev1; j++ ) { 00281 avg[j] = valsum[j] / nsamples[j]; 00282 spread[j] = 0; 00283 for ( i = 0; i < nsamples[j]; ++i ) { 00284 double diff = ( valsample[j][i] - avg[j] ); 00285 spread[j] += diff * diff; 00286 } 00287 spread[j] = sqrt( spread[j] / nsamples[j] ) / avg[j]; 00288 if ( !TESTS_QUIET ) 00289 printf( "%9.2g ", spread[j] ); 00290 /* Make sure that NaN get counted as errors */ 00291 if ( spread[j] < MPX_TOLERANCE ) 00292 fails--; 00293 else if ( values[j] < MINCOUNTS ) /* Neglect inprecise results with low counts */ 00294 fails--; 00295 } 00296 if ( !TESTS_QUIET ) { 00297 printf( "\n\n" ); 00298 for ( j = 0; j < nev1; j++ ) { 00299 PAPI_get_event_info( events[j], &info ); 00300 printf( "Event %.2d: mean=%10.0f, sdev/mean=%7.2g nrpt=%2d -- %s\n", 00301 j, avg[j], spread[j], nsamples[j], info.short_descr ); 00302 } 00303 printf( "\n\n" ); 00304 } 00305 00306 if ( fails ) 00307 test_fail( __FILE__, __LINE__, "Values differ from reference", fails ); 00308 else 00309 test_pass( __FILE__, NULL, 0 ); 00310 00311 return 0; 00312 } 00313 00314 static double 00315 dummy3( double x, int iters ) 00316 { 00317 int i; 00318 double w, y, z, a, b, c, d, e, f, g, h; 00319 double one; 00320 one = 1.0; 00321 w = x; 00322 y = x; 00323 z = x; 00324 a = x; 00325 b = x; 00326 c = x; 00327 d = x; 00328 e = x; 00329 f = x; 00330 g = x; 00331 h = x; 00332 for ( i = 1; i <= iters; i++ ) { 00333 w = w * 1.000000000001 + one; 00334 y = y * 1.000000000002 + one; 00335 z = z * 1.000000000003 + one; 00336 a = a * 1.000000000004 + one; 00337 b = b * 1.000000000005 + one; 00338 c = c * 0.999999999999 + one; 00339 d = d * 0.999999999998 + one; 00340 e = e * 0.999999999997 + one; 00341 f = f * 0.999999999996 + one; 00342 g = h * 0.999999999995 + one; 00343 h = h * 1.000000000006 + one; 00344 } 00345 return 2.0 * ( a + b + c + d + e + f + w + x + y + z + g + h ); 00346 }