|
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 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 ( ( retval = PAPI_stop( eventset, values ) ) ) 00182 test_fail( __FILE__, __LINE__, "PAPI_stop", retval ); 00183 00184 if ( !TESTS_QUIET ) { 00185 printf( "\n\nEstimated variance relative to average counts:\n" ); 00186 for ( j = 0; j < nevents; j++ ) 00187 printf( " Event %.2d", j ); 00188 printf( "\n" ); 00189 } 00190 00191 fails = nevents; 00192 /* Due to limited precision of floating point cannot really use 00193 typical standard deviation compuation for large numbers with 00194 very small variations. Instead compute the std devation 00195 problems with precision. 00196 */ 00197 for ( j = 0; j < nevents; j++ ) { 00198 avg[j] = valsum[j] / REPEATS; 00199 spread[j] = 0; 00200 for ( i = 0; i < REPEATS; ++i ) { 00201 double diff = ( valsample[j][i] - avg[j] ); 00202 spread[j] += diff * diff; 00203 } 00204 spread[j] = sqrt( spread[j] / REPEATS ) / avg[j]; 00205 if ( !TESTS_QUIET ) 00206 printf( "%9.2g ", spread[j] ); 00207 /* Make sure that NaN get counted as errors */ 00208 if ( spread[j] < MPX_TOLERANCE ) 00209 --fails; 00210 else if ( valsum[j] < MINCOUNTS ) /* Neglect inprecise results with low counts */ 00211 --fails; 00212 } 00213 00214 if ( !TESTS_QUIET ) { 00215 printf( "\n\n" ); 00216 for ( j = 0; j < nevents; j++ ) { 00217 PAPI_get_event_info( events[j], &info ); 00218 printf( "Event %.2d: mean=%10.0f, sdev/mean=%7.2g nrpt=%2d -- %s\n", 00219 j, avg[j], spread[j], REPEATS, info.short_descr ); 00220 } 00221 printf( "\n\n" ); 00222 } 00223 00224 if ( fails ) 00225 test_fail( __FILE__, __LINE__, "Values outside threshold", fails ); 00226 else 00227 test_pass( __FILE__, NULL, 0 ); 00228 00229 return 0; 00230 } 00231 00232 static double 00233 dummy3( double x, int iters ) 00234 { 00235 int i; 00236 double w, y, z, a, b, c, d, e, f, g, h; 00237 double one; 00238 one = 1.0; 00239 w = x; 00240 y = x; 00241 z = x; 00242 a = x; 00243 b = x; 00244 c = x; 00245 d = x; 00246 e = x; 00247 f = x; 00248 g = x; 00249 h = x; 00250 for ( i = 1; i <= iters; i++ ) { 00251 w = w * 1.000000000001 + one; 00252 y = y * 1.000000000002 + one; 00253 z = z * 1.000000000003 + one; 00254 a = a * 1.000000000004 + one; 00255 b = b * 1.000000000005 + one; 00256 c = c * 0.999999999999 + one; 00257 d = d * 0.999999999998 + one; 00258 e = e * 0.999999999997 + one; 00259 f = f * 0.999999999996 + one; 00260 g = h * 0.999999999995 + one; 00261 h = h * 1.000000000006 + one; 00262 } 00263 return 2.0 * ( a + b + c + d + e + f + w + x + y + z + g + h ); 00264 }