PAPI  5.0.1.0
sdsc4.c
Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines