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