/* 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 #else #include #endif #include /* for sin, exp etc. */ #include /* standard I/O */ #include /* for strcpy - 3 occurrences */ #include /* for exit - 1 occurrence */ #include /* #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; ix2) 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; ix0) { 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; }