|
PAPI
5.3.0.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 if ( ( retval = PAPI_stop( eventset, values ) ) ) 00267 test_fail( __FILE__, __LINE__, "PAPI_stop", retval ); 00268 00269 if ( !TESTS_QUIET ) { 00270 printf( "\n\nEstimated variance relative to average counts:\n" ); 00271 for ( j = 0; j < nev1; j++ ) 00272 printf( " Event %.2d", j ); 00273 printf( "\n" ); 00274 } 00275 00276 fails = nevents; 00277 /* Due to limited precision of floating point cannot really use 00278 typical standard deviation compuation for large numbers with 00279 very small variations. Instead compute the std devation 00280 problems with precision. 00281 */ 00282 for ( j = 0; j < nev1; j++ ) { 00283 avg[j] = valsum[j] / nsamples[j]; 00284 spread[j] = 0; 00285 for ( i = 0; i < nsamples[j]; ++i ) { 00286 double diff = ( valsample[j][i] - avg[j] ); 00287 spread[j] += diff * diff; 00288 } 00289 spread[j] = sqrt( spread[j] / nsamples[j] ) / avg[j]; 00290 if ( !TESTS_QUIET ) 00291 printf( "%9.2g ", spread[j] ); 00292 /* Make sure that NaN get counted as errors */ 00293 if ( spread[j] < MPX_TOLERANCE ) 00294 fails--; 00295 else if ( values[j] < MINCOUNTS ) /* Neglect inprecise results with low counts */ 00296 fails--; 00297 } 00298 if ( !TESTS_QUIET ) { 00299 printf( "\n\n" ); 00300 for ( j = 0; j < nev1; j++ ) { 00301 PAPI_get_event_info( events[j], &info ); 00302 printf( "Event %.2d: mean=%10.0f, sdev/mean=%7.2g nrpt=%2d -- %s\n", 00303 j, avg[j], spread[j], nsamples[j], info.short_descr ); 00304 } 00305 printf( "\n\n" ); 00306 } 00307 00308 if ( fails ) 00309 test_fail( __FILE__, __LINE__, "Values differ from reference", fails ); 00310 else 00311 test_pass( __FILE__, NULL, 0 ); 00312 00313 return 0; 00314 } 00315 00316 static double 00317 dummy3( double x, int iters ) 00318 { 00319 int i; 00320 double w, y, z, a, b, c, d, e, f, g, h; 00321 double one; 00322 one = 1.0; 00323 w = x; 00324 y = x; 00325 z = x; 00326 a = x; 00327 b = x; 00328 c = x; 00329 d = x; 00330 e = x; 00331 f = x; 00332 g = x; 00333 h = x; 00334 for ( i = 1; i <= iters; i++ ) { 00335 w = w * 1.000000000001 + one; 00336 y = y * 1.000000000002 + one; 00337 z = z * 1.000000000003 + one; 00338 a = a * 1.000000000004 + one; 00339 b = b * 1.000000000005 + one; 00340 c = c * 0.999999999999 + one; 00341 d = d * 0.999999999998 + one; 00342 e = e * 0.999999999997 + one; 00343 f = f * 0.999999999996 + one; 00344 g = h * 0.999999999995 + one; 00345 h = h * 1.000000000006 + one; 00346 } 00347 return 2.0 * ( a + b + c + d + e + f + w + x + y + z + g + h ); 00348 }