PAPI 7.1.0.0
Loading...
Searching...
No Matches
sdsc4-mpx.c
Go to the documentation of this file.
1/*
2 * Test example for multiplex functionality, originally
3 * provided by Timothy Kaiser, SDSC. It was modified to fit the
4 * PAPI test suite by Nils Smeds, <smeds@pdc.kth.se>.
5 *
6 * This example verifies the adding and removal of multiplexed
7 * events in an event set.
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <math.h>
14#include <assert.h>
15
16#include "papi.h"
17#include "papi_test.h"
18
19#include "testcode.h"
20
21#define MAXEVENTS 9
22#define REPEATS (MAXEVENTS * 4)
23#define SLEEPTIME 100
24#define MINCOUNTS 100000
25#define MPX_TOLERANCE 0.20
26#define NUM_FLOPS 20000000
27
28int
29main( int argc, char **argv )
30{
32 char name2[PAPI_MAX_STR_LEN];
33 int i, j, retval, idx, repeats;
34 int iters = NUM_FLOPS;
35 double x = 1.1, y, dtmp;
36 long long t1, t2;
37 long long values[MAXEVENTS], refvals[MAXEVENTS];
38 int nsamples[MAXEVENTS], truelist[MAXEVENTS], ntrue;
39#ifdef STARTSTOP
40 long long dummies[MAXEVENTS];
41#endif
42 int sleep_time = SLEEPTIME;
43 double valsample[MAXEVENTS][REPEATS];
44 double valsum[MAXEVENTS];
45 double avg[MAXEVENTS];
46 double spread[MAXEVENTS];
47 int nevents = MAXEVENTS, nev1;
48 int eventset = PAPI_NULL;
49 int events[MAXEVENTS];
50 int eventidx[MAXEVENTS];
51 int eventmap[MAXEVENTS];
52 int fails;
53 int quiet;
54
55 quiet = tests_quiet( argc, argv );
56
57 if ( argc > 1 ) {
58 if ( !strcmp( argv[1], "quiet" ) ) {
59 }
60 else {
61 sleep_time = atoi( argv[1] );
62 if ( sleep_time <= 0 )
63 sleep_time = SLEEPTIME;
64 }
65 }
66
76
77 for ( i = 0; i < MAXEVENTS; i++ ) {
78 values[i] = 0;
79 valsum[i] = 0;
80 nsamples[i] = 0;
81 }
82
83 /* Print test summary */
84 if ( !quiet ) {
85 printf( "\nFunctional check of multiplexing routines.\n" );
86 printf( "Adding and removing events from an event set.\n\n" );
87 }
88
89 /* Init the library */
91 if (retval != PAPI_VER_CURRENT ) {
92 test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
93 }
94
95 /* Enable multiplexing */
96#ifdef MPX
98 if ( retval != PAPI_OK ) {
99 test_fail( __FILE__, __LINE__, "PAPI multiplex init fail\n", retval );
100 }
101#endif
102
103 /* Create an eventset */
104 if ( ( retval = PAPI_create_eventset( &eventset ) ) ) {
105 test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval );
106 }
107
108 /* Enable multiplexing on the eventset */
109#ifdef MPX
110
111 /* In Component PAPI, EventSets must be assigned a component index
112 before you can fiddle with their internals.
113 0 is always the cpu component */
114 retval = PAPI_assign_eventset_component( eventset, 0 );
115 if ( retval != PAPI_OK )
116 test_fail( __FILE__, __LINE__, "PAPI_assign_eventset_component",
117 retval );
118
119 if ( ( retval = PAPI_set_multiplex( eventset ) ) ) {
120 if ( retval == PAPI_ENOSUPP) {
121 test_skip(__FILE__, __LINE__, "Multiplex not supported", 1);
122 }
123 test_fail( __FILE__, __LINE__, "PAPI_set_multiplex", retval );
124 }
125#endif
126
127 /* See which events are available and remove the ones that aren't */
128 nevents = MAXEVENTS;
129 for ( i = 0; i < nevents; i++ ) {
130 if ( ( retval = PAPI_add_event( eventset, events[i] ) ) ) {
131 for ( j = i; j < MAXEVENTS-1; j++ )
132 events[j] = events[j + 1];
133 nevents--;
134 i--;
135 }
136 }
137
138 /* We want at least three events? */
139 /* Seems arbitrary. Might be because intel machines used to */
140 /* Only have two event slots */
141 if ( nevents < 3 ) {
142 test_skip( __FILE__, __LINE__, "Not enough events left...", 0 );
143 }
144
145 /* Find a reasonable number of iterations (each
146 * event active 20 times) during the measurement
147 */
148
149 /* TODO: find Linux multiplex interval */
150 /* not sure if 10ms is close or not */
151 /* Target: 10000 usec/multiplex, 20 repeats */
152 t2 = 10000 * 20 * nevents;
153 if ( t2 > 30e6 ) {
154 test_skip( __FILE__, __LINE__,
155 "This test takes too much time", retval );
156 }
157
158 /* Measure one run */
160 y = do_flops3( x, iters, 1 );
161 t1 = PAPI_get_real_usec( ) - t1;
162
163 /* Scale up execution time to match t2 */
164 if ( t2 > t1 ) {
165 iters = iters * ( int ) ( t2 / t1 );
166 }
167 /* Make sure execution time is < 30s per repeated test */
168 else if ( t1 > 30e6 ) {
169 test_skip( __FILE__, __LINE__,
170 "This test takes too much time", retval );
171 }
172
173 /* Split the events up by odd and even? */
174 j = nevents;
175 for ( i = 1; i < nevents; i = i + 2 )
176 eventidx[--j] = i;
177 for ( i = 0; i < nevents; i = i + 2 )
178 eventidx[--j] = i;
179 assert( j == 0 );
180
181 /* put event mapping in eventmap? */
182 for ( i = 0; i < nevents; i++ )
183 eventmap[i] = i;
184
185 x = 1.0;
186
187 /* Make a reference run */
188 if ( !quiet ) {
189 printf( "\nReference run:\n" );
190 }
191
193 if ( ( retval = PAPI_start( eventset ) ) ) {
194 test_fail( __FILE__, __LINE__, "PAPI_start", retval );
195 }
196 y = do_flops3( x, iters, 1 );
197 PAPI_read( eventset, refvals );
199
200 /* Print results */
201 ntrue = nevents;
202 PAPI_list_events( eventset, truelist, &ntrue );
203 if ( !quiet ) {
204 printf( "\tOperations= %.1f Mflop", y * 1e-6 );
205 printf( "\t(%g Mflop/s)\n\n", ( y / ( double ) ( t2 - t1 ) ) );
206 printf( "%20s %16s %-15s %-15s\n", "PAPI measurement:",
207 "Acquired count", "Expected event", "PAPI_list_events" );
208
209 for ( j = 0; j < nevents; j++ ) {
210 PAPI_get_event_info( events[j], &info );
211 PAPI_event_code_to_name( truelist[j], name2 );
212 printf( "%20s = %16lld %-15s %-15s %s\n",
213 info.short_descr, refvals[j],
214 info.symbol, name2,
215 strcmp( info.symbol,name2 ) ?
216 "*** MISMATCH ***" : "" );
217 }
218 printf( "\n" );
219 }
220
221 /* Make repeated runs while removing/readding events */
222
223 nev1 = nevents;
224 repeats = nevents * 4;
225
226 /* Repeat four times for each event? */
227
228 for ( i = 0; i < repeats; i++ ) {
229
230 /* What's going on here? as example, nevents=4, repeats=16*/
231 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 == i*/
232 /* 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 == i%nevents */
233 /* 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 == (i%nevents)+1 */
234 /* 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 */
235 /* so we skip nevery NEVENTS time through the loop? */
236 if ( ( i % nevents ) + 1 == nevents ) continue;
237
238 if ( !quiet ) {
239 printf( "\nTest %d (of %d):\n",
240 i + 1 - (i / nevents), repeats - 4 );
241 }
242
243 /* Stop the counter, it's been left running */
244 if ( ( retval = PAPI_stop( eventset, values ) ) ) {
245 test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
246 }
247
248 /* We run through a 4-way pattern */
249 /* 1st quarter, remove events */
250 /* 2nd quarter, add back events */
251 /* 3rd quarter, remove events again */
252 /* 4th wuarter, re-add events */
253 j = eventidx[i % nevents];
254 if ( ( i / nevents ) % 2 == 0 ) {
255
256 /* Remove event */
257 PAPI_get_event_info( events[j], &info );
258 if ( !quiet ) {
259 printf( "Removing event[%d]: %s\n",
260 j, info.short_descr );
261 }
262
263 retval = PAPI_remove_event( eventset, events[j] );
264 if (retval != PAPI_OK ) {
265 test_fail( __FILE__, __LINE__,
266 "PAPI_remove_event", retval );
267 }
268
269 /* Update the complex event mapping */
270 nev1--;
271 for ( idx = 0; eventmap[idx] != j; idx++ );
272 for ( j = idx; j < nev1; j++ )
273 eventmap[j] = eventmap[j + 1];
274 } else {
275
276 /* Add an event back in */
277 PAPI_get_event_info( events[j], &info );
278 if ( !quiet ) {
279 printf( "Adding event[%d]: %s\n",
280 j, info.short_descr );
281 }
282 retval = PAPI_add_event( eventset, events[j] );
283 if (retval != PAPI_OK ) {
284 test_fail( __FILE__, __LINE__,
285 "PAPI_add_event", retval );
286 }
287
288 eventmap[nev1] = j;
289 nev1++;
290 }
291
292 if ( ( retval = PAPI_start( eventset ) ) ) {
293 test_fail( __FILE__, __LINE__, "PAPI_start", retval );
294 }
295
296 x = 1.0;
297
298 // This startstop is leftover from sdsc2? */
299#ifndef STARTSTOP
300 if ( ( retval = PAPI_reset( eventset ) ) )
301 test_fail( __FILE__, __LINE__, "PAPI_reset", retval );
302#else
303 if ( ( retval = PAPI_stop( eventset, dummies ) ) )
304 test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
305 if ( ( retval = PAPI_start( eventset ) ) )
306 test_fail( __FILE__, __LINE__, "PAPI_start", retval );
307#endif
308
309 /* Run the actual workload */
311 y = do_flops3( x, iters, 1 );
312 PAPI_read( eventset, values );
314
315 /* Print approximate flops plus header */
316 if ( !quiet ) {
317 printf( "\n(calculated independent of PAPI)\n" );
318 printf( "\tOperations= %.1f Mflop", y * 1e-6 );
319 printf( "\t(%g Mflop/s)\n\n",
320 ( y / ( double ) ( t2 - t1 ) ) );
321
322 printf( "%20s %16s %-15s %-15s\n",
323 "PAPI measurement:",
324 "Acquired count",
325 "Expected event",
326 "PAPI_list_events" );
327
328
329 ntrue = nev1;
330 PAPI_list_events( eventset, truelist, &ntrue );
331 for ( j = 0; j < nev1; j++ ) {
332 idx = eventmap[j];
333 /* printf("Mapping: Counter %d -> slot %d.\n",j,idx); */
334 PAPI_get_event_info( events[idx], &info );
335 PAPI_event_code_to_name( truelist[j], name2 );
336 printf( "%20s = %16lld %-15s %-15s %s\n",
337 info.short_descr, values[j],
338 info.symbol, name2,
339 strcmp( info.symbol, name2 ) ?
340 "*** MISMATCH ***" : "" );
341 }
342 printf( "\n" );
343 }
344
345 /* Calculate results */
346 for ( j = 0; j < nev1; j++ ) {
347 idx = eventmap[j];
348 dtmp = ( double ) values[j];
349 valsum[idx] += dtmp;
350 valsample[idx][nsamples[idx]] = dtmp;
351 nsamples[idx]++;
352 }
353 }
354
355 /* Stop event for good */
356 if ( ( retval = PAPI_stop( eventset, values ) ) ) {
357 test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
358 }
359
360 if ( !quiet ) {
361 printf( "\n\nEstimated variance relative "
362 "to average counts:\n" );
363 for ( j = 0; j < nev1; j++ ) {
364 printf( " Event %.2d", j );
365 }
366 printf( "\n" );
367 }
368
369 fails = nevents;
370
371 /* Due to limited precision of floating point cannot really use
372 typical standard deviation compuation for large numbers with
373 very small variations. Instead compute the std devation
374 problems with precision.
375 */
376
377 /* Update so that if our event count is small (<1000 or so) */
378 /* Then don't fail with high variation. Since we're multiplexing */
379 /* it's hard to capture such small counts, and it makes the test */
380 /* fail on machines such as Haswell and the PAPI_SR_INS event */
381
382 for ( j = 0; j < nev1; j++ ) {
383
384 avg[j] = valsum[j] / nsamples[j];
385 spread[j] = 0;
386 for ( i = 0; i < nsamples[j]; ++i ) {
387 double diff = ( valsample[j][i] - avg[j] );
388 spread[j] += diff * diff;
389 }
390 spread[j] = sqrt( spread[j] / nsamples[j] ) / avg[j];
391 if ( !quiet ) {
392 printf( "%9.2g ", spread[j] );
393 }
394 }
395
396 for ( j = 0; j < nev1; j++ ) {
397
398 /* Make sure that NaN get counted as errors */
399 if ( spread[j] < MPX_TOLERANCE ) {
400 if (!quiet) printf("Event %d tolerance good\n",j);
401 fails--;
402 }
403 /* Neglect inprecise results with low counts */
404 else if ( avg[j] < MINCOUNTS ) {
405 if (!quiet) printf("Event %d too small to fail\n",j);
406 fails--;
407 }
408 else {
409 if (!quiet) printf("Event %d failed!\n",j);
410 }
411 }
412
413 if ( !quiet ) {
414 printf( "\n\n" );
415 for ( j = 0; j < nev1; j++ ) {
416 PAPI_get_event_info( events[j], &info );
417 printf( "Event %.2d: mean=%10.0f, "
418 "sdev/mean=%7.2g nrpt=%2d -- %s\n",
419 j, avg[j], spread[j],
420 nsamples[j], info.short_descr );
421 }
422 printf( "\n\n" );
423 }
424
425 if ( fails ) {
426 test_fail( __FILE__, __LINE__, "Values differ from reference", fails );
427 }
428
429 test_pass( __FILE__ );
430
431 return 0;
432}
int i
static struct timeval t1 t2
Definition: benchSANVML.c:117
add PAPI preset or native hardware event to an event set
Assign a component index to an existing but empty EventSet.
Create a new empty PAPI EventSet.
Convert a numeric hardware event code to a name.
Get the event's name and description info.
get real time counter value in microseconds
initialize the PAPI library.
list the events in an event set
Initialize multiplex support in the PAPI library.
Read hardware counters from an event set.
removes a hardware event from a PAPI event set.
Reset the hardware event counts in an event set.
Convert a standard event set to a multiplexed event set.
Start counting hardware events in an event set.
Stop counting hardware events in an event set.
volatile double t1
double do_flops3(double x, int iters, int quiet)
#define PAPI_VER_CURRENT
Definition: f90papi.h:54
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_NULL
Definition: f90papi.h:78
#define PAPI_TOT_CYC
Definition: f90papi.h:308
#define PAPI_BR_INS
Definition: f90papi.h:300
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define PAPI_FP_INS
Definition: f90papi.h:366
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_STL_CCY
Definition: f90papi.h:373
#define PAPI_SR_INS
Definition: f90papi.h:357
#define PAPI_INT_INS
Definition: f90papi.h:391
#define PAPI_TOT_INS
Definition: f90papi.h:317
#define PAPI_TOT_IIS
Definition: f90papi.h:379
#define PAPI_LD_INS
Definition: f90papi.h:292
char events[MAX_EVENTS][BUFSIZ]
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
Return codes and api definitions.
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 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
int
Definition: sde_internal.h:89
#define MAXEVENTS
Definition: sdsc4-mpx.c:21
#define MINCOUNTS
Definition: sdsc4-mpx.c:24
#define MPX_TOLERANCE
Definition: sdsc4-mpx.c:25
#define NUM_FLOPS
Definition: sdsc4-mpx.c:26
#define SLEEPTIME
Definition: sdsc4-mpx.c:23
#define REPEATS
Definition: sdsc4-mpx.c:22
char short_descr[PAPI_MIN_STR_LEN]
Definition: papi.h:961
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:960
volatile double y
volatile double x
int retval
Definition: zero_fork.c:53