aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-05-07 16:39:32 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-05-07 16:39:32 -0700
commit0cd8926f0f8b7076e2badcb0c6d03f680b677179 (patch)
treed091f7bc3380b4ac61bfec9cac62f8efe49b4c0f
parent06a8c252d94f34a3729aaefe8cb89fbe1a877a57 (diff)
add whets testcase
-rwxr-xr-xtests/runner.py4
-rw-r--r--tests/whets.cpp622
2 files changed, 626 insertions, 0 deletions
diff --git a/tests/runner.py b/tests/runner.py
index 29c8ca7d..773cb157 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -7390,6 +7390,10 @@ extern "C" {
src = open(path_from_root('tests', 'fasta.cpp'), 'r').read()
self.do_run(src, j, [str(i)], lambda x, err: x.replace('\n', '*'), no_build=i>1)
+ def test_whets(self):
+ if not Settings.ASM_JS: return self.skip('mainly a test for asm validation here')
+ self.do_run(open(path_from_root('tests', 'whets.cpp')).read(), 'Single Precision C Whetstone Benchmark')
+
def test_dlmalloc(self):
if self.emcc_args is None: self.emcc_args = [] # dlmalloc auto-inclusion is only done if we use emcc
diff --git a/tests/whets.cpp b/tests/whets.cpp
new file mode 100644
index 00000000..437b292b
--- /dev/null
+++ b/tests/whets.cpp
@@ -0,0 +1,622 @@
+/* gcc whets.c cpuidc64.o cpuida64.o -m64 -lrt -lc -lm -o whet
+*
+* XXX modified by emscripten to be slower, to not slow down test runner
+*
+* Document: Whets.c
+* File Group: Classic Benchmarks
+* Creation Date: 6 November 1996
+* Revision Date: 6 November 2010 Ubuntu Version for PCs
+*
+* Title: Whetstone Benchmark in C/C++
+* Keywords: WHETSTONE BENCHMARK PERFORMANCE MIPS
+* MWIPS MFLOPS
+*
+* Abstract: C or C++ version of Whetstone one of the
+* Classic Numeric Benchmarks with example
+* results on P3 to P6 based PCs.
+*
+* Contributor: roy@roylongbottom.org.uk
+*
+************************************************************
+*
+* C/C++ Whetstone Benchmark Single or Double Precision
+*
+* Original concept Brian Wichmann NPL 1960's
+* Original author Harold Curnow CCTA 1972
+* Self timing versions Roy Longbottom CCTA 1978/87
+* Optimisation control Bangor University 1987/90
+* C/C++ Version Roy Longbottom 1996
+* Compatibility & timers Al Aburto 1996
+*
+************************************************************
+*
+* Official version approved by:
+*
+* Harold Curnow 100421.1615@compuserve.com
+*
+* Happy 25th birthday Whetstone, 21 November 1997
+*
+************************************************************
+*
+* The program normally runs for about 100 seconds
+* (adjustable in main - variable duration). This time
+* is necessary because of poor PC clock resolution.
+* The original concept included such things as a given
+* number of subroutine calls and divides which may be
+* changed by optimisation. For comparison purposes the
+* compiler and level of optimisation should be identified.
+*
+* This version is set to run for 10 seconds using high
+* resolution timer.
+*
+************************************************************
+*
+* The original benchmark had a single variable I which
+* controlled the running time. Constants with values up
+* to 899 were multiplied by I to control the number
+* passes for each loop. It was found that large values
+* of I could overflow index registers so an extra outer
+* loop with a second variable J was added.
+*
+* Self timing versions were produced during the early
+* days. The 1978 changes supplied timings of individual
+* loops and these were used later to produce MFLOPS and
+* MOPS ratings.
+*
+* 1987 changes converted the benchmark to Fortran 77
+* standards and removed redundant IF statements and
+* loops to leave the 8 active loops N1 to N8. Procedure
+* P3 was changed to use global variables to avoid over-
+* optimisation with the first two statements changed from
+* X1=X and Y1=Y to X=Y and Y=Z. A self time calibrating
+* version for PCs was also produced, the facility being
+* incorporated in this version.
+*
+* This version has changes to avoid worse than expected
+* speed ratings, due to underflow, and facilities to show
+* that consistent numeric output is produced with varying
+* optimisation levels or versions in different languages.
+*
+* Some of the procedures produce ever decreasing numbers.
+* To avoid problems, variables T and T1 have been changed
+* from 0.499975 and 0.50025 to 0.49999975 and 0.50000025.
+*
+* Each section now has its own double loop. Inner loops
+* are run 100 times the loop constants. Calibration
+* determines the number of outer loop passes. The
+* numeric results produced in the main output are for
+* one pass on the outer loop. As underflow problems were
+* still likely on a processor 100 times faster than a 100
+* MHz Pentium, three sections have T=1.0-T inserted in the
+* outer loop to avoid the problem. The two loops avoid
+* index register overflows.
+*
+* The first section is run ten times longer than required
+* for accuracy in calculating MFLOPS. This time is divided
+* by ten for inclusion in the MWIPS calculations.
+*
+* Early version has facilities for typing in details of
+* the particular run, appended to file whets.txt along
+* with the results. This version attemps to obtain these
+* automatically.
+*
+* 2010 Section 4 modified slightly to avoid over optimisation
+* by GCC compiler
+*
+* Roy Longbottom roy@roylongbottom.org.uk
+*
+************************************************************
+*
+* Whetstone benchmark results, further details of the
+* benchmarks and history are available from:
+*
+* http://www.roylongbottom.org.uk/whetstone%20results.htm
+* http://www.roylongbottom.org.uk/whetstone.htm
+*
+************************************************************
+*
+* Source code is available in C/C++, Fortran, Basic and
+* Visual Basic in the same format as this version. Pre-
+* compiled versions for PCs are also available via C++.
+* These comprise optimised and non-optimised versions
+* for DOS, Windows and NT. See:
+*
+* http://www.roylongbottom.org.uk/whetstone%20results.htm
+*
+************************************************************
+*
+* Example of initial calibration display (Pentium 100 MHz)
+*
+* Single Precision C/C++ Whetstone Benchmark
+*
+* Calibrate
+* 0.17 Seconds 1 Passes (x 100)
+* 0.77 Seconds 5 Passes (x 100)
+* 3.70 Seconds 25 Passes (x 100)
+*
+* Use 676 passes (x 100)
+*
+* 676 passes are used for an approximate duration of 100
+* seconds, providing an initial estimate of a speed rating
+* of 67.6 MWIPS.
+*
+* This is followed by the table of results as below.
+
+* Whetstone Single Precision Benchmark in C/C++
+*
+* Loop content Result MFLOPS MOPS Seconds
+*
+* N1 floating point -1.12475025653839100 19.971 0.274
+* N2 floating point -1.12274754047393800 11.822 3.240
+* N3 if then else 1.00000000000000000 11.659 2.530
+* N4 fixed point 12.00000000000000000 13.962 6.430
+* N5 sin,cos etc. 0.49904659390449520 2.097 11.310
+* N6 floating point 0.99999988079071040 3.360 45.750
+* N7 assignments 3.00000000000000000 2.415 21.810
+* N8 exp,sqrt etc. 0.75110864639282230 1.206 8.790
+*
+* MWIPS 28.462 100.134
+*
+* Note different numeric results to single precision. Slight variations
+* are normal with different compilers and sometimes optimisation levels.
+*
+**************************************************************************/
+
+#define _CRT_SECURE_NO_WARNINGS 1
+#ifdef WIN32
+#include <Windows.h>
+#else
+#include <sys/time.h>
+#endif
+
+#include <math.h> /* for sin, exp etc. */
+#include <stdio.h> /* standard I/O */
+#include <string.h> /* for strcpy - 3 occurrences */
+#include <stdlib.h> /* for exit - 1 occurrence */
+#include <time.h>
+
+/* #include "cpuidh.h" */
+
+/*PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION*/
+
+/* #define DP */
+
+#ifdef DP
+#define SPDP double
+#define Precision "Double"
+#else
+#define SPDP float
+#define Precision "Single"
+#endif
+
+#define opt "Opt 3 64 Bit"
+
+void whetstones(long xtra, long x100, int calibrate);
+void pa(SPDP e[4], SPDP t, SPDP t2);
+void po(SPDP e1[4], long j, long k, long l);
+void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2);
+void pout(char title[22], float ops, int type, SPDP checknum,
+ SPDP time, int calibrate, int section);
+
+
+static SPDP loop_time[9];
+static SPDP loop_mops[9];
+static SPDP loop_mflops[9];
+static SPDP TimeUsed;
+static SPDP mwips;
+static char headings[9][18];
+static SPDP Check;
+static SPDP results[9];
+
+/* this is truly rank, but it's minimally invasive, and lifted in part from the STREAM scores */
+
+static double secs;
+
+#ifndef WIN32
+
+double mysecond()
+{
+ struct timeval tp;
+ struct timezone tzp;
+ int i;
+
+ i = gettimeofday(&tp,&tzp);
+ return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 );
+}
+#else
+
+double mysecond()
+{
+ static LARGE_INTEGER freq = {0};
+ LARGE_INTEGER count = {0};
+ if(freq.QuadPart == 0LL) {
+ QueryPerformanceFrequency(&freq);
+ }
+ QueryPerformanceCounter(&count);
+ return (double)count.QuadPart / (double)freq.QuadPart;
+}
+
+#endif
+
+void start_time()
+{
+ secs = mysecond();
+}
+
+void end_time()
+{
+ secs = mysecond() - secs;
+}
+
+int main(int argc, char *argv[])
+{
+ int count = 1, calibrate = 1;
+ long xtra = 1;
+ int section;
+ long x100 = 1;
+ int duration = 1;
+ char compiler[80], options[256], general[10][80] = {" "};
+ char endit[80];
+ int i;
+
+ printf("\n");
+ printf("##########################################\n");
+ {
+ time_t t;
+ char timeday[30];
+ t = time(NULL);
+ sprintf(timeday, "%s", asctime(localtime(&t)));
+
+ printf("%s Precision C Whetstone Benchmark %s, %s\n", Precision, opt, timeday);
+ }
+
+ printf("Calibrate\n");
+ do
+ {
+ TimeUsed=0;
+
+ whetstones(xtra,x100,calibrate);
+
+ printf("%11.2f Seconds %10.0lf Passes (x 100)\n",
+ TimeUsed,(SPDP)(xtra));
+ calibrate++;
+ count--;
+
+ if (TimeUsed > 2.0)
+ {
+ count = 0;
+ }
+ else
+ {
+ xtra = xtra * 5;
+ }
+ }
+
+ while (count > 0);
+
+ if (TimeUsed > 0) xtra = (long)((SPDP)(duration * xtra) / TimeUsed);
+ if (xtra < 1) xtra = 1;
+
+ calibrate = 0;
+
+ printf("\nUse %d passes (x 100)\n", (int)xtra);
+
+ printf("\n %s Precision C/C++ Whetstone Benchmark",Precision);
+
+#ifdef PRECOMP
+ printf("\n Compiler %s", precompiler);
+ printf("\n Options %s\n", preoptions);
+#else
+ printf("\n");
+#endif
+
+ printf("\nLoop content Result MFLOPS "
+ " MOPS Seconds\n\n");
+
+ TimeUsed=0;
+ whetstones(xtra,x100,calibrate);
+
+ printf("\nMWIPS ");
+ if (TimeUsed>0)
+ {
+ mwips=(float)(xtra) * (float)(x100) / (10 * TimeUsed);
+ }
+ else
+ {
+ mwips = 0;
+ }
+
+ printf("%39.3f%19.3f\n\n",mwips,TimeUsed);
+
+ if (Check == 0) printf("Wrong answer ");
+
+ printf ("\n");
+ printf ("A new results file, whets.txt, will have been created in the same\n");
+ printf ("directory as the .EXE files, if one did not already exist.\n\n");
+
+ return 0;
+}
+
+void whetstones(long xtra, long x100, int calibrate)
+{
+
+ long n1,n2,n3,n4,n5,n6,n7,n8,i,ix,n1mult;
+ SPDP x,y,z;
+ long j,k,l;
+ SPDP e1[4];
+
+ SPDP t = 0.49999975;
+ SPDP t0 = t;
+ SPDP t1 = 0.50000025;
+ SPDP t2 = 2.0;
+
+ Check=0.0;
+
+ n1 = 1*x100;
+ n2 = 1*x100;
+ n3 = 3*x100;
+ n4 = 2*x100;
+ n5 = 3*x100;
+ n6 = 8*x100;
+ n7 = 6*x100;
+ n8 = 9*x100;
+ n1mult = 1;
+
+ /* Section 1, Array elements */
+
+ e1[0] = 1.0;
+ e1[1] = -1.0;
+ e1[2] = -1.0;
+ e1[3] = -1.0;
+ start_time();
+ {
+ for (ix=0; ix<xtra; ix++)
+ {
+ for(i=0; i<n1*n1mult; i++)
+ {
+ e1[0] = (e1[0] + e1[1] + e1[2] - e1[3]) * t;
+ e1[1] = (e1[0] + e1[1] - e1[2] + e1[3]) * t;
+ e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * t;
+ e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * t;
+ }
+ t = 1.0 - t;
+ }
+ t = t0;
+ }
+ end_time();
+ secs = secs/(SPDP)(n1mult);
+ pout("N1 floating point\0",(float)(n1*16)*(float)(xtra),
+ 1,e1[3],secs,calibrate,1);
+
+ /* Section 2, Array as parameter */
+
+ start_time();
+ {
+ for (ix=0; ix<xtra; ix++)
+ {
+ for(i=0; i<n2; i++)
+ {
+ pa(e1,t,t2);
+ }
+ t = 1.0 - t;
+ }
+ t = t0;
+ }
+ end_time();
+ pout("N2 floating point\0",(float)(n2*96)*(float)(xtra),
+ 1,e1[3],secs,calibrate,2);
+
+ /* Section 3, Conditional jumps */
+ j = 1;
+ start_time();
+ {
+ for (ix=0; ix<xtra; ix++)
+ {
+ for(i=0; i<n3; i++)
+ {
+ if(j==1) j = 2;
+ else j = 3;
+ if(j>2) j = 0;
+ else j = 1;
+ if(j<1) j = 1;
+ else j = 0;
+ }
+ }
+ }
+ end_time();
+ pout("N3 if then else \0",(float)(n3*3)*(float)(xtra),
+ 2,(SPDP)(j),secs,calibrate,3);
+
+ /* Section 4, Integer arithmetic */
+ j = 1;
+ k = 2;
+ l = 3;
+ e1[0] = 0.0;
+ e1[1] = 0.0;
+ start_time();
+ {
+ for (ix=0; ix<xtra; ix++)
+ {
+ for(i=0; i<n4; i++)
+ {
+ j = j *(k-j)*(l-k);
+ k = l * k - (l-j) * k;
+ l = (l-k) * (k+j);
+ e1[l-2] = e1[l-2] + j + k + l;
+ e1[k-2] = e1[k-2] + j * k * l;
+ // was e1[l-2] = j + k + l; and e1[k-2] = j * k * l;
+ }
+ }
+ }
+ end_time();
+ x = (e1[0]+e1[1])/(SPDP)n4/(SPDP)xtra; // was x = e1[0]+e1[1];
+ pout("N4 fixed point \0",(float)(n4*15)*(float)(xtra),
+ 2,x,secs,calibrate,4);
+
+ /* Section 5, Trig functions */
+ x = 0.5;
+ y = 0.5;
+ start_time();
+ {
+ for (ix=0; ix<xtra; ix++)
+ {
+ for(i=1; i<n5; i++)
+ {
+ x = t*atan(t2*sin(x)*cos(x)/(cos(x+y)+cos(x-y)-1.0));
+ y = t*atan(t2*sin(y)*cos(y)/(cos(x+y)+cos(x-y)-1.0));
+ }
+ t = 1.0 - t;
+ }
+ t = t0;
+ }
+ end_time();
+ pout("N5 sin,cos etc. \0",(float)(n5*26)*(float)(xtra),
+ 2,y,secs,calibrate,5);
+
+
+ /* Section 6, Procedure calls */
+ x = 1.0;
+
+ y = 1.0;
+ z = 1.0;
+ start_time();
+ {
+ for (ix=0; ix<xtra; ix++)
+ {
+ for(i=0; i<n6; i++)
+ {
+ p3(&x,&y,&z,t,t1,t2);
+ }
+ }
+ }
+ end_time();
+ pout("N6 floating point\0",(float)(n6*6)*(float)(xtra),
+ 1,z,secs,calibrate,6);
+
+ /* Section 7, Array refrences */
+ j = 0;
+ k = 1;
+ l = 2;
+ e1[0] = 1.0;
+ e1[1] = 2.0;
+ e1[2] = 3.0;
+ start_time();
+ {
+ for (ix=0; ix<xtra; ix++)
+ {
+ for(i=0;i<n7;i++)
+ {
+ po(e1,j,k,l);
+ }
+ }
+ }
+ end_time();
+ pout("N7 assignments \0",(float)(n7*3)*(float)(xtra),
+ 2,e1[2],secs,calibrate,7);
+
+ /* Section 8, Standard functions */
+ x = 0.75;
+ start_time();
+ {
+ for (ix=0; ix<xtra; ix++)
+ {
+ for(i=0; i<n8; i++)
+ {
+ x = sqrt(exp(log(x)/t1));
+ }
+ }
+ }
+ end_time();
+ pout("N8 exp,sqrt etc. \0",(float)(n8*4)*(float)(xtra),
+ 2,x,secs,calibrate,8);
+
+ return;
+}
+
+
+void pa(SPDP e[4], SPDP t, SPDP t2)
+{
+ long j;
+ for(j=0;j<6;j++)
+ {
+ e[0] = (e[0]+e[1]+e[2]-e[3])*t;
+ e[1] = (e[0]+e[1]-e[2]+e[3])*t;
+ e[2] = (e[0]-e[1]+e[2]+e[3])*t;
+ e[3] = (-e[0]+e[1]+e[2]+e[3])/t2;
+ }
+
+ return;
+}
+
+void po(SPDP e1[4], long j, long k, long l)
+{
+ e1[j] = e1[k];
+ e1[k] = e1[l];
+ e1[l] = e1[j];
+ return;
+}
+
+void p3(SPDP *x, SPDP *y, SPDP *z, SPDP t, SPDP t1, SPDP t2)
+{
+ *x = *y;
+ *y = *z;
+ *x = t * (*x + *y);
+ *y = t1 * (*x + *y);
+ *z = (*x + *y)/t2;
+ return;
+}
+
+
+void pout(char title[18], float ops, int type, SPDP checknum,
+ SPDP time, int calibrate, int section)
+{
+ SPDP mops,mflops;
+
+ Check = Check + checknum;
+ loop_time[section] = time;
+ strcpy (headings[section],title);
+ TimeUsed = TimeUsed + time;
+ if (calibrate == 1)
+
+ {
+ results[section] = checknum;
+ }
+ if (calibrate == 0)
+ {
+ printf("%s %24.17f ",headings[section],results[section]);
+
+ if (type == 1)
+ {
+ if (time>0)
+ {
+ mflops = ops/(1000000L*time);
+ }
+ else
+ {
+ mflops = 0;
+ }
+ loop_mops[section] = 99999;
+ loop_mflops[section] = mflops;
+ printf(" %9.3f %9.3f\n",
+ loop_mflops[section], loop_time[section]);
+ }
+ else
+ {
+ if (time>0)
+ {
+ mops = ops/(1000000L*time);
+ }
+ else
+ {
+ mops = 0;
+ }
+ loop_mops[section] = mops;
+ loop_mflops[section] = 0;
+ printf(" %9.3f%9.3f\n",
+ loop_mops[section], loop_time[section]);
+ }
+ }
+
+ return;
+}
+