PAPI  5.0.1.0
cycle_ratio.c
Go to the documentation of this file.
00001 /* This test exercises the PAPI_TOT_CYC and PAPI_REF_CYC counters.
00002     PAPI_TOT_CYC should measure the number of cycles required to do a fixed amount of
00003     work. It should be roughly constant for constant work, regardless of the speed state
00004     a core is in.
00005     PAPI_REF_CYC should measure the number of cycles at a constant reference clock rate,
00006     independent of the actual clock rate of the core.
00007     Thus if the core is running at nominal clock rate, PAPI_TOT_CYC and PAPI_REF_CYC
00008     should match and the ratio should be approximately 1.
00009     If the core is in an idle state (such as at startup), the ratio of TOT / REF should be
00010     less than 1.
00011     If the core is accelerated above nominal, such as TurboBoost when only one core is
00012     active, the ratio of TOT / REF should be greater than 1.
00013 
00014     This test measures the ratio first from a roughly idle state. It then does floating
00015     point intensive work to push this core into a fully active or accelerated state,
00016     and then it measures the ratio again.
00017     
00018     Using this technique allows you to measure the effective clock rate of the processor
00019     over a specific region of code, allowing you to infer the state of acceleration.
00020 */
00021 
00022 #include "papi_test.h"
00023 
00024 static void work (int EventSet, int mhz);
00025 
00026 int
00027 main( int argc, char **argv )
00028 {
00029     int retval;
00030     int EventSet = PAPI_NULL;
00031     int numflops = NUM_FLOPS;
00032     const PAPI_hw_info_t *hwinfo = NULL;
00033     long long elapsed_cyc;
00034     long long values[2];
00035     int mhz;
00036 
00037     /* Set TESTS_QUIET variable */
00038     tests_quiet( argc, argv );  
00039 
00040     /* Init the PAPI library */
00041     retval = PAPI_library_init( PAPI_VER_CURRENT );
00042     if ( retval != PAPI_VER_CURRENT ) {
00043        test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
00044     }
00045 
00046     retval = PAPI_query_named_event("PAPI_REF_CYC");
00047     if (PAPI_OK!=retval) {
00048         test_skip( __FILE__, __LINE__, "PAPI_REF_CYC is not defined on this platform.", PAPI_OK );
00049     }
00050 
00051     /* create an eventset */
00052     retval = PAPI_create_eventset( &EventSet );
00053     if ( retval != PAPI_OK ) {
00054         test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval );
00055   }
00056 
00057     /* add core cycle event */
00058     retval = PAPI_add_named_event( EventSet, "PAPI_TOT_CYC");
00059     if ( retval != PAPI_OK ) {
00060         test_fail( __FILE__, __LINE__, "PAPI_add_named_event: PAPI_TOT_CYC", retval );
00061   }
00062 
00063     /* add ref cycle event */
00064     retval = PAPI_add_named_event( EventSet, "PAPI_REF_CYC");
00065     if ( retval != PAPI_OK ) {
00066         test_fail( __FILE__, __LINE__, "PAPI_add_events: PAPI_REF_CYC", retval );
00067   }
00068   
00069     retval = papi_print_header
00070     ( "Test case CycleRatio.c: Compute the ratio of TOT and REF cycles.\n",
00071       &hwinfo );
00072     if ( retval != PAPI_OK )
00073         test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 );
00074     
00075     /* compute a nominal bus clock frequency */
00076     retval = PAPI_start( EventSet );
00077     if ( retval != PAPI_OK ) {
00078        test_fail( __FILE__, __LINE__, "PAPI_start", retval );
00079     }
00080     
00081     elapsed_cyc = PAPI_get_real_cyc(  );
00082     usleep(1000000);
00083     elapsed_cyc = PAPI_get_real_cyc(  ) - elapsed_cyc;
00084     mhz = elapsed_cyc / 1000000;
00085     
00086     retval = PAPI_stop( EventSet, values );
00087     if ( retval != PAPI_OK ) {
00088        test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
00089     }
00090     
00091     if ( values[1] == 0 ) {
00092        test_warn( __FILE__, __LINE__, "PAPI_REF_CYC = 0\nTry upgrading your kernel.", 0 );
00093     }
00094     
00095     printf( "CPU Computed Megahertz   : %d\n", mhz );
00096     printf( "Measure TOT and REF cycles from a cold start\n" );
00097 
00098     work(EventSet, mhz);
00099     do_flops(10*numflops);
00100     
00101     printf( "\nMeasure again after working for a while\n" );
00102 
00103     work(EventSet, mhz);
00104     test_pass( __FILE__, NULL, 0 );
00105     return ( 0 );
00106 }
00107 
00108 static void work (int EventSet, int mhz)
00109 {
00110     int retval;
00111     long long values[2];
00112     long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc;
00113     double cycles_error;
00114     float ratio, ratio1;
00115     int numflops = NUM_FLOPS;
00116 
00117     ratio = ratio1 = 0;
00118 
00119     /* Gather before stats */
00120     elapsed_us = PAPI_get_real_usec(  );
00121     elapsed_cyc = PAPI_get_real_cyc(  );
00122     elapsed_virt_us = PAPI_get_virt_usec(  );
00123     elapsed_virt_cyc = PAPI_get_virt_cyc(  );
00124 
00125     /* Start PAPI */
00126     retval = PAPI_start( EventSet );
00127     if ( retval != PAPI_OK ) {
00128        test_fail( __FILE__, __LINE__, "PAPI_start", retval );
00129     }
00130 
00131     /* our test code */
00132     do_flops( numflops );
00133 
00134     /* Stop PAPI */
00135     retval = PAPI_stop( EventSet, values );
00136     if ( retval != PAPI_OK ) {
00137        test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
00138     }
00139     ratio = (float)values[0]/(float)values[1];
00140 
00141     /* Calculate total values */
00142     elapsed_virt_us = PAPI_get_virt_usec(  ) - elapsed_virt_us;
00143     elapsed_virt_cyc = PAPI_get_virt_cyc(  ) - elapsed_virt_cyc;
00144     elapsed_us = PAPI_get_real_usec(  ) - elapsed_us;
00145     elapsed_cyc = PAPI_get_real_cyc(  ) - elapsed_cyc;
00146 
00147    printf( "-------------------------------------------------------------------------\n" );
00148    printf( "Using %d iterations of c += a*b\n", numflops );
00149    printf( "-------------------------------------------------------------------------\n" );
00150 
00151    printf( TAB1, "PAPI_TOT_CYC             : \t", values[0] );
00152    printf( TAB1, "PAPI_REF_CYC             : \t", values[1] );
00153    printf( "%-12s %12f\n", "Cycle Ratio              : \t", ratio );
00154    printf( "%-12s %12d\n", "Effective MHz            : \t", (int)(ratio * mhz) );
00155    printf( TAB1, "Real usec                : \t", elapsed_us );
00156    printf( TAB1, "Real cycles              : \t", elapsed_cyc );
00157    printf( TAB1, "Virt usec                : \t", elapsed_virt_us );
00158    printf( TAB1, "Virt cycles              : \t", elapsed_virt_cyc );
00159 
00160    printf( "-------------------------------------------------------------------------\n" );
00161 
00162    printf( "Verification: PAPI_REF_CYC should be roughly equal to real_cycles\n" );
00163    cycles_error=100.0*((double)values[1] - (double)elapsed_cyc)/(double)elapsed_cyc;
00164 
00165    if ((cycles_error>10.0) || (cycles_error<-10.0)) {
00166      printf("Error of %.2f%%\n",cycles_error);
00167      test_warn( __FILE__, __LINE__, "validation", 0 );
00168    }
00169 
00170 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines