|
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 PAPI_reset function for 00009 * multiplexed events 00010 */ 00011 00012 #include "papi_test.h" 00013 #include <stdio.h> 00014 #include <math.h> 00015 00016 #define REPEATS 5 00017 #define MAXEVENTS 9 00018 #define SLEEPTIME 100 00019 #define MINCOUNTS 100000 00020 00021 static double dummy3( double x, int iters ); 00022 00023 int 00024 main( int argc, char **argv ) 00025 { 00026 PAPI_event_info_t info; 00027 int i, j, retval; 00028 int iters = NUM_FLOPS; 00029 double x = 1.1, y, dtmp; 00030 long long t1, t2; 00031 long long values[MAXEVENTS]; 00032 int sleep_time = SLEEPTIME; 00033 #ifdef STARTSTOP 00034 long long dummies[MAXEVENTS]; 00035 #endif 00036 double valsample[MAXEVENTS][REPEATS]; 00037 double valsum[MAXEVENTS]; 00038 double avg[MAXEVENTS]; 00039 double spread[MAXEVENTS]; 00040 int nevents = MAXEVENTS; 00041 int eventset = PAPI_NULL; 00042 int events[MAXEVENTS]; 00043 int fails; 00044 00045 events[0] = PAPI_FP_INS; 00046 events[1] = PAPI_TOT_INS; 00047 events[2] = PAPI_INT_INS; 00048 events[3] = PAPI_TOT_CYC; 00049 events[4] = PAPI_STL_CCY; 00050 events[5] = PAPI_BR_INS; 00051 events[6] = PAPI_SR_INS; 00052 events[7] = PAPI_LD_INS; 00053 events[8] = PAPI_TOT_IIS; 00054 00055 for ( i = 0; i < MAXEVENTS; i++ ) { 00056 values[i] = 0; 00057 valsum[i] = 0; 00058 } 00059 00060 if ( argc > 1 ) { 00061 if ( !strcmp( argv[1], "TESTS_QUIET" ) ) 00062 tests_quiet( argc, argv ); 00063 else { 00064 sleep_time = atoi( argv[1] ); 00065 if ( sleep_time <= 0 ) 00066 sleep_time = SLEEPTIME; 00067 } 00068 } 00069 00070 if ( !TESTS_QUIET ) { 00071 printf( "\nAccuracy check of multiplexing routines.\n" ); 00072 printf( "Investigating the variance of multiplexed measurements.\n\n" ); 00073 } 00074 00075 if ( ( retval = 00076 PAPI_library_init( PAPI_VER_CURRENT ) ) != PAPI_VER_CURRENT ) 00077 test_fail( __FILE__, __LINE__, "PAPI_library_init", retval ); 00078 00079 #ifdef MPX 00080 init_multiplex( ); 00081 #endif 00082 00083 if ( ( retval = PAPI_create_eventset( &eventset ) ) ) 00084 test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval ); 00085 #ifdef MPX 00086 00087 /* In Component PAPI, EventSets must be assigned a component index 00088 before you can fiddle with their internals. 00089 0 is always the cpu component */ 00090 retval = PAPI_assign_eventset_component( eventset, 0 ); 00091 if ( retval != PAPI_OK ) 00092 test_fail( __FILE__, __LINE__, "PAPI_assign_eventset_component", 00093 retval ); 00094 00095 if ( ( retval = PAPI_set_multiplex( eventset ) ) ) { 00096 if ( retval == PAPI_ENOSUPP) { 00097 test_skip(__FILE__, __LINE__, "Multiplex not supported", 1); 00098 } 00099 00100 test_fail( __FILE__, __LINE__, "PAPI_set_multiplex", retval ); 00101 } 00102 #endif 00103 00104 /* What does this code even do? */ 00105 nevents = MAXEVENTS; 00106 for ( i = 0; i < nevents; i++ ) { 00107 if ( ( retval = PAPI_add_event( eventset, events[i] ) ) ) { 00108 for ( j = i; j < MAXEVENTS-1; j++ ) { 00109 events[j] = events[j + 1]; 00110 } 00111 nevents--; 00112 i--; 00113 } 00114 } 00115 if ( nevents < 2 ) 00116 test_skip( __FILE__, __LINE__, "Not enough events left...", 0 ); 00117 00118 /* Find a reasonable number of iterations (each 00119 * event active 20 times) during the measurement 00120 */ 00121 t2 = 10000 * 20 * nevents; /* Target: 10000 usec/multiplex, 20 repeats */ 00122 if ( t2 > 30e6 ) 00123 test_skip( __FILE__, __LINE__, "This test takes too much time", 00124 retval ); 00125 00126 /* Measure one run */ 00127 t1 = PAPI_get_real_usec( ); 00128 y = dummy3( x, iters ); 00129 t1 = PAPI_get_real_usec( ) - t1; 00130 00131 if ( t2 > t1 ) /* Scale up execution time to match t2 */ 00132 iters = iters * ( int ) ( t2 / t1 ); 00133 else if ( t1 > 30e6 ) /* Make sure execution time is < 30s per repeated test */ 00134 test_skip( __FILE__, __LINE__, "This test takes too much time", 00135 retval ); 00136 00137 if ( ( retval = PAPI_start( eventset ) ) ) 00138 test_fail( __FILE__, __LINE__, "PAPI_start", retval ); 00139 00140 for ( i = 1; i <= REPEATS; i++ ) { 00141 x = 1.0; 00142 00143 #ifndef STARTSTOP 00144 if ( ( retval = PAPI_reset( eventset ) ) ) 00145 test_fail( __FILE__, __LINE__, "PAPI_reset", retval ); 00146 #else 00147 if ( ( retval = PAPI_stop( eventset, dummies ) ) ) 00148 test_fail( __FILE__, __LINE__, "PAPI_stop", retval ); 00149 if ( ( retval = PAPI_start( eventset ) ) ) 00150 test_fail( __FILE__, __LINE__, "PAPI_start", retval ); 00151 #endif 00152 00153 if ( !TESTS_QUIET ) 00154 printf( "\nTest %d (of %d):\n", i, REPEATS ); 00155 t1 = PAPI_get_real_usec( ); 00156 y = dummy3( x, iters ); 00157 PAPI_read( eventset, values ); 00158 t2 = PAPI_get_real_usec( ); 00159 00160 if ( !TESTS_QUIET ) { 00161 printf( "\n(calculated independent of PAPI)\n" ); 00162 printf( "\tOperations= %.1f Mflop", y * 1e-6 ); 00163 printf( "\t(%g Mflop/s)\n\n", ( y / ( double ) ( t2 - t1 ) ) ); 00164 printf( "PAPI measurements:\n" ); 00165 } 00166 for ( j = 0; j < nevents; j++ ) { 00167 PAPI_get_event_info( events[j], &info ); 00168 if ( !TESTS_QUIET ) { 00169 printf( "%20s = ", info.short_descr ); 00170 printf( LLDFMT, values[j] ); 00171 printf( "\n" ); 00172 } 00173 dtmp = ( double ) values[j]; 00174 valsum[j] += dtmp; 00175 valsample[j][i - 1] = dtmp; 00176 } 00177 if ( !TESTS_QUIET ) 00178 printf( "\n" ); 00179 } 00180 00181 if ( !TESTS_QUIET ) { 00182 printf( "\n\nEstimated variance relative to average counts:\n" ); 00183 for ( j = 0; j < nevents; j++ ) 00184 printf( " Event %.2d", j ); 00185 printf( "\n" ); 00186 } 00187 00188 fails = nevents; 00189 /* Due to limited precision of floating point cannot really use 00190 typical standard deviation compuation for large numbers with 00191 very small variations. Instead compute the std devation 00192 problems with precision. 00193 */ 00194 for ( j = 0; j < nevents; j++ ) { 00195 avg[j] = valsum[j] / REPEATS; 00196 spread[j] = 0; 00197 for ( i = 0; i < REPEATS; ++i ) { 00198 double diff = ( valsample[j][i] - avg[j] ); 00199 spread[j] += diff * diff; 00200 } 00201 spread[j] = sqrt( spread[j] / REPEATS ) / avg[j]; 00202 if ( !TESTS_QUIET ) 00203 printf( "%9.2g ", spread[j] ); 00204 /* Make sure that NaN get counted as errors */ 00205 if ( spread[j] < MPX_TOLERANCE ) 00206 --fails; 00207 else if ( valsum[j] < MINCOUNTS ) /* Neglect inprecise results with low counts */ 00208 --fails; 00209 } 00210 00211 if ( !TESTS_QUIET ) { 00212 printf( "\n\n" ); 00213 for ( j = 0; j < nevents; j++ ) { 00214 PAPI_get_event_info( events[j], &info ); 00215 printf( "Event %.2d: mean=%10.0f, sdev/mean=%7.2g nrpt=%2d -- %s\n", 00216 j, avg[j], spread[j], REPEATS, info.short_descr ); 00217 } 00218 printf( "\n\n" ); 00219 } 00220 00221 if ( fails ) 00222 test_fail( __FILE__, __LINE__, "Values outside threshold", fails ); 00223 else 00224 test_pass( __FILE__, NULL, 0 ); 00225 00226 return 0; 00227 } 00228 00229 static double 00230 dummy3( double x, int iters ) 00231 { 00232 int i; 00233 double w, y, z, a, b, c, d, e, f, g, h; 00234 double one; 00235 one = 1.0; 00236 w = x; 00237 y = x; 00238 z = x; 00239 a = x; 00240 b = x; 00241 c = x; 00242 d = x; 00243 e = x; 00244 f = x; 00245 g = x; 00246 h = x; 00247 for ( i = 1; i <= iters; i++ ) { 00248 w = w * 1.000000000001 + one; 00249 y = y * 1.000000000002 + one; 00250 z = z * 1.000000000003 + one; 00251 a = a * 1.000000000004 + one; 00252 b = b * 1.000000000005 + one; 00253 c = c * 0.999999999999 + one; 00254 d = d * 0.999999999998 + one; 00255 e = e * 0.999999999997 + one; 00256 f = f * 0.999999999996 + one; 00257 g = h * 0.999999999995 + one; 00258 h = h * 1.000000000006 + one; 00259 } 00260 return 2.0 * ( a + b + c + d + e + f + w + x + y + z + g + h ); 00261 }