|
PAPI
5.0.1.0
|
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 }