PAPI  5.7.0.0
papi_tot_ins.c
Go to the documentation of this file.
1 /* This file attempts to test the retired instruction event */
2 /* As implemented by PAPI_TOT_INS */
3 
4 /* For more info on the causes of overcount on x86 systems */
5 /* See the ISPASS2013 paper: */
6 /* "Non-Determinism and Overcount on Modern Hardware */
7 /* Performance Counter Implementations" */
8 
9 /* by Vince Weaver, <vincent.weaver@maine.edu> */
10 
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <errno.h>
16 
17 #include "papi.h"
18 #include "papi_test.h"
19 
20 #include "display_error.h"
21 #include "testcode.h"
22 
23 #define NUM_RUNS 100
24 
25 
26  /* Test a simple loop of 1 million instructions */
27  /* Most implementations should count be correct within 1% */
28  /* This loop in in assembly language, as compiler generated */
29  /* code varies too much. */
30 
31 static void test_million(int quiet) {
32 
33  int i,result,ins_result;
34 
35  long long count,high=0,low=0,total=0,average=0;
36  double error;
37  int eventset=PAPI_NULL;
38 
39  if (!quiet) {
40  printf("\nTesting a loop of 1 million instructions (%d times):\n",
41  NUM_RUNS);
42  }
43 
44  result=PAPI_create_eventset(&eventset);
45  if (result!=PAPI_OK) {
46  test_fail( __FILE__, __LINE__, "PAPI_create_eventset", result );
47  }
48 
49  result=PAPI_add_named_event(eventset,"PAPI_TOT_INS");
50  if (result!=PAPI_OK) {
51  if (!quiet) printf("Could not add PAPI_TOT_INS\n");
52  test_skip( __FILE__, __LINE__, "adding PAPI_TOT_INS", result );
53  }
54 
55  for(i=0;i<NUM_RUNS;i++) {
56 
57  PAPI_reset(eventset);
58  PAPI_start(eventset);
59 
60  ins_result=instructions_million();
61 
62  result=PAPI_stop(eventset,&count);
63 
64  if (ins_result==CODE_UNIMPLEMENTED) {
65  fprintf(stderr,"\tCode unimplemented\n");
66  test_skip( __FILE__, __LINE__, "unimplemented", 0);
67  }
68 
69  if (result!=PAPI_OK) {
70  test_fail( __FILE__, __LINE__,
71  "reading PAPI_TOT_INS", result );
72  }
73 
74  if (count>high) high=count;
75  if ((low==0) || (count<low)) low=count;
76  total+=count;
77  }
78 
79  average=total/NUM_RUNS;
80 
81  error=display_error(average,high,low,1000000ULL,quiet);
82 
83  if ((error > 1.0) || (error<-1.0)) {
84 
85 #if defined(__PPC__)
86 
87  if(!quiet) {
88  printf("If PPC is off by 50%%, this might be due to\n"
89  "\"folded\" branch instructions on PPC32\n");
90  }
91 #endif
92  test_fail( __FILE__, __LINE__, "validation", result );
93 
94  }
95 }
96 
97 /* Test fldcw. Pentium 4 overcounts this instruction */
98 
99 static void test_fldcw(int quiet) {
100 
101  (void)quiet;
102 
103 #if defined(__i386__) || (defined __x86_64__)
104  int i,result,ins_result;
105  int eventset=PAPI_NULL;
106 
107  long long count,high=0,low=0,total=0,average=0;
108  double error;
109 
110  if (!quiet) {
111  printf("\nTesting a fldcw loop of 900,000 instructions (%d times):\n",
112  NUM_RUNS);
113  }
114 
115  result=PAPI_create_eventset(&eventset);
116  if (result!=PAPI_OK) {
117  test_fail( __FILE__, __LINE__, "PAPI_create_eventset", result );
118  }
119 
120  result=PAPI_add_named_event(eventset,"PAPI_TOT_INS");
121  if (result!=PAPI_OK) {
122  test_fail( __FILE__, __LINE__, "adding PAPI_TOT_INS", result );
123  }
124 
125  for(i=0;i<NUM_RUNS;i++) {
126 
127  PAPI_reset(eventset);
128  PAPI_start(eventset);
129 
130  ins_result=instructions_fldcw();
131 
132  result=PAPI_stop(eventset,&count);
133 
134  if (ins_result==CODE_UNIMPLEMENTED) {
135  test_fail( __FILE__, __LINE__, "Code unimplemented", 1 );
136  }
137 
138  if (result!=PAPI_OK) {
139  test_fail( __FILE__, __LINE__, "Unexpected error on read", 1 );
140  }
141 
142  if (count>high) high=count;
143  if ((low==0) || (count<low)) low=count;
144  total+=count;
145  }
146 
147  average=total/NUM_RUNS;
148 
149  error=display_error(average,high,low,900000ULL,quiet);
150 
151  if ((error > 1.0) || (error<-1.0)) {
152 
153  if (!quiet) {
154  printf("On Pentium 4 machines, the fldcw instruction counts as 2.\n");
155  printf("This will lead to an overcount of 22%%\n");
156  }
157  test_fail( __FILE__, __LINE__, "Error too high", 1 );
158  }
159 #endif
160 }
161 
162 /* Test rep-prefixed instructions. */
163 /* HW counters count this as one each, not one per repeat */
164 
165 static void test_rep(int quiet) {
166 
167  (void)quiet;
168 
169 #if defined(__i386__) || (defined __x86_64__)
170  int i,result,ins_result;
171  int eventset=PAPI_NULL;
172 
173  long long count,high=0,low=0,total=0,average=0;
174  double error;
175 
176  if(!quiet) {
177  printf("\nTesting a 16k rep loop (%d times):\n", NUM_RUNS);
178  }
179 
180  result=PAPI_create_eventset(&eventset);
181  if (result!=PAPI_OK) {
182  test_fail( __FILE__, __LINE__, "PAPI_create_eventset", result );
183  }
184 
185  result=PAPI_add_named_event(eventset,"PAPI_TOT_INS");
186  if (result!=PAPI_OK) {
187  test_fail( __FILE__, __LINE__, "adding PAPI_TOT_INS", result );
188  }
189 
190  for(i=0;i<NUM_RUNS;i++) {
191 
192  PAPI_reset(eventset);
193  PAPI_start(eventset);
194 
195  ins_result=instructions_rep();
196 
197  result=PAPI_stop(eventset,&count);
198 
199  if (ins_result==CODE_UNIMPLEMENTED) {
200  fprintf(stderr,"\tCode unimplemented\n");
201  test_fail( __FILE__, __LINE__, "Code unimplemented", 1 );
202  }
203 
204  if (result!=PAPI_OK) {
205  test_fail( __FILE__, __LINE__, "Unexpected error on read", 1 );
206  }
207 
208  if (count>high) high=count;
209  if ((low==0) || (count<low)) low=count;
210  total+=count;
211  }
212 
213  average=total/NUM_RUNS;
214 
215  error=display_error(average,high,low,6002,quiet);
216 
217  if ((error > 10.0) || (error<-10.0)) {
218  if (!quiet) {
219  printf("Instruction count off by more than 10%%\n");
220  }
221  test_fail( __FILE__, __LINE__, "Error too high", 1 );
222  }
223 #endif
224 }
225 
226 int main(int argc, char **argv) {
227 
228  int retval;
229  int quiet=0;
230 
231  (void)argc;
232  (void)argv;
233 
234  quiet=tests_quiet(argc,argv);
235 
236  if (!quiet) {
237  printf("\nThis test checks that the \"PAPI_TOT_INS\" generalized "
238  "event is working.\n");
239  }
240 
241  /* Init the PAPI library */
243  if ( retval != PAPI_VER_CURRENT ) {
244  test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
245  }
246 
248  test_fldcw(quiet);
249  test_rep(quiet);
250 
251  if (!quiet) printf("\n");
252 
253  test_pass( __FILE__ );
254 
255  PAPI_shutdown();
256 
257  return 0;
258 }
#define PAPI_OK
Definition: fpapi.h:105
int PAPI_stop(int EventSet, long long *values)
Definition: papi.c:2314
void test_pass(const char *filename)
Definition: test_utils.c:432
int PAPI_reset(int EventSet)
Definition: papi.c:2459
double display_error(long long average, long long high, long long low, long long expected, int quiet)
Definition: display_error.c:7
static void test_million(int quiet)
Definition: papi_tot_ins.c:31
#define PAPI_VER_CURRENT
Definition: fpapi.h:14
#define CODE_UNIMPLEMENTED
Definition: testcode.h:2
int retval
Definition: zero_fork.c:53
Return codes and api definitions.
void test_skip(const char *file, int line, const char *call, int retval)
Definition: test_utils.c:561
int PAPI_add_named_event(int EventSet, const char *EventName)
Definition: papi.c:1876
int main(int argc, char **argv)
Definition: papi_tot_ins.c:226
int PAPI_library_init(int version)
Definition: papi.c:500
void PAPI_shutdown(void)
Definition: papi.c:4461
int quiet
Definition: rapl_overflow.c:18
#define PAPI_NULL
Definition: fpapi.h:13
static void test_fldcw(int quiet)
Definition: papi_tot_ins.c:99
int instructions_million(void)
int PAPI_create_eventset(int *EventSet)
Definition: papi.c:1464
#define NUM_RUNS
Definition: papi_tot_ins.c:23
int instructions_rep(void)
static int total
Definition: rapl_overflow.c:9
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
static void test_rep(int quiet)
Definition: papi_tot_ins.c:165
int instructions_fldcw(void)
int PAPI_start(int EventSet)
Definition: papi.c:2096
static long count
int i
Definition: fileop.c:140