1
/* gcc whets.c cpuidc64.o cpuida64.o -m64 -lrt -lc -lm -o whet
3
* XXX modified by emscripten to be slower, to not slow down test runner
6
* File Group: Classic Benchmarks
7
* Creation Date: 6 November 1996
8
* Revision Date: 6 November 2010 Ubuntu Version for PCs
10
* Title: Whetstone Benchmark in C/C++
11
* Keywords: WHETSTONE BENCHMARK PERFORMANCE MIPS
14
* Abstract: C or C++ version of Whetstone one of the
15
* Classic Numeric Benchmarks with example
16
* results on P3 to P6 based PCs.
18
* Contributor: roy@roylongbottom.org.uk
20
************************************************************
22
* C/C++ Whetstone Benchmark Single or Double Precision
24
* Original concept Brian Wichmann NPL 1960's
25
* Original author Harold Curnow CCTA 1972
26
* Self timing versions Roy Longbottom CCTA 1978/87
27
* Optimisation control Bangor University 1987/90
28
* C/C++ Version Roy Longbottom 1996
29
* Compatibility & timers Al Aburto 1996
31
************************************************************
33
* Official version approved by:
35
* Harold Curnow 100421.1615@compuserve.com
37
* Happy 25th birthday Whetstone, 21 November 1997
39
************************************************************
41
* The program normally runs for about 100 seconds
42
* (adjustable in main - variable duration). This time
43
* is necessary because of poor PC clock resolution.
44
* The original concept included such things as a given
45
* number of subroutine calls and divides which may be
46
* changed by optimisation. For comparison purposes the
47
* compiler and level of optimisation should be identified.
49
* This version is set to run for 10 seconds using high
52
************************************************************
54
* The original benchmark had a single variable I which
55
* controlled the running time. Constants with values up
56
* to 899 were multiplied by I to control the number
57
* passes for each loop. It was found that large values
58
* of I could overflow index registers so an extra outer
59
* loop with a second variable J was added.
61
* Self timing versions were produced during the early
62
* days. The 1978 changes supplied timings of individual
63
* loops and these were used later to produce MFLOPS and
66
* 1987 changes converted the benchmark to Fortran 77
67
* standards and removed redundant IF statements and
68
* loops to leave the 8 active loops N1 to N8. Procedure
69
* P3 was changed to use global variables to avoid over-
70
* optimisation with the first two statements changed from
71
* X1=X and Y1=Y to X=Y and Y=Z. A self time calibrating
72
* version for PCs was also produced, the facility being
73
* incorporated in this version.
75
* This version has changes to avoid worse than expected
76
* speed ratings, due to underflow, and facilities to show
77
* that consistent numeric output is produced with varying
78
* optimisation levels or versions in different languages.
80
* Some of the procedures produce ever decreasing numbers.
81
* To avoid problems, variables T and T1 have been changed
82
* from 0.499975 and 0.50025 to 0.49999975 and 0.50000025.
84
* Each section now has its own double loop. Inner loops
85
* are run 100 times the loop constants. Calibration
86
* determines the number of outer loop passes. The
87
* numeric results produced in the main output are for
88
* one pass on the outer loop. As underflow problems were
89
* still likely on a processor 100 times faster than a 100
90
* MHz Pentium, three sections have T=1.0-T inserted in the
91
* outer loop to avoid the problem. The two loops avoid
92
* index register overflows.
94
* The first section is run ten times longer than required
95
* for accuracy in calculating MFLOPS. This time is divided
96
* by ten for inclusion in the MWIPS calculations.
98
* Early version has facilities for typing in details of
99
* the particular run, appended to file whets.txt along
100
* with the results. This version attemps to obtain these
103
* 2010 Section 4 modified slightly to avoid over optimisation
106
* Roy Longbottom roy@roylongbottom.org.uk
108
************************************************************
110
* Whetstone benchmark results, further details of the
111
* benchmarks and history are available from:
113
* http://www.roylongbottom.org.uk/whetstone%20results.htm
114
* http://www.roylongbottom.org.uk/whetstone.htm
116
************************************************************
118
* Source code is available in C/C++, Fortran, Basic and
119
* Visual Basic in the same format as this version. Pre-
120
* compiled versions for PCs are also available via C++.
121
* These comprise optimised and non-optimised versions
122
* for DOS, Windows and NT. See:
124
* http://www.roylongbottom.org.uk/whetstone%20results.htm
126
************************************************************
128
* Example of initial calibration display (Pentium 100 MHz)
130
* Single Precision C/C++ Whetstone Benchmark
133
* 0.17 Seconds 1 Passes (x 100)
134
* 0.77 Seconds 5 Passes (x 100)
135
* 3.70 Seconds 25 Passes (x 100)
137
* Use 676 passes (x 100)
139
* 676 passes are used for an approximate duration of 100
140
* seconds, providing an initial estimate of a speed rating
143
* This is followed by the table of results as below.
145
* Whetstone Single Precision Benchmark in C/C++
147
* Loop content Result MFLOPS MOPS Seconds
149
* N1 floating point -1.12475025653839100 19.971 0.274
150
* N2 floating point -1.12274754047393800 11.822 3.240
151
* N3 if then else 1.00000000000000000 11.659 2.530
152
* N4 fixed point 12.00000000000000000 13.962 6.430
153
* N5 sin,cos etc. 0.49904659390449520 2.097 11.310
154
* N6 floating point 0.99999988079071040 3.360 45.750
155
* N7 assignments 3.00000000000000000 2.415 21.810
156
* N8 exp,sqrt etc. 0.75110864639282230 1.206 8.790
158
* MWIPS 28.462 100.134
160
* Note different numeric results to single precision. Slight variations
161
* are normal with different compilers and sometimes optimisation levels.
163
**************************************************************************/
165
#define _CRT_SECURE_NO_WARNINGS 1
169
#include <sys/time.h>
172
#include <math.h> /* for sin, exp etc. */
173
#include <stdio.h> /* standard I/O */
174
#include <string.h> /* for strcpy - 3 occurrences */
175
#include <stdlib.h> /* for exit - 1 occurrence */
178
/* #include "cpuidh.h" */
180
/*PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION*/
186
#define Precision "Double"
189
#define Precision "Single"
192
#define opt "Opt 3 64 Bit"
194
void whetstones(long xtra, long x100, int calibrate);
195
void pa(SPDP e[4], SPDP t, SPDP t2);
196
void po(SPDP e1[4], long j, long k, long l);
197
void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2);
198
void pout(char title[22], float ops, int type, SPDP checknum,
199
SPDP time, int calibrate, int section);
202
static SPDP loop_time[9];
203
static SPDP loop_mops[9];
204
static SPDP loop_mflops[9];
205
static SPDP TimeUsed;
207
static char headings[9][18];
209
static SPDP results[9];
211
/* this is truly rank, but it's minimally invasive, and lifted in part from the STREAM scores */
223
i = gettimeofday(&tp,&tzp);
224
return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 );
230
static LARGE_INTEGER freq = {0};
231
LARGE_INTEGER count = {0};
232
if(freq.QuadPart == 0LL) {
233
QueryPerformanceFrequency(&freq);
235
QueryPerformanceCounter(&count);
236
return (double)count.QuadPart / (double)freq.QuadPart;
248
secs = mysecond() - secs;
251
int main(int argc, char *argv[])
253
int count = 1, calibrate = 1;
258
char compiler[80], options[256], general[10][80] = {" "};
263
printf("##########################################\n");
268
sprintf(timeday, "%s", asctime(localtime(&t)));
270
printf("%s Precision C Whetstone Benchmark %s, %s\n", Precision, opt, timeday);
273
printf("Calibrate\n");
278
whetstones(xtra,x100,calibrate);
280
printf("%11.2f Seconds %10.0lf Passes (x 100)\n",
281
TimeUsed,(SPDP)(xtra));
297
if (TimeUsed > 0) xtra = (long)((SPDP)(duration * xtra) / TimeUsed);
298
if (xtra < 1) xtra = 1;
302
printf("\nUse %d passes (x 100)\n", (int)xtra);
304
printf("\n %s Precision C/C++ Whetstone Benchmark",Precision);
307
printf("\n Compiler %s", precompiler);
308
printf("\n Options %s\n", preoptions);
313
printf("\nLoop content Result MFLOPS "
314
" MOPS Seconds\n\n");
317
whetstones(xtra,x100,calibrate);
322
mwips=(float)(xtra) * (float)(x100) / (10 * TimeUsed);
329
printf("%39.3f%19.3f\n\n",mwips,TimeUsed);
331
if (Check == 0) printf("Wrong answer ");
334
printf ("A new results file, whets.txt, will have been created in the same\n");
335
printf ("directory as the .EXE files, if one did not already exist.\n\n");
340
void whetstones(long xtra, long x100, int calibrate)
343
long n1,n2,n3,n4,n5,n6,n7,n8,i,ix,n1mult;
350
SPDP t1 = 0.50000025;
365
/* Section 1, Array elements */
373
for (ix=0; ix<xtra; ix++)
375
for(i=0; i<n1*n1mult; i++)
377
e1[0] = (e1[0] + e1[1] + e1[2] - e1[3]) * t;
378
e1[1] = (e1[0] + e1[1] - e1[2] + e1[3]) * t;
379
e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * t;
380
e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * t;
387
secs = secs/(SPDP)(n1mult);
388
pout("N1 floating point\0",(float)(n1*16)*(float)(xtra),
389
1,e1[3],secs,calibrate,1);
391
/* Section 2, Array as parameter */
395
for (ix=0; ix<xtra; ix++)
406
pout("N2 floating point\0",(float)(n2*96)*(float)(xtra),
407
1,e1[3],secs,calibrate,2);
409
/* Section 3, Conditional jumps */
413
for (ix=0; ix<xtra; ix++)
427
pout("N3 if then else \0",(float)(n3*3)*(float)(xtra),
428
2,(SPDP)(j),secs,calibrate,3);
430
/* Section 4, Integer arithmetic */
438
for (ix=0; ix<xtra; ix++)
443
k = l * k - (l-j) * k;
445
e1[l-2] = e1[l-2] + j + k + l;
446
e1[k-2] = e1[k-2] + j * k * l;
447
// was e1[l-2] = j + k + l; and e1[k-2] = j * k * l;
452
x = (e1[0]+e1[1])/(SPDP)n4/(SPDP)xtra; // was x = e1[0]+e1[1];
453
pout("N4 fixed point \0",(float)(n4*15)*(float)(xtra),
454
2,x,secs,calibrate,4);
456
/* Section 5, Trig functions */
461
for (ix=0; ix<xtra; ix++)
465
x = t*atan(t2*sin(x)*cos(x)/(cos(x+y)+cos(x-y)-1.0));
466
y = t*atan(t2*sin(y)*cos(y)/(cos(x+y)+cos(x-y)-1.0));
473
pout("N5 sin,cos etc. \0",(float)(n5*26)*(float)(xtra),
474
2,y,secs,calibrate,5);
477
/* Section 6, Procedure calls */
484
for (ix=0; ix<xtra; ix++)
488
p3(&x,&y,&z,t,t1,t2);
493
pout("N6 floating point\0",(float)(n6*6)*(float)(xtra),
494
1,z,secs,calibrate,6);
496
/* Section 7, Array refrences */
505
for (ix=0; ix<xtra; ix++)
514
pout("N7 assignments \0",(float)(n7*3)*(float)(xtra),
515
2,e1[2],secs,calibrate,7);
517
/* Section 8, Standard functions */
521
for (ix=0; ix<xtra; ix++)
525
x = sqrt(exp(log(x)/t1));
530
pout("N8 exp,sqrt etc. \0",(float)(n8*4)*(float)(xtra),
531
2,x,secs,calibrate,8);
537
void pa(SPDP e[4], SPDP t, SPDP t2)
542
e[0] = (e[0]+e[1]+e[2]-e[3])*t;
543
e[1] = (e[0]+e[1]-e[2]+e[3])*t;
544
e[2] = (e[0]-e[1]+e[2]+e[3])*t;
545
e[3] = (-e[0]+e[1]+e[2]+e[3])/t2;
551
void po(SPDP e1[4], long j, long k, long l)
559
void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2)
570
void pout(char title[18], float ops, int type, SPDP checknum,
571
SPDP time, int calibrate, int section)
575
Check = Check + checknum;
576
loop_time[section] = time;
577
strcpy (headings[section],title);
578
TimeUsed = TimeUsed + time;
582
results[section] = checknum;
586
printf("%s %24.17f ",headings[section],results[section]);
592
mflops = ops/(1000000L*time);
598
loop_mops[section] = 99999;
599
loop_mflops[section] = mflops;
600
printf(" %9.3f %9.3f\n",
601
loop_mflops[section], loop_time[section]);
607
mops = ops/(1000000L*time);
613
loop_mops[section] = mops;
614
loop_mflops[section] = 0;
615
printf(" %9.3f%9.3f\n",
616
loop_mops[section], loop_time[section]);