PAPI  5.4.1.0
calibrate.c
Go to the documentation of this file.
1 /*
2  Calibrate.c
3  A program to perform one or all of three tests to count flops.
4  Test 1. Inner Product: 2*n operations
5  for i = 1:n; a = a + x(i)*y(i); end
6  Test 2. Matrix Vector Product: 2*n^2 operations
7  for i = 1:n; for j = 1:n; x(i) = x(i) + a(i,j)*y(j); end; end;
8  Test 3. Matrix Matrix Multiply: 2*n^3 operations
9  for i = 1:n; for j = 1:n; for k = 1:n; c(i,j) = c(i,j) + a(i,k)*b(k,j); end; end; end;
10
11  Supply a command line argument of 1, 2, or 3 to perform each test, or
12  no argument to perform all three.
13
14  Each test initializes PAPI and presents a header with processor information.
15  Then it performs 500 iterations, printing result lines containing:
16  n, measured counts, theoretical counts, (measured - theory), % error
17  */
18
19 #include "papi_test.h"
20
21 static void resultline( int i, int j, int EventSet, int fail );
22 static void headerlines( char *title, int TESTS_QUIET );
23
24 #define INDEX1 100
25 #define INDEX5 500
26
27 #define MAX_WARN 10
28 #define MAX_ERROR 80
29 #define MAX_DIFF 14
30
31 extern int TESTS_QUIET;
32
33 static void
34 print_help( char **argv )
35 {
36  printf( "Usage: %s [-ivmdh] [-e event]\n", argv[0] );
37  printf( "Options:\n\n" );
38  printf( "\t-i Inner Product test.\n" );
39  printf( "\t-v Matrix-Vector multiply test.\n" );
40  printf( "\t-m Matrix-Matrix multiply test.\n" );
41  printf( "\t-d Double precision data. Default is float.\n" );
42  printf
43  ( "\t-e event Use <event> as PAPI event instead of PAPI_FP_OPS\n" );
44  printf( "\t-f Suppress failures\n" );
45  printf( "\t-h Print this help message\n" );
46  printf( "\n" );
47  printf
48  ( "This test measures floating point operations for the specified test.\n" );
49  printf( "Operations can be performed in single or double precision.\n" );
50  printf( "Default operation is all three tests in single precision.\n" );
51 }
52
53 static float
54 inner_single( int n, float *x, float *y )
55 {
56  float aa = 0.0;
57  int i;
58
59  for ( i = 0; i <= n; i++ )
60  aa = aa + x[i] * y[i];
61  return ( aa );
62 }
63
64 static double
65 inner_double( int n, double *x, double *y )
66 {
67  double aa = 0.0;
68  int i;
69
70  for ( i = 0; i <= n; i++ )
71  aa = aa + x[i] * y[i];
72  return ( aa );
73 }
74
75 static void
76 vector_single( int n, float *a, float *x, float *y )
77 {
78  int i, j;
79
80  for ( i = 0; i <= n; i++ )
81  for ( j = 0; j <= n; j++ )
82  y[i] = y[i] + a[i * n + j] * x[i];
83 }
84
85 static void
86 vector_double( int n, double *a, double *x, double *y )
87 {
88  int i, j;
89
90  for ( i = 0; i <= n; i++ )
91  for ( j = 0; j <= n; j++ )
92  y[i] = y[i] + a[i * n + j] * x[i];
93 }
94
95 static void
96 matrix_single( int n, float *c, float *a, float *b )
97 {
98  int i, j, k;
99
100  for ( i = 0; i <= n; i++ )
101  for ( j = 0; j <= n; j++ )
102  for ( k = 0; k <= n; k++ )
103  c[i * n + j] = c[i * n + j] + a[i * n + k] * b[k * n + j];
104 }
105
106 static void
107 matrix_double( int n, double *c, double *a, double *b )
108 {
109  int i, j, k;
110
111  for ( i = 0; i <= n; i++ )
112  for ( j = 0; j <= n; j++ )
113  for ( k = 0; k <= n; k++ )
114  c[i * n + j] = c[i * n + j] + a[i * n + k] * b[k * n + j];
115 }
116
117 static void
118 reset_flops( char *title, int EventSet )
119 {
120  int retval;
121  char err_str[PAPI_MAX_STR_LEN];
122
123  retval = PAPI_start( EventSet );
124  if ( retval != PAPI_OK ) {
125  sprintf( err_str, "%s: PAPI_start", title );
126  test_fail( __FILE__, __LINE__, err_str, retval );
127  }
128 }
129
130 int
131 main( int argc, char *argv[] )
132 {
133  extern void dummy( void * );
134
135  float aa, *a, *b, *c, *x, *y;
136  double aad, *ad, *bd, *cd, *xd, *yd;
137  int i, j, n;
138  int inner = 0;
139  int vector = 0;
140  int matrix = 0;
141  int double_precision = 0;
142  int fail = 1;
143  int retval = PAPI_OK;
144  char papi_event_str[PAPI_MIN_STR_LEN] = "PAPI_FP_OPS";
145  int papi_event;
146  int EventSet = PAPI_NULL;
147
148 /* Parse the input arguments */
149  for ( i = 0; i < argc; i++ ) {
150  if ( strstr( argv[i], "-i" ) )
151  inner = 1;
152  else if ( strstr( argv[i], "-f" ) )
153  fail = 0;
154  else if ( strstr( argv[i], "-v" ) )
155  vector = 1;
156  else if ( strstr( argv[i], "-m" ) )
157  matrix = 1;
158  else if ( strstr( argv[i], "-e" ) ) {
159  if ( ( argv[i + 1] == NULL ) || ( strlen( argv[i + 1] ) == 0 ) ) {
160  print_help( argv );
161  exit( 1 );
162  }
163  strncpy( papi_event_str, argv[i + 1], sizeof ( papi_event_str ) - 1);
164  papi_event_str[sizeof ( papi_event_str )-1] = '\0';
165  i++;
166  } else if ( strstr( argv[i], "-d" ) )
167  double_precision = 1;
168  else if ( strstr( argv[i], "-h" ) ) {
169  print_help( argv );
170  exit( 1 );
171  }
172  }
173
174  /* if no options specified, set all tests to TRUE */
175  if ( inner + vector + matrix == 0 )
176  inner = vector = matrix = 1;
177
178
179  tests_quiet( argc, argv ); /* Set TESTS_QUIET variable */
180
181  if ( !TESTS_QUIET )
182  printf( "Initializing..." );
183
184  /* Initialize PAPI */
186  if ( retval != PAPI_VER_CURRENT )
187  test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
188
189  /* Translate name */
190  retval = PAPI_event_name_to_code( papi_event_str, &papi_event );
191  if ( retval != PAPI_OK )
192  test_fail( __FILE__, __LINE__, "PAPI_event_name_to_code", retval );
193
194  if ( PAPI_query_event( papi_event ) != PAPI_OK )
195  test_skip( __FILE__, __LINE__, "PAPI_query_event", PAPI_ENOEVNT );
196
197  if ( ( retval = PAPI_create_eventset( &EventSet ) ) != PAPI_OK )
198  test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval );
199
200  if ( ( retval = PAPI_add_event( EventSet, papi_event ) ) != PAPI_OK )
201  test_fail( __FILE__, __LINE__, "PAPI_add_event", retval );
202
203  printf( "\n" );
204
205  retval = PAPI_OK;
206
207  /* Inner Product test */
208  if ( inner ) {
209  /* Allocate the linear arrays */
210  if (double_precision) {
211  xd = malloc( INDEX5 * sizeof(double) );
212  yd = malloc( INDEX5 * sizeof(double) );
213  if ( !( xd && yd ) )
214  retval = PAPI_ENOMEM;
215  }
216  else {
217  x = malloc( INDEX5 * sizeof(float) );
218  y = malloc( INDEX5 * sizeof(float) );
219  if ( !( x && y ) )
220  retval = PAPI_ENOMEM;
221  }
222
223  if ( retval == PAPI_OK ) {
224  headerlines( "Inner Product Test", TESTS_QUIET );
225
226  /* step through the different array sizes */
227  for ( n = 0; n < INDEX5; n++ ) {
228  if ( n < INDEX1 || ( ( n + 1 ) % 50 ) == 0 ) {
229
230  /* Initialize the needed arrays at this size */
231  if ( double_precision ) {
232  for ( i = 0; i <= n; i++ ) {
233  xd[i] = ( double ) rand( ) * ( double ) 1.1;
234  yd[i] = ( double ) rand( ) * ( double ) 1.1;
235  }
236  } else {
237  for ( i = 0; i <= n; i++ ) {
238  x[i] = ( float ) rand( ) * ( float ) 1.1;
239  y[i] = ( float ) rand( ) * ( float ) 1.1;
240  }
241  }
242
243  /* reset PAPI flops count */
244  reset_flops( "Inner Product Test", EventSet );
245
246  /* do the multiplication */
247  if ( double_precision ) {
248  aad = inner_double( n, xd, yd );
249  dummy( ( void * ) &aad );
250  } else {
251  aa = inner_single( n, x, y );
252  dummy( ( void * ) &aa );
253  }
254  resultline( n, 1, EventSet, fail );
255  }
256  }
257  }
258  if (double_precision) {
259  free( xd );
260  free( yd );
261  } else {
262  free( x );
263  free( y );
264  }
265  }
266
267  /* Matrix Vector test */
268  if ( vector && retval != PAPI_ENOMEM ) {
269  /* Allocate the needed arrays */
270  if (double_precision) {
271  ad = malloc( INDEX5 * INDEX5 * sizeof(double) );
272  xd = malloc( INDEX5 * sizeof(double) );
273  yd = malloc( INDEX5 * sizeof(double) );
274  if ( !( ad && xd && yd ) )
275  retval = PAPI_ENOMEM;
276  } else {
277  a = malloc( INDEX5 * INDEX5 * sizeof(float) );
278  x = malloc( INDEX5 * sizeof(float) );
279  y = malloc( INDEX5 * sizeof(float) );
280  if ( !( a && x && y ) )
281  retval = PAPI_ENOMEM;
282  }
283
284  if ( retval == PAPI_OK ) {
285  headerlines( "Matrix Vector Test", TESTS_QUIET );
286
287  /* step through the different array sizes */
288  for ( n = 0; n < INDEX5; n++ ) {
289  if ( n < INDEX1 || ( ( n + 1 ) % 50 ) == 0 ) {
290
291  /* Initialize the needed arrays at this size */
292  if ( double_precision ) {
293  for ( i = 0; i <= n; i++ ) {
294  yd[i] = 0.0;
295  xd[i] = ( double ) rand( ) * ( double ) 1.1;
296  for ( j = 0; j <= n; j++ )
297  ad[i * n + j] =
298  ( double ) rand( ) * ( double ) 1.1;
299  }
300  } else {
301  for ( i = 0; i <= n; i++ ) {
302  y[i] = 0.0;
303  x[i] = ( float ) rand( ) * ( float ) 1.1;
304  for ( j = 0; j <= n; j++ )
305  a[i * n + j] =
306  ( float ) rand( ) * ( float ) 1.1;
307  }
308  }
309
310  /* reset PAPI flops count */
311  reset_flops( "Matrix Vector Test", EventSet );
312
313  /* compute the resultant vector */
314  if ( double_precision ) {
315  vector_double( n, ad, xd, yd );
316  dummy( ( void * ) yd );
317  } else {
318  vector_single( n, a, x, y );
319  dummy( ( void * ) y );
320  }
321  resultline( n, 2, EventSet, fail );
322  }
323  }
324  }
325  if (double_precision) {
326  free( ad );
327  free( xd );
328  free( yd );
329  } else {
330  free( a );
331  free( x );
332  free( y );
333  }
334  }
335
336  /* Matrix Multiply test */
337  if ( matrix && retval != PAPI_ENOMEM ) {
338  /* Allocate the needed arrays */
339  if (double_precision) {
340  ad = malloc( INDEX5 * INDEX5 * sizeof(double) );
341  bd = malloc( INDEX5 * INDEX5 * sizeof(double) );
342  cd = malloc( INDEX5 * INDEX5 * sizeof(double) );
343  if ( !( ad && bd && cd ) )
344  retval = PAPI_ENOMEM;
345  } else {
346  a = malloc( INDEX5 * INDEX5 * sizeof(float) );
347  b = malloc( INDEX5 * INDEX5 * sizeof(float) );
348  c = malloc( INDEX5 * INDEX5 * sizeof(float) );
349  if ( !( a && b && c ) )
350  retval = PAPI_ENOMEM;
351  }
352
353
354  if ( retval == PAPI_OK ) {
355  headerlines( "Matrix Multiply Test", TESTS_QUIET );
356
357  /* step through the different array sizes */
358  for ( n = 0; n < INDEX5; n++ ) {
359  if ( n < INDEX1 || ( ( n + 1 ) % 50 ) == 0 ) {
360
361  /* Initialize the needed arrays at this size */
362  if ( double_precision ) {
363  for ( i = 0; i <= n * n + n; i++ ) {
364  cd[i] = 0.0;
365  ad[i] = ( double ) rand( ) * ( double ) 1.1;
366  bd[i] = ( double ) rand( ) * ( double ) 1.1;
367  }
368  } else {
369  for ( i = 0; i <= n * n + n; i++ ) {
370  c[i] = 0.0;
371  a[i] = ( float ) rand( ) * ( float ) 1.1;
372  b[i] = ( float ) rand( ) * ( float ) 1.1;
373  }
374  }
375
376  /* reset PAPI flops count */
377  reset_flops( "Matrix Multiply Test", EventSet );
378
379  /* compute the resultant matrix */
380  if ( double_precision ) {
381  matrix_double( n, cd, ad, bd );
382  dummy( ( void * ) c );
383  } else {
384  matrix_single( n, c, a, b );
385  dummy( ( void * ) c );
386  }
387  resultline( n, 3, EventSet, fail );
388  }
389  }
390  }
391  if (double_precision) {
392  free( ad );
393  free( bd );
394  free( cd );
395  } else {
396  free( a );
397  free( b );
398  free( c );
399  }
400  }
401
402  /* exit with status code */
403  if ( retval == PAPI_ENOMEM )
404  test_fail( __FILE__, __LINE__, "malloc", retval );
405  else
406  test_pass( __FILE__, NULL, 0 );
407  exit( 1 );
408 }
409
410 /*
411  Extract and display hardware information for this processor.
412  (Re)Initialize PAPI_flops() and begin counting floating ops.
413 */
414 static void
415 headerlines( char *title, int TESTS_QUIET )
416 {
417  const PAPI_hw_info_t *hwinfo = NULL;
418
419  if ( !TESTS_QUIET ) {
420  if ( papi_print_header( "", &hwinfo ) != PAPI_OK )
421  test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 );
422
423  printf( "\n%s:\n%8s %12s %12s %8s %8s\n", title, "i", "papi", "theory",
424  "diff", "%error" );
425  printf
426  ( "-------------------------------------------------------------------------\n" );
427  }
428 }
429
430 /*
431  Read PAPI_flops.
432  Format and display results.
433  Compute error without using floating ops.
434 */
435 #if defined(mips)
436 #define FMA 1
437 #elif (defined(sparc) && defined(sun))
438 #define FMA 1
439 #else
440 #define FMA 0
441 #endif
442
443 static void
444 resultline( int i, int j, int EventSet, int fail )
445 {
446  float ferror = 0;
447  long long flpins = 0;
448  long long papi, theory;
449  int diff, retval;
450  char err_str[PAPI_MAX_STR_LEN];
451
452  retval = PAPI_stop( EventSet, &flpins );
453  if ( retval != PAPI_OK )
454  test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
455
456  i++; /* convert to 1s base */
457  theory = 2;
458  while ( j-- )
459  theory *= i; /* theoretical ops */
460  papi = flpins << FMA;
461
462  diff = ( int ) ( papi - theory );
463
464  ferror = ( ( float ) abs( diff ) ) / ( ( float ) theory ) * 100;
465
466  printf( "%8d %12lld %12lld %8d %10.4f\n", i, papi, theory, diff, ferror );
467
468  if ( ferror > MAX_WARN && abs( diff ) > MAX_DIFF && i > 20 ) {
469  sprintf( err_str, "Calibrate: difference exceeds %d percent", MAX_WARN );
470  test_warn( __FILE__, __LINE__, err_str, 0 );
471  }
472  if (fail) {
473  if ( ferror > MAX_ERROR && abs( diff ) > MAX_DIFF && i > 20 ) {
474  sprintf( err_str, "Calibrate: error exceeds %d percent", MAX_ERROR );
475  test_fail( __FILE__, __LINE__, err_str, PAPI_EMISC );
476  }
477  }
478 }
#define PAPI_ENOEVNT
Definition: papi.h:258
sprintf(splash[splash_line++],"\tIozone: Performance Test of File I/O\n")
int PAPI_stop(int EventSet, long long *values)
Definition: papi.c:2305
static void reset_flops(char *title, int EventSet)
Definition: calibrate.c:118
int PAPI_add_event(int EventSet, int EventCode)
Definition: papi.c:1668
Hardware info structure.
Definition: papi.h:777
static void headerlines(char *title, int TESTS_QUIET)
Definition: calibrate.c:415
static void vector_double(int n, double *a, double *x, double *y)
Definition: calibrate.c:86
static void resultline(int i, int j, int EventSet, int fail)
Definition: calibrate.c:444
void test_skip(char *file, int line, char *call, int retval)
Definition: test_utils.c:614
int papi_print_header(char *prompt, const PAPI_hw_info_t **hwinfo)
Definition: test_utils.c:21
#define MAX_ERROR
Definition: calibrate.c:28
#define PAPI_NULL
Definition: papi.h:290
static float inner_single(int n, float *x, float *y)
Definition: calibrate.c:54
int EventSet
Definition: data_range.c:25
static void vector_single(int n, float *a, float *x, float *y)
Definition: calibrate.c:76
return PAPI_OK
Definition: linux-nvml.c:458
tests_quiet(argc, argv)
double aa[N]
Definition: byte_profile.c:30
static void matrix_single(int n, float *c, float *a, float *b)
Definition: calibrate.c:96
#define printf
Definition: papi_test.h:125
double c
Definition: multiplex.c:22
static double
Definition: fileop.c:1281
test_pass(__FILE__, NULL, 0)
int int argc
Definition: iozone.c:1609
static double a[MATRIX_SIZE][MATRIX_SIZE]
Definition: rapl_basic.c:37
int dummy
Definition: iozone.c:19741
static void matrix_double(int n, double *c, double *a, double *b)
Definition: calibrate.c:107
#define FMA
Definition: calibrate.c:440
int TESTS_QUIET
Definition: test_utils.c:11
char ** argv
Definition: iozone.c:1610
#define PAPI_EMISC
Definition: papi.h:265
test_fail(__FILE__, __LINE__,"PAPI_library_init", retval)
#define INDEX5
Definition: calibrate.c:25
int PAPI_library_init(int version)
Definition: papi.c:500
long long y
Definition: iozone.c:1335
int i
Definition: fileop.c:140
void test_warn(char *file, int line, char *call, int retval)
Definition: test_utils.c:578
#define MAX_WARN
Definition: calibrate.c:27
free(dummyfile[xx])
int k
Definition: iozone.c:19136
static void print_help(char **argv)
Definition: calibrate.c:34
#define INDEX1
Definition: calibrate.c:24
int PAPI_create_eventset(int *EventSet)
Definition: papi.c:1469
#define PAPI_ENOMEM
Definition: papi.h:252
int PAPI_event_name_to_code(char *in, int *out)
Definition: papi.c:1013
int PAPI_query_event(int EventCode)
Definition: papi.c:693
static double b[MATRIX_SIZE][MATRIX_SIZE]
Definition: rapl_basic.c:38
int
Definition: iozone.c:18528
#define PAPI_MIN_STR_LEN
Definition: papi.h:462
int x
Definition: fileop.c:78
int rand()
static double inner_double(int n, double *x, double *y)
Definition: calibrate.c:65
#define PAPI_MAX_STR_LEN
Definition: papi.h:463
int PAPI_start(int EventSet)
Definition: papi.c:2100
long j
Definition: iozone.c:19135
ssize_t retval
Definition: libasync.c:338
#define PAPI_VER_CURRENT
Definition: papi.h:223
int main(int argc, char **argv)
List all appio events codes and names.
void exit()
#define MAX_DIFF
Definition: calibrate.c:29
int n
Definition: mendes-alt.c:164