' ' Document: Whets.bas ' File Group: Classic Benchmarks ' Creation Date: 9 December 1996 ' Revision Date: ' ' Title: Whetstone Benchmark for QBasic ' Keywords: WHETSTONE BENCHMARK PERFORMANCE MIPS ' MWIPS MFLOPS ' ' Abstract: QBasic version of Whetstone one of the ' Classic Numeric Benchmarks with example ' results for PCs. ' ' Contributor: Roy Longbottom 101323.2241@compuserve.com ' or Roy_Longbottom@compuserve.com ' '************************************************************* ' QBasic Whetstone benchmark Single 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 ' PC versions Roy Longbottom 1996 ' '*********************************************************** ' ' The program should run for about 100 seconds on PCs ' (adjustable - variable duration). This time is ' necessary because of the poor 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. ' Print statements referring to QBasic should be changed ' if applicable. ' '*********************************************************** ' ' 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. ' ' This version has facilities for typing in details of the ' particular run. This information is appended to file ' Whets.txt along with the results. ' ' Roy Longbottom 101323.2241@compuserve.com ' '*********************************************************** ' ' Whetstone benchmark results are available in whets.tbl ' from ftp.nosc.mil/pub/aburto. The results include ' further details of the benchmarks. ' '*********************************************************** ' ' 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. ' '*********************************************************** ' Example of Results ' ' Single Precision Whetstone Benchmark QBasic ' ' Month run .. 04/1996 ' PC model .. Escom ' CPU .. Pentium ' Clock MHz .. 100 ' Cache .. 256K ' Options .. Neptune chipset ' OS/DOS .. Win 95 Dos ' Compiler .. Qbasic ' Version .. 1995 ' Run by .. Roy Longbottom ' From .. UK ' Mail .. 101323.2241@compuserve.com ' ' Loop content Result MFLOPS MOPS Seconds ' ' N1 floating point -1.12475025653839100 0.057 1.005 ' N2 floating point -1.12274754047393800 0.058 6.980 ' N3 if then else 1.00000000000000000 0.237 1.309 ' N4 fixed point 12.00000000000000000 0.331 2.852 ' N5 sin,cos etc. 0.49904629588127140 0.014 18.398 ' N6 floating point 0.99999988079071040 0.043 37.523 ' N7 assigns 3.00000000000000000 0.068 8.129 ' N8 exp,sqrt etc. 0.75110864639282230 0.011 9.770 ' ' MWIPS 0.349 85.966 ' ' '*********************************************************************** ' ' Example results QBasic ' ' ' MWIPS MFLOPS MFLOPS MFLOPS COS EXP FIXPT IF EQUAL ' Key 1 2 3 MOPS MOPS MOPS MOPS MOPS ' ' P3 0.064 0.011 0.011 0.008 0.002 0.002 0.051 0.031 0.012 ' P4 0.125 0.020 0.020 0.015 0.005 0.004 0.120 0.100 0.026 ' P5 0.349 0.057 0.058 0.043 0.014 0.011 0.331 0.237 0.068 ' P6 0.310 0.050 0.049 0.037 0.012 0.010 0.367 0.352 0.067 ' ' Note that 200 MHz Pentium Pro is slower than 100 MHz Pentium ' ' Systems ' ' Key System CPU MHz Cache Options OS ' ' P3 Clone AM80386DX 40 128K with 387 Windows 95 ' P4 Escom, 80486DX2 66.7 128K CIS chipset Windows 95 ' P5 Escom, Pentium 100 256K Neptune chipset Windows 95 ' P6 Dell Pro PentPro 200 256K 440FX PCIset NT 3.51 ' '************************************************************************* DEFLNG I, N DEFINT H, J-L DEFSNG A-G, O-Z DIM e(4) DIM results(8) DIM xtime(8) DIM heading$(8) DIM ops(8) DIM flops(8) ON ERROR GOTO Errline OPEN "Whets.txt" FOR APPEND AS #1 CLS icount = 10 calibrate = 1 ixtra = 1 ix100 = 100 duration = 100 ' run time seconds PRINT "Calibrating Whetstone Benchmark" PRINT PRINT "12345678 modules" DO ' calculate loops per second TimeUsed = 0 GOSUB Whetstones PRINT PRINT TimeUsed; " seconds "; ixtra; " Passes (x 100)" calibrate = calibrate + 1 icount = icount - 1 IF TimeUsed > 2 THEN icount = 0 ELSE ixtra = ixtra * 5 END IF LOOP WHILE icount > 0 IF TimeUsed > 0 THEN ixtra = duration * CSNG(ixtra) / TimeUsed END IF IF ixtra < 1 THEN ixtra = 1 PRINT PRINT ixtra; " passes used (x 100)" PRINT calibrate = 0 PRINT PRINT "QBasic Whetstone Benchmark - Single Precision" PRINT PRINT "Loop content"; TAB(28); "Result"; PRINT TAB(46); " MFLOPS MOPS Seconds" PRINT TimeUsed = 0 Check = 0 GOSUB Whetstones IF TimeUsed > 0 THEN wips = CSNG(ixtra * ix100) / (10 * TimeUsed) ELSE wips = 0 END IF PRINT PRINT "MWIPS"; TAB(48); PRINT USING "#####.###"; wips; PRINT TAB(69); PRINT USING "####.###"; TimeUsed PRINT IF Check = 0 THEN PRINT "Wrong answer": PRINT PRINT "Enter datails in the boxes for filing with the results" PRINT #1, "----------------- ----------------------------- "; PRINT #1, "--------- --------- --------- --------- --------- "; PRINT #1, "--------- --------- --------- ---------" PRINT #1, "Single Precision Whetstone Benchmark QBasic" PRINT #1, " " PRINT #1, "Month run .. "; LEFT$(DATE$, 2); "/"; RIGHT$(DATE$, 4) INPUT "PC Supplier/model ? ", a$ PRINT #1, "PC model .. "; a$ INPUT "CPU chip type ? ", a$ PRINT #1, "CPU .. "; a$ INPUT "Clock MHz ? ", a$ PRINT #1, "Clock MHz .. "; a$ INPUT "Cache size ? ", a$ PRINT #1, "Cache .. "; a$ INPUT "Chipset/options ? ", a$ PRINT #1, "Options .. "; a$ INPUT "OS/DOS ? ", a$ PRINT #1, "OS/DOS .. "; a$ PRINT #1, "Compiler .. "; "Qbasic" INPUT "QBasic version ? ", a$ PRINT #1, "Version .. "; a$ INPUT "Your name ? ", a$ PRINT #1, "Run by .. "; a$ INPUT "Where from ? ", a$ PRINT #1, "From .. "; a$ INPUT "E-Mail address ? ", a$ PRINT #1, "Mail .. "; a$ PRINT #1, " " PRINT #1, "Loop content Result "; PRINT #1, " MFLOPS MOPS Seconds" PRINT #1, " " FOR section = 1 TO 8 PRINT #1, heading$(section); TAB(23); PRINT #1, USING "###.#################"; results(section); IF ops(section) = 999999 THEN PRINT #1, TAB(49); PRINT #1, USING "#####.###"; flops(section); ELSE PRINT #1, TAB(59); PRINT #1, USING "#####.###"; ops(section); END IF PRINT #1, TAB(69); PRINT #1, USING "#####.###"; xtime(section) NEXT section PRINT #1, " " PRINT #1, "MWIPS"; TAB(49); PRINT #1, USING "#####.###"; wips; PRINT #1, TAB(69); PRINT #1, USING "#####.###"; TimeUsed PRINT #1, " " PRINT #1, "Results to load to spreadsheet "; PRINT #1, " MWIPS Mflops1 Mflops2 Mflops3 Cosmops "; PRINT #1, " Expmops Fixpmops Ifmops Eqmops" PRINT #1, "Results to load to spreadsheet "; PRINT #1, USING "#####.### "; wips; PRINT #1, USING "#####.### "; flops(1); PRINT #1, USING "#####.### "; flops(2); PRINT #1, USING "#####.### "; flops(6); PRINT #1, USING "#####.### "; ops(5); PRINT #1, USING "#####.### "; ops(8); PRINT #1, USING "#####.### "; ops(4); PRINT #1, USING "#####.### "; ops(3); PRINT #1, USING "#####.### "; ops(7); PRINT #1, " " PRINT #1, " " CLOSE #1 PRINT PRINT "Results are in file Whets.txt" PRINT PRINT "Press any key" DO WHILE INKEY$ = "" LOOP STOP Errline: PRINT "Error unable to open file?" STOP END Whetstones: ' INITIALISE CONSTANTS t = .49999975# t0 = t t1 = .50000025# t2 = 2# n1 = 12 * ix100 n2 = 14 * ix100 n3 = 345 * ix100 n4 = 210 * ix100 n5 = 32 * ix100 n6 = 899 * ix100 n7 = 616 * ix100 n8 = 93 * ix100 n1mult = 10 ' MODULE 1 - ARRAY ELEMENTS stime = TIMER e(1) = 1 e(2) = -1 e(3) = -1 e(4) = -1 FOR ix = 1 TO ixtra FOR i = 1 TO n1 * n1mult e(1) = (e(1) + e(2) + e(3) - e(4)) * t e(2) = (e(1) + e(2) - e(3) + e(4)) * t e(3) = (e(1) - e(2) + e(3) + e(4)) * t e(4) = (-e(1) + e(2) + e(3) + e(4)) * t NEXT i t = 1.0 - t NEXT ix t = t0 checsum = e(4) rtime = (TIMER - stime) / n1mult smflops = n1 * 16 title$ = "N1 floating point" atype = 1 section = 1 GOSUB Pout ' N1 * 16 floating point calculations ' MODULE 2 - ARRAY AS PARAMETER stime = TIMER FOR ix = 1 TO ixtra FOR i = 1 TO n2 GOSUB PA NEXT i t = 1.0 -t NEXT ix t = t0 checsum = e(4) rtime = TIMER - stime smflops = n2 * 96 title$ = "N2 floating point" atype = 1 section = 2 GOSUB Pout ' N2 * 96 floating point calculations ' MODULE 3 - CONDITIONAL JUMPS stime = TIMER j = 1 FOR ix = 1 TO ixtra FOR i = 1 TO n3 IF j <> 1 THEN j = 3 ELSE j = 2 END IF IF j <= 2 THEN j = 1 ELSE j = 0 END IF IF j >= 1 THEN j = 0 ELSE j = 1 END IF NEXT i NEXT ix checsum = j rtime = TIMER - stime smflops = n3 * 3 title$ = "N3 if then else" atype = 2 section = 3 GOSUB Pout ' N3 * 3 IF THEN ELSE ' MODULE 4 - INTEGER ARITHMETIC stime = TIMER j = 1 k = 2 l = 3 FOR ix = 1 TO ixtra FOR i = 1 TO n4 j = j * (k - j) * (l - k) k = l * k - (l - j) * k l = (l - k) * (k + j) e(l - 1) = j + k + l e(k - 1) = j * k * l NEXT i NEXT ix checsum = e(2) + e(1) rtime = TIMER - stime smflops = n4 * 15 title$ = "N4 fixed point" atype = 2 section = 4 GOSUB Pout ' N4 * 15 fixed point operations ' MODULE 5 - TRIG. FUNCTIONS stime = TIMER X = .5 Y = .5 FOR ix = 1 TO ixtra FOR i = 1 TO n5 X = t * ATN(t2 * SIN(X) * COS(X) / (COS(X + Y) + COS(X - Y) - 1)) Y = t * ATN(t2 * SIN(Y) * COS(Y) / (COS(X + Y) + COS(X - Y) - 1)) NEXT i t = 1.0 - t NEXT ix t = t0 checsum = Y rtime = TIMER - stime smflops = n5 * 26 title$ = "N5 sin,cos etc." atype = 2 section = 5 GOSUB Pout ' N5 * 26 function calls and floating point operations ' MODULE 6 - PROCEDURE CALLS stime = TIMER X = 1 Y = 1 Z = 1 FOR ix = 1 TO ixtra FOR i = 1 TO n6 GOSUB P3 NEXT i NEXT ix checsum = Z rtime = TIMER - stime smflops = n6 * 6 title$ = "N6 floating point" atype = 1 section = 6 GOSUB Pout ' N6 * 6 floating point operations ' MODULE 7 - ARRAY REFERENCES stime = TIMER j = 1 k = 2 l = 3 e(1) = 1 e(2) = 2 e(3) = 3 FOR ix = 1 TO ixtra FOR i = 1 TO n7 GOSUB PO NEXT i NEXT ix checsum = e(3) rtime = TIMER - stime smflops = n7 * 3 title$ = "N7 assigns" atype = 2 section = 7 GOSUB Pout ' N7 * 3 assignments ' MODULE 8 - STANDARD FUNCTIONS stime = TIMER X = .75 FOR ix = 1 TO ixtra FOR i = 1 TO n8 X = SQR(EXP(LOG(X) / t1)) NEXT i NEXT ix checsum = X rtime = TIMER - stime smflops = n8 * 4 title$ = "N8 exp,sqrt etc." atype = 2 section = 8 GOSUB Pout ' N8 * 4 function calls and floating point operations RETURN ' END OF MAIN ROUTINE PA: ' PROCEDURE PA j = 0 DO e(1) = (e(1) + e(2) + e(3) - e(4)) * t e(2) = (e(1) + e(2) - e(3) + e(4)) * t e(3) = (e(1) - e(2) + e(3) + e(4)) * t e(4) = (-e(1) + e(2) + e(3) + e(4)) / t2 j = j + 1 LOOP WHILE j < 6 RETURN PO: ' PROCEDURE P0 e(j) = e(k) e(k) = e(l) e(l) = e(j) RETURN P3: ' PROCEDURE P3 X = Y Y = Z X = t * (X + Y) Y = t1 * (X + Y) Z = (X + Y) / t2 RETURN Pout: Check = Check + checsum xtime(section) = rtime heading$(section) = title$ TimeUsed = TimeUsed + rtime IF rtime <= 0! THEN smflops = 0! ELSE smflops = CSNG(ixtra) * smflops / (rtime * 1000000!) END IF IF calibrate = 1 THEN results(section) = checsum PRINT "#"; END IF IF calibrate = 0 THEN PRINT heading$(section); TAB(22); PRINT USING "##.##################"; results(section); IF atype = 1 THEN flops(section) = smflops ops(section) = 999999 PRINT TAB(48); PRINT USING "#####.###"; flops(section); ELSE flops(section) = 0 ops(section) = smflops PRINT TAB(58); PRINT USING "#####.###"; ops(section); END IF PRINT TAB(68); PRINT USING "#####.###"; xtime(section) END IF RETURN