diff options
-rwxr-xr-x | tests/runner.py | 4 | ||||
-rw-r--r-- | tests/whets.cpp | 622 |
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; +} + |