PAPI  5.7.0.0
sdsc4-mpx.c File Reference
Include dependency graph for sdsc4-mpx.c:

Go to the source code of this file.

Macros

#define MAXEVENTS   9
 
#define REPEATS   (MAXEVENTS * 4)
 
#define SLEEPTIME   100
 
#define MINCOUNTS   100000
 
#define MPX_TOLERANCE   0.20
 
#define NUM_FLOPS   20000000
 

Functions

int main (int argc, char **argv)
 

Macro Definition Documentation

◆ MAXEVENTS

#define MAXEVENTS   9

Definition at line 21 of file sdsc4-mpx.c.

◆ MINCOUNTS

#define MINCOUNTS   100000

Definition at line 24 of file sdsc4-mpx.c.

◆ MPX_TOLERANCE

#define MPX_TOLERANCE   0.20

Definition at line 25 of file sdsc4-mpx.c.

◆ NUM_FLOPS

#define NUM_FLOPS   20000000

Definition at line 26 of file sdsc4-mpx.c.

◆ REPEATS

#define REPEATS   (MAXEVENTS * 4)

Definition at line 22 of file sdsc4-mpx.c.

◆ SLEEPTIME

#define SLEEPTIME   100

Definition at line 23 of file sdsc4-mpx.c.

Function Documentation

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 29 of file sdsc4-mpx.c.

30 {
31  PAPI_event_info_t info;
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 
67  events[0] = PAPI_FP_INS;
68  events[1] = PAPI_TOT_CYC;
69  events[2] = PAPI_TOT_INS;
70  events[3] = PAPI_TOT_IIS;
71  events[4] = PAPI_INT_INS;
72  events[5] = PAPI_STL_CCY;
73  events[6] = PAPI_BR_INS;
74  events[7] = PAPI_SR_INS;
75  events[8] = PAPI_LD_INS;
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 */
159  t1 = PAPI_get_real_usec( );
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 
192  t1 = PAPI_get_real_usec( );
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 );
198  t2 = PAPI_get_real_usec( );
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 */
310  t1 = PAPI_get_real_usec( );
311  y = do_flops3( x, iters, 1 );
312  PAPI_read( eventset, values );
313  t2 = PAPI_get_real_usec( );
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 }
#define PAPI_OK
Definition: fpapi.h:105
int atoi()
int PAPI_stop(int EventSet, long long *values)
Definition: papi.c:2314
#define PAPI_INT_INS
Definition: fpapi.h:187
#define MPX_TOLERANCE
Definition: sdsc4-mpx.c:25
void test_pass(const char *filename)
Definition: test_utils.c:432
int PAPI_add_event(int EventSet, int EventCode)
Definition: papi.c:1663
int PAPI_reset(int EventSet)
Definition: papi.c:2459
#define PAPI_ENOSUPP
Definition: fpapi.h:123
int PAPI_remove_event(int EventSet, int EventCode)
Definition: papi.c:1758
double do_flops3(double x, int iters, int quiet)
#define PAPI_VER_CURRENT
Definition: fpapi.h:14
volatile double t2
int retval
Definition: zero_fork.c:53
#define PAPI_STL_CCY
Definition: fpapi.h:175
volatile double t1
int PAPI_get_event_info(int EventCode, PAPI_event_info_t *info)
Definition: papi.c:835
void test_skip(const char *file, int line, const char *call, int retval)
Definition: test_utils.c:561
char events[MAX_EVENTS][BUFSIZ]
int PAPI_library_init(int version)
Definition: papi.c:500
#define PAPI_TOT_INS
Definition: fpapi.h:186
int quiet
Definition: rapl_overflow.c:18
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:967
#define PAPI_TOT_IIS
Definition: fpapi.h:185
#define PAPI_NULL
Definition: fpapi.h:13
#define PAPI_BR_INS
Definition: fpapi.h:191
char short_descr[PAPI_MIN_STR_LEN]
Definition: papi.h:968
int PAPI_assign_eventset_component(int EventSet, int cidx)
Definition: papi.c:1526
int PAPI_create_eventset(int *EventSet)
Definition: papi.c:1464
int PAPI_event_code_to_name(int EventCode, char *out)
Definition: papi.c:915
#define NUM_FLOPS
Definition: sdsc4-mpx.c:26
#define MAXEVENTS
Definition: sdsc4-mpx.c:21
int PAPI_multiplex_init(void)
Definition: papi.c:2982
#define REPEATS
Definition: sdsc4-mpx.c:22
long long PAPI_get_real_usec(void)
Definition: papi.c:6264
#define SLEEPTIME
Definition: sdsc4-mpx.c:23
int tests_quiet(int argc, char **argv)
Definition: test_utils.c:376
void test_fail(const char *file, int line, const char *call, int retval)
Definition: test_utils.c:468
int x
Definition: fileop.c:78
int PAPI_set_multiplex(int EventSet)
Definition: papi.c:3333
#define MINCOUNTS
Definition: sdsc4-mpx.c:24
int PAPI_read(int EventSet, long long *values)
Definition: papi.c:2559
int PAPI_start(int EventSet)
Definition: papi.c:2096
#define PAPI_TOT_CYC
Definition: fpapi.h:195
static long long values[NUM_EVENTS]
Definition: init_fini.c:10
#define PAPI_LD_INS
Definition: fpapi.h:189
#define PAPI_SR_INS
Definition: fpapi.h:190
#define PAPI_FP_INS
Definition: fpapi.h:188
int i
Definition: fileop.c:140
int PAPI_list_events(int EventSet, int *Events, int *number)
Definition: papi.c:6001
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
long long y
Definition: iozone.c:1335
Here is the call graph for this function: