PAPI 7.1.0.0
Loading...
Searching...
No Matches
papi_ref_cyc.c
Go to the documentation of this file.
1/* This test exercises the PAPI_TOT_CYC and PAPI_REF_CYC counters.
2
3 PAPI_TOT_CYC should measure the number of cycles required to do
4 a fixed amount of work.
5 It should be roughly constant for constant work, regardless of the
6 speed state a core is in.
7
8 PAPI_REF_CYC should measure the number of cycles at a constant
9 reference clock rate, independent of the actual clock rate of the core.
10*/
11
12/*
13 PAPI_REF_CYC has various issues on Intel chips:
14
15 On older machines PAPI uses UNHALTED_REFERENCE_CYCLES but this
16 means different things on different architectures
17
18 + On Core2/Atom this maps to the special Fixed Counter 2
19 CPU_CLK_UNHALTED.REF
20 This counts at the same rate as the TSC (PAPI_get_real_cyc())
21 And also seems to match PAPI_TOT_CYC
22 It is documented as having a fixed ratio to the
23 CPU_CLK_UNHALTED.BUS (3c/1) event.
24
25 + On Nehalem/Westemere this also maps to Fixed Counter 2.
26 Again, counts same rate as the TSC and returns
27 CPU_CLK_UNHALTED.REF_P (3c/1)
28 times the "Maximum Non-Turbo Ratio"
29
30 + Same for Sandybridge/Ivybridge
31
32 On newer HSW,BDW,SKL machines PAPI uses a different type of event
33 CPU_CLK_THREAD_UNHALTED:REF_XCLK
34
35 + On Haswell machines this is just the reference clock
36 (100MHz?)
37 + On Sandybridge this is off by a factor of 8x?
38*/
39
40/* NOTE:
41 PAPI_get_virt_cyc() returns a lie!
42 It's just virt_time() * max_theoretical_MHz
43 so no point in checking that */
44
45#include <stdio.h>
46#include <stdlib.h>
47#include <unistd.h>
48
49#include "papi.h"
50#include "papi_test.h"
51
52#include "testcode.h"
53
54#define NUM_FLOPS 20000000
55
56static void work (int EventSet, int sleep_test, int quiet)
57{
58 int retval;
59 long long values[2];
60 long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc;
61 double cycles_error;
62 int numflops = NUM_FLOPS;
63
64 /* Gather before stats */
67 elapsed_virt_us = PAPI_get_virt_usec( );
68 elapsed_virt_cyc = PAPI_get_virt_cyc( );
69
70 /* Start PAPI */
72 if ( retval != PAPI_OK ) {
73 test_fail( __FILE__, __LINE__, "PAPI_start", retval );
74 }
75
76 /* our test code */
77 if (sleep_test) {
78 sleep(2);
79 }
80 else {
81 do_flops( numflops, 1 );
82 }
83
84 /* Stop PAPI */
86 if ( retval != PAPI_OK ) {
87 test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
88 }
89
90 /* Calculate total values */
91 elapsed_virt_us = PAPI_get_virt_usec( ) - elapsed_virt_us;
92 elapsed_virt_cyc = PAPI_get_virt_cyc( ) - elapsed_virt_cyc;
95
96 if (!quiet) {
97 printf( "-------------------------------------------------------------------------\n" );
98 if (sleep_test) printf("Sleeping for 2s\n");
99 else printf( "Using %d iterations of c += a*b\n", numflops );
100 printf( "-------------------------------------------------------------------------\n" );
101
102 printf( "PAPI_TOT_CYC : \t%10lld\n", values[0] );
103 printf( "PAPI_REF_CYC : \t%10lld\n", values[1] );
104 printf( "Real usec : \t%10lld\n", elapsed_us );
105 printf( "Real cycles : \t%10lld\n", elapsed_cyc );
106 printf( "Virt usec : \t%10lld\n", elapsed_virt_us );
107 printf( "Virt cycles (estimate) : \t%10lld\n", elapsed_virt_cyc );
108 printf( "Estimated GHz : \t%10.3lf\n", (double) elapsed_cyc/(double)elapsed_us/1000.0);
109
110 printf( "-------------------------------------------------------------------------\n" );
111 }
112
113
114 if (sleep_test) {
115 if (!quiet) {
116 printf( "Verification: PAPI_REF_CYC should be much lower than real_usec\n");
117 }
118 if (values[1]>elapsed_us) {
119 if (!quiet) printf("PAPI_REF_CYC too high!\n");
120 test_fail( __FILE__, __LINE__, "PAPI_REF_CYC too high", 0 );
121 }
122
123 }
124 else {
125 /* PAPI_REF_CYC should be roughly the same as TSC when busy */
126 /* on Intel chips */
127 if (!quiet) {
128 printf( "Verification: real_cyc should be roughly PAPI_REF_CYC\n");
129 printf( " real_usec should be roughly virt_usec (on otherwise idle system)\n");
130 }
131
132 cycles_error=100.0*
133 ((double)values[1]-((double)elapsed_cyc))
134 /values[1];
135
136 if ((cycles_error>10.0) || (cycles_error<-10.0)) {
137 if (!quiet) printf("Error of %.2f%%\n",cycles_error);
138 test_fail( __FILE__, __LINE__, "PAPI_REF_CYC validation", 0 );
139 }
140
141 cycles_error=100.0*
142 ((double)elapsed_us-(double)elapsed_virt_us)
143 /(double)elapsed_us;
144
145 if ((cycles_error>10.0) || (cycles_error<-10.0)) {
146 if (!quiet) printf("Error of %.2f%%\n",cycles_error);
147 test_warn( __FILE__, __LINE__, "real_us validation", 0 );
148 }
149 }
150}
151
152
153int
154main( int argc, char **argv )
155{
156 int retval;
157 int EventSet = PAPI_NULL;
158 int quiet;
159
160 /* Set TESTS_QUIET variable */
161 quiet = tests_quiet( argc, argv );
162
163 /* Init the PAPI library */
165 if ( retval != PAPI_VER_CURRENT ) {
166 test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
167 }
168
169 /* Check the ref cycles event */
170 retval = PAPI_query_named_event("PAPI_REF_CYC");
171 if (PAPI_OK!=retval) {
172 if (!quiet) printf("No PAPI_REF_CYC available\n");
173 test_skip( __FILE__, __LINE__,
174 "PAPI_REF_CYC is not defined on this platform.", 0);
175 }
176
177 /* create an eventset */
179 if ( retval != PAPI_OK ) {
180 test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval );
181 }
182
183 /* add core cycle event */
184 retval = PAPI_add_named_event( EventSet, "PAPI_TOT_CYC");
185 if ( retval != PAPI_OK ) {
186 test_fail( __FILE__, __LINE__,
187 "PAPI_add_named_event: PAPI_TOT_CYC", retval );
188 }
189
190 /* add ref cycle event */
191 retval = PAPI_add_named_event( EventSet, "PAPI_REF_CYC");
192 if ( retval != PAPI_OK ) {
193 test_fail( __FILE__, __LINE__,
194 "PAPI_add_events: PAPI_REF_CYC", retval );
195 }
196
197 if (!quiet) {
198 printf("Test case sleeping: "
199 "Look at TOT and REF cycles.\n");
200 }
201
202 work(EventSet, 1, quiet);
203// do_flops(10*numflops);
204
205 if (!quiet) {
206 printf( "\nTest case busy:\n" );
207 }
208
209 work(EventSet, 0, quiet);
210
211 test_pass( __FILE__ );
212
213 return 0;
214}
215
add PAPI preset or native hardware event by name to an EventSet
Create a new empty PAPI EventSet.
get real time counter value in clock cycles Returns the total real time passed since some arbitrary s...
get real time counter value in microseconds
get virtual time counter value in clock cycles
get virtual time counter values in microseconds
initialize the PAPI library.
Query if a named PAPI event exists.
Start counting hardware events in an event set.
Stop counting hardware events in an event set.
#define PAPI_VER_CURRENT
Definition: f90papi.h:54
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_NULL
Definition: f90papi.h:78
static int EventSet
Definition: init_fini.c:8
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
void do_flops(int n)
Definition: multiplex.c:23
Return codes and api definitions.
#define NUM_FLOPS
Definition: papi_ref_cyc.c:54
static void work(int EventSet, int sleep_test, int quiet)
Definition: papi_ref_cyc.c:56
int tests_quiet(int argc, char **argv)
Definition: test_utils.c:376
void PAPI_NORETURN test_fail(const char *file, int line, const char *call, int retval)
Definition: test_utils.c:491
void PAPI_NORETURN test_pass(const char *filename)
Definition: test_utils.c:432
void test_warn(const char *file, int line, const char *call, int retval)
Definition: test_utils.c:547
void PAPI_NORETURN test_skip(const char *file, int line, const char *call, int retval)
Definition: test_utils.c:584
int main()
Definition: pernode.c:20
int quiet
Definition: rapl_overflow.c:19
long long elapsed_cyc
Definition: zero_fork.c:50
long long elapsed_us
Definition: zero_fork.c:50
int retval
Definition: zero_fork.c:53