PAPI  5.3.2.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cycle_ratio.c
Go to the documentation of this file.
1 /* This test exercises the PAPI_TOT_CYC and PAPI_REF_CYC counters.
2  PAPI_TOT_CYC should measure the number of cycles required to do a fixed amount of
3  work. It should be roughly constant for constant work, regardless of the speed state
4  a core is in.
5  PAPI_REF_CYC should measure the number of cycles at a constant reference clock rate,
6  independent of the actual clock rate of the core.
7  Thus if the core is running at nominal clock rate, PAPI_TOT_CYC and PAPI_REF_CYC
8  should match and the ratio should be approximately 1.
9  If the core is in an idle state (such as at startup), the ratio of TOT / REF should be
10  less than 1.
11  If the core is accelerated above nominal, such as TurboBoost when only one core is
12  active, the ratio of TOT / REF should be greater than 1.
13 
14  This test measures the ratio first from a roughly idle state. It then does floating
15  point intensive work to push this core into a fully active or accelerated state,
16  and then it measures the ratio again.
17 
18  Using this technique allows you to measure the effective clock rate of the processor
19  over a specific region of code, allowing you to infer the state of acceleration.
20 */
21 
22 #include "papi_test.h"
23 
24 static void work (int EventSet, int mhz);
25 
26 int
27 main( int argc, char **argv )
28 {
29  int retval;
30  int EventSet = PAPI_NULL;
31  int numflops = NUM_FLOPS;
32  const PAPI_hw_info_t *hwinfo = NULL;
33  long long elapsed_cyc;
34  long long values[2];
35  int mhz;
36 
37  /* Set TESTS_QUIET variable */
38  tests_quiet( argc, argv );
39 
40  /* Init the PAPI library */
42  if ( retval != PAPI_VER_CURRENT ) {
43  test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
44  }
45 
46  retval = PAPI_query_named_event("PAPI_REF_CYC");
47  if (PAPI_OK!=retval) {
48  test_skip( __FILE__, __LINE__, "PAPI_REF_CYC is not defined on this platform.", PAPI_OK );
49  }
50 
51  /* create an eventset */
52  retval = PAPI_create_eventset( &EventSet );
53  if ( retval != PAPI_OK ) {
54  test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval );
55  }
56 
57  /* add core cycle event */
58  retval = PAPI_add_named_event( EventSet, "PAPI_TOT_CYC");
59  if ( retval != PAPI_OK ) {
60  test_fail( __FILE__, __LINE__, "PAPI_add_named_event: PAPI_TOT_CYC", retval );
61  }
62 
63  /* add ref cycle event */
64  retval = PAPI_add_named_event( EventSet, "PAPI_REF_CYC");
65  if ( retval != PAPI_OK ) {
66  test_fail( __FILE__, __LINE__, "PAPI_add_events: PAPI_REF_CYC", retval );
67  }
68 
69  retval = papi_print_header
70  ( "Test case CycleRatio.c: Compute the ratio of TOT and REF cycles.\n",
71  &hwinfo );
72  if ( retval != PAPI_OK )
73  test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 );
74 
75  /* compute a nominal bus clock frequency */
76  retval = PAPI_start( EventSet );
77  if ( retval != PAPI_OK ) {
78  test_fail( __FILE__, __LINE__, "PAPI_start", retval );
79  }
80 
81  elapsed_cyc = PAPI_get_real_cyc( );
82  usleep(1000000);
83  elapsed_cyc = PAPI_get_real_cyc( ) - elapsed_cyc;
84  mhz = elapsed_cyc / 1000000;
85 
86  retval = PAPI_stop( EventSet, values );
87  if ( retval != PAPI_OK ) {
88  test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
89  }
90 
91  if ( values[1] == 0 ) {
92  test_warn( __FILE__, __LINE__, "PAPI_REF_CYC = 0\nTry upgrading your kernel.", 0 );
93  }
94 
95  printf( "CPU Computed Megahertz : %d\n", mhz );
96  printf( "Measure TOT and REF cycles from a cold start\n" );
97 
98  work(EventSet, mhz);
99  do_flops(10*numflops);
100 
101  printf( "\nMeasure again after working for a while\n" );
102 
103  work(EventSet, mhz);
104  test_pass( __FILE__, NULL, 0 );
105  return ( 0 );
106 }
107 
108 static void work (int EventSet, int mhz)
109 {
110  int retval;
111  long long values[2];
112  long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc;
113  double cycles_error;
114  float ratio, ratio1;
115  int numflops = NUM_FLOPS;
116 
117  ratio = ratio1 = 0;
118 
119  /* Gather before stats */
120  elapsed_us = PAPI_get_real_usec( );
121  elapsed_cyc = PAPI_get_real_cyc( );
122  elapsed_virt_us = PAPI_get_virt_usec( );
123  elapsed_virt_cyc = PAPI_get_virt_cyc( );
124 
125  /* Start PAPI */
126  retval = PAPI_start( EventSet );
127  if ( retval != PAPI_OK ) {
128  test_fail( __FILE__, __LINE__, "PAPI_start", retval );
129  }
130 
131  /* our test code */
132  do_flops( numflops );
133 
134  /* Stop PAPI */
135  retval = PAPI_stop( EventSet, values );
136  if ( retval != PAPI_OK ) {
137  test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
138  }
139  ratio = (float)values[0]/(float)values[1];
140 
141  /* Calculate total values */
142  elapsed_virt_us = PAPI_get_virt_usec( ) - elapsed_virt_us;
143  elapsed_virt_cyc = PAPI_get_virt_cyc( ) - elapsed_virt_cyc;
144  elapsed_us = PAPI_get_real_usec( ) - elapsed_us;
145  elapsed_cyc = PAPI_get_real_cyc( ) - elapsed_cyc;
146 
147  printf( "-------------------------------------------------------------------------\n" );
148  printf( "Using %d iterations of c += a*b\n", numflops );
149  printf( "-------------------------------------------------------------------------\n" );
150 
151  printf( TAB1, "PAPI_TOT_CYC : \t", values[0] );
152  printf( TAB1, "PAPI_REF_CYC : \t", values[1] );
153  printf( "%-12s %12f\n", "Cycle Ratio : \t", ratio );
154  printf( "%-12s %12d\n", "Effective MHz : \t", (int)(ratio * mhz) );
155  printf( TAB1, "Real usec : \t", elapsed_us );
156  printf( TAB1, "Real cycles : \t", elapsed_cyc );
157  printf( TAB1, "Virt usec : \t", elapsed_virt_us );
158  printf( TAB1, "Virt cycles : \t", elapsed_virt_cyc );
159 
160  printf( "-------------------------------------------------------------------------\n" );
161 
162  printf( "Verification: PAPI_REF_CYC should be roughly equal to real_cycles\n" );
163  cycles_error=100.0*((double)values[1] - (double)elapsed_cyc)/(double)elapsed_cyc;
164 
165  if ((cycles_error>10.0) || (cycles_error<-10.0)) {
166  printf("Error of %.2f%%\n",cycles_error);
167  test_warn( __FILE__, __LINE__, "validation", 0 );
168  }
169 
170 }
int PAPI_stop(int EventSet, long long *values)
Definition: papi.c:2232
#define NUM_FLOPS
static void work(int EventSet, int mhz)
Definition: cycle_ratio.c:108
Hardware info structure.
Definition: papi.h:775
long long PAPI_get_virt_usec(void)
Definition: papi.c:6246
#define PAPI_NULL
Definition: fpapi.h:13
int PAPI_add_named_event(int EventSet, char *EventName)
Definition: papi.c:1816
void test_skip(char *file, int line, char *call, int retval)
Definition: test_utils.c:614
long long PAPI_get_virt_cyc(void)
Definition: papi.c:6174
int papi_print_header(char *prompt, const PAPI_hw_info_t **hwinfo)
Definition: test_utils.c:21
#define TAB1
Definition: papi_test.h:112
return PAPI_OK
Definition: linux-nvml.c:458
tests_quiet(argc, argv)
#define printf
Definition: papi_test.h:125
static double
Definition: fileop.c:1281
test_pass(__FILE__, NULL, 0)
int int argc
Definition: iozone.c:1609
char ** argv
Definition: iozone.c:1610
test_fail(__FILE__, __LINE__,"PAPI_library_init", retval)
int PAPI_library_init(int version)
Definition: papi.c:495
void test_warn(char *file, int line, char *call, int retval)
Definition: test_utils.c:578
long long elapsed_cyc
Definition: zero_fork.c:43
#define PAPI_VER_CURRENT
Definition: fpapi.h:14
int PAPI_create_eventset(int *EventSet)
Definition: papi.c:1406
void do_flops(int n)
Definition: multiplex.c:23
int EventSet
long long PAPI_get_real_usec(void)
Definition: papi.c:6138
int PAPI_query_named_event(char *EventName)
Definition: papi.c:765
long long PAPI_get_real_cyc(void)
Definition: papi.c:6091
int PAPI_start(int EventSet)
Definition: papi.c:2026
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
ssize_t retval
Definition: libasync.c:338
long long elapsed_us
Definition: zero_fork.c:43
int main(int argc, char **argv)
List all appio events codes and names.