mirror of https://github.com/BOINC/boinc.git
476 lines
15 KiB
C
476 lines
15 KiB
C
/*
|
|
* "DHRYSTONE" Benchmark Program for PCs
|
|
*
|
|
* Version: C/1.1,
|
|
*
|
|
* Date: PROGRAM updated 02 Feb 95, RESULTS updated 03/31/86
|
|
*
|
|
* Author: Reinhold P. Weicker, CACM Vol27, No10,10/84 pg.1013
|
|
* Translated from ADA by Rick Richardson.
|
|
* Translated from C to ANSI C by James Day.
|
|
*
|
|
**************************************************************************
|
|
*
|
|
* This version by Roy Longbottom
|
|
101323.2241@compuserve.com
|
|
April 1996
|
|
*
|
|
* A number of enhancements have been included to conform to a format
|
|
* used for a number of standard benchmarks:
|
|
*
|
|
* 1. Function prototypes are declared and function headers have
|
|
* embedded parameter types to produce code for C and C++
|
|
*
|
|
* 2. Timing function include (compiler dependent).
|
|
*
|
|
* 3. Additional date function included (compiler dependent).
|
|
*
|
|
* 4. Automatic run time calibration rather than fixed parameters
|
|
*
|
|
* 5. Initial calibration with time display to show linearity
|
|
*
|
|
* 6. Facilities included for typing in details of system used etc.
|
|
* The input section can be avoided using a command line
|
|
* parameter N (for example dhry1nd.exe N).
|
|
*
|
|
* 7. Compiler details in code in case .exe files used elsewhere
|
|
*
|
|
* 8. Results appended to a text file (Dhry.txt)
|
|
*
|
|
* Other changes:
|
|
|
|
* Proc1 statement Proc3(NextRecord.PtrComp) changed to
|
|
* Proc3(&NextRecord.PtrComp) as in Dhrystone 2.1 in order to compile.
|
|
*
|
|
* Loops and loop variable i are both unsigned long to work with 16
|
|
* bit compilers. The only check that the program has executed properly
|
|
* is the display of loops executed + 10 (Array2Glob8/7). With a 16 bit
|
|
* compiler this should still indicate OK but the number will appear
|
|
* to be incorrect as it is derived from overflowing 16 bit integers
|
|
* and might have a negative value.
|
|
*
|
|
**************************************************************************
|
|
*
|
|
* Timing
|
|
*
|
|
* The PC timer is updated at about 18 times per second or resolution of
|
|
* 0.05 to 0.06 seconds. Running time is arranged to be greater than five
|
|
* seconds.
|
|
*
|
|
**************************************************************************
|
|
*
|
|
* Example of Output
|
|
*
|
|
* Dhrystone Benchmark, Version 1.1 (Language: C)
|
|
*
|
|
* Compiler Watcom C/ C++ 10.5 Win386
|
|
* Optimisation -otexan -zp8 -5r
|
|
*
|
|
* 10000 runs 0.00 seconds
|
|
* 100000 runs 0.38 seconds
|
|
* 200000 runs 0.66 seconds
|
|
* 400000 runs 1.43 seconds
|
|
* 800000 runs 2.80 seconds
|
|
* 1600000 runs 5.55 seconds
|
|
*
|
|
* Array2Glob8/7: O.K. 1600010
|
|
*
|
|
* Microseconds for one run through Dhrystone: 3.47
|
|
* Dhrystones per Second: 288288
|
|
* VAX MIPS rating = 164.08
|
|
*
|
|
* Enter the following data which will be filed with the results
|
|
*
|
|
* Month run 9/1996 #
|
|
* PC model Escom
|
|
* CPU Pentium
|
|
* Clock MHz 100
|
|
* Cache 256K
|
|
* Options Neptune chipset
|
|
* OS/DOS Windows 95
|
|
* Compiler Watcom C/C++ 10.5 Win 386 #
|
|
* OptLevel -otexan -zp8 -5r #
|
|
* Run by Roy Longbottom
|
|
* From UK
|
|
* Mail 101323.2241@compuserve.com
|
|
*
|
|
* Included by program #
|
|
*
|
|
* The speed and running details are appended to file Dhry.txt
|
|
*
|
|
************************************************************************
|
|
*
|
|
* Examples of Results
|
|
*
|
|
* Pre-compiled 32 bit codes were produced via a Watcom C/C++ 10.5
|
|
* compiler. Versions are available for DOS, Windows 3/95 and NT/Win95.
|
|
* Both non-optimised and optimised programs are available. The latter
|
|
* has options as in the above example. These include the -otexan default
|
|
* options which can place functions in-line and carry out loop
|
|
* optimisation. These are not supposed to be used with this benchmark
|
|
* but it seems that some published results ignore this directive.
|
|
*
|
|
* Results produced are not necessarily consistent between runs. Besides
|
|
* occasional interference from Windows, the timing seems to be dependent
|
|
* on where the code or data is placed in memory. Representative good
|
|
* results are:
|
|
*
|
|
* 32 Bit Operation
|
|
*
|
|
* Opt No Opt Version/
|
|
* MHz Cache VaxMips VaxMips Make/Options Via
|
|
*
|
|
* AM80386DX 40 128K 17.4 4.5 Clone Win/W95
|
|
* 80486DX2 66 128K 42.3 12.6 Escom SIS chipset Win/W95
|
|
* 80486DX2 66 128K 41.5 13.3 Escom SIS chipset NT/W95
|
|
* 80486DX2 66 128K 46.3 12.9 Escom SIS chipset Dos/Dos
|
|
* Pentium 100 256K 164.1 27.0 Escom Neptune chipset Win/W95
|
|
* Pentium 100 256K 157.8 29.7 Escom Neptune chipset NT/W95
|
|
* Pentium 100 256K 176.5 28.1 Escom Neptune chipset Dos/Dos
|
|
* Pentium Pro 200 256K 372.8 92.4 Dell XPS Pro200n NT/NT
|
|
*
|
|
* The results are as produced when compiled as Dhry1.c. Compiling as
|
|
* Dhry1.cpp gives similar speeds but the code is slightly different. Other
|
|
* results were produced for the above 486 and Pentium via a Watcom Windows
|
|
* 16 bit system and Borland Light development system with no optimising
|
|
* options:
|
|
*
|
|
* 16 Bit Operation
|
|
*
|
|
* Watcom Opt Watcom No Opt Borland
|
|
* VaxMips VaxMips VaxMips
|
|
*
|
|
* 80486DX2 66 38.8 13.7 14.5
|
|
* Pentium 100 91.5 41.7 44.5
|
|
*
|
|
***************************************************************************
|
|
*
|
|
*/
|
|
|
|
// Slightly modified for BOINC
|
|
|
|
#ifdef _WIN32
|
|
#include "stdafx.h"
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "util.h"
|
|
#include "cpu_benchmark.h"
|
|
|
|
#define structassign(d, s) d = s
|
|
|
|
typedef enum {Ident1, Ident2, Ident3, Ident4, Ident5} Enumeration;
|
|
|
|
typedef int OneToThirty;
|
|
typedef int OneToFifty;
|
|
typedef char CapitalLetter;
|
|
typedef char String30[31];
|
|
typedef int Array1Dim[51];
|
|
typedef int Array2Dim[51][51];
|
|
|
|
struct Record
|
|
{
|
|
struct Record *PtrComp;
|
|
Enumeration Discr;
|
|
Enumeration EnumComp;
|
|
OneToFifty IntComp;
|
|
String30 StringComp;
|
|
};
|
|
|
|
typedef struct Record RecordType;
|
|
typedef RecordType * RecordPtr;
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
|
|
void Proc0();
|
|
void Proc1(RecordPtr PtrParIn);
|
|
void Proc2(OneToFifty *IntParIO);
|
|
void Proc3(RecordPtr *PtrParOut);
|
|
void Proc4();
|
|
void Proc5();
|
|
void Proc6(Enumeration EnumParIn, Enumeration *EnumParOut);
|
|
void Proc7(OneToFifty IntParI1, OneToFifty IntParI2, OneToFifty *IntParOut);
|
|
void Proc8(Array1Dim Array1Par, Array2Dim Array2Par, OneToFifty IntParI1,
|
|
OneToFifty IntParI2);
|
|
extern Enumeration Func1(CapitalLetter CharPar1, CapitalLetter CharPar2);
|
|
extern bool Func2(String30 StrParI1, String30 StrParI2);
|
|
bool Func3(Enumeration EnumParIn);
|
|
|
|
|
|
/*
|
|
* Package 1
|
|
*/
|
|
int IntGlob;
|
|
bool BoolGlob;
|
|
char Char1Glob;
|
|
char Char2Glob;
|
|
Array1Dim Array1Glob;
|
|
Array2Dim Array2Glob;
|
|
RecordPtr PtrGlb;
|
|
RecordPtr PtrGlbNext;
|
|
int getinput = 1;
|
|
|
|
|
|
void dhrystone(
|
|
double& Dhrystones_Per_Second, double& Vax_Mips
|
|
){
|
|
OneToFifty IntLoc1;
|
|
OneToFifty IntLoc2;
|
|
OneToFifty IntLoc3;
|
|
char CharIndex;
|
|
Enumeration EnumLoc;
|
|
String30 String1Loc;
|
|
String30 String2Loc;
|
|
unsigned long Loops;
|
|
|
|
double startclock;
|
|
double benchtime;
|
|
|
|
register unsigned long i;
|
|
|
|
|
|
/***********************************************************************
|
|
* Change for compiler and optimisation used *
|
|
***********************************************************************/
|
|
|
|
PtrGlbNext = (RecordPtr) malloc(sizeof(RecordType));
|
|
PtrGlb = (RecordPtr) malloc(sizeof(RecordType));
|
|
PtrGlb->PtrComp = PtrGlbNext;
|
|
PtrGlb->Discr = Ident1;
|
|
PtrGlb->EnumComp = Ident3;
|
|
PtrGlb->IntComp = 40;
|
|
strcpy(PtrGlb->StringComp, "DHRYSTONE PROGRAM, SOME STRING");
|
|
strcpy(String1Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
|
|
|
|
//printf ("Dhrystone Benchmark, Version 1.1 (Language: C or C++)\n");
|
|
|
|
Loops = 160000; // determines runtime
|
|
|
|
Array2Glob[8][7] = 10;
|
|
|
|
benchmark_wait_to_start(BM_TYPE_INT);
|
|
|
|
/*****************
|
|
-- Start Timer --
|
|
*****************/
|
|
|
|
startclock = dtime();
|
|
int bigloops = 0;
|
|
|
|
do
|
|
{
|
|
for (i = 0; i < Loops; ++i)
|
|
{
|
|
Proc5();
|
|
Proc4();
|
|
IntLoc1 = 2;
|
|
IntLoc2 = 3;
|
|
strcpy(String2Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
|
|
EnumLoc = Ident2;
|
|
BoolGlob = ! Func2(String1Loc, String2Loc);
|
|
while (IntLoc1 < IntLoc2)
|
|
{
|
|
IntLoc3 = 5 * IntLoc1 - IntLoc2;
|
|
Proc7(IntLoc1, IntLoc2, &IntLoc3);
|
|
++IntLoc1;
|
|
}
|
|
Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3);
|
|
Proc1(PtrGlb);
|
|
for (CharIndex = 'A'; CharIndex <= Char2Glob; ++CharIndex)
|
|
if (EnumLoc == Func1(CharIndex, 'C'))
|
|
Proc6(Ident1, &EnumLoc);
|
|
IntLoc3 = IntLoc2 * IntLoc1;
|
|
IntLoc2 = IntLoc3 / IntLoc1;
|
|
IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1;
|
|
Proc2(&IntLoc1);
|
|
}
|
|
bigloops++;
|
|
}
|
|
while (!benchmark_time_to_stop(BM_TYPE_INT));
|
|
|
|
Loops *= bigloops;
|
|
|
|
/*****************
|
|
-- Stop Timer --
|
|
*****************/
|
|
|
|
benchtime = dtime() - startclock;
|
|
|
|
//printf ("%12.0f runs %6.2f seconds \n",(double) Loops, benchtime);
|
|
|
|
Dhrystones_Per_Second = (double) Loops / benchtime;
|
|
Vax_Mips = Dhrystones_Per_Second / 1757.0;
|
|
#if 0
|
|
printf ("Dhrystones per Second: ");
|
|
printf ("%10.0lf \n", Dhrystones_Per_Second);
|
|
printf ("VAX MIPS rating = ");
|
|
printf ("%12.2lf \n",Vax_Mips);
|
|
#endif
|
|
}
|
|
|
|
void Proc1(RecordPtr PtrParIn)
|
|
{
|
|
#define NextRecord (*(PtrParIn->PtrComp))
|
|
|
|
structassign(NextRecord, *PtrGlb);
|
|
PtrParIn->IntComp = 5;
|
|
NextRecord.IntComp = PtrParIn->IntComp;
|
|
NextRecord.PtrComp = PtrParIn->PtrComp;
|
|
Proc3(&NextRecord.PtrComp);
|
|
if (NextRecord.Discr == Ident1)
|
|
{
|
|
NextRecord.IntComp = 6;
|
|
Proc6(PtrParIn->EnumComp, &NextRecord.EnumComp);
|
|
NextRecord.PtrComp = PtrGlb->PtrComp;
|
|
Proc7(NextRecord.IntComp, 10, &NextRecord.IntComp);
|
|
}
|
|
else
|
|
structassign(*PtrParIn, NextRecord);
|
|
|
|
#undef NextRecord
|
|
}
|
|
|
|
void Proc2(OneToFifty *IntParIO)
|
|
{
|
|
OneToFifty IntLoc;
|
|
Enumeration EnumLoc;
|
|
|
|
IntLoc = *IntParIO + 10;
|
|
for(;;)
|
|
{
|
|
if (Char1Glob == 'A')
|
|
{
|
|
--IntLoc;
|
|
*IntParIO = IntLoc - IntGlob;
|
|
EnumLoc = Ident1;
|
|
}
|
|
if (EnumLoc == Ident1)
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Proc3(RecordPtr *PtrParOut)
|
|
{
|
|
if (PtrGlb != NULL)
|
|
*PtrParOut = PtrGlb->PtrComp;
|
|
else
|
|
IntGlob = 100;
|
|
Proc7(10, IntGlob, &PtrGlb->IntComp);
|
|
}
|
|
|
|
void Proc4()
|
|
{
|
|
bool BoolLoc;
|
|
|
|
BoolLoc = Char1Glob == 'A';
|
|
BoolLoc |= BoolGlob;
|
|
Char2Glob = 'B';
|
|
}
|
|
|
|
void Proc5()
|
|
{
|
|
Char1Glob = 'A';
|
|
BoolGlob = FALSE;
|
|
}
|
|
|
|
extern bool Func3();
|
|
|
|
void Proc6(Enumeration EnumParIn, Enumeration *EnumParOut)
|
|
{
|
|
*EnumParOut = EnumParIn;
|
|
if (! Func3(EnumParIn) )
|
|
*EnumParOut = Ident4;
|
|
switch (EnumParIn)
|
|
{
|
|
case Ident1: *EnumParOut = Ident1; break;
|
|
case Ident2: if (IntGlob > 100) *EnumParOut = Ident1;
|
|
else *EnumParOut = Ident4;
|
|
break;
|
|
case Ident3: *EnumParOut = Ident2; break;
|
|
case Ident4: break;
|
|
case Ident5: *EnumParOut = Ident3;
|
|
}
|
|
}
|
|
|
|
void Proc7(OneToFifty IntParI1, OneToFifty IntParI2, OneToFifty *IntParOut)
|
|
{
|
|
OneToFifty IntLoc;
|
|
|
|
IntLoc = IntParI1 + 2;
|
|
*IntParOut = IntParI2 + IntLoc;
|
|
}
|
|
|
|
void Proc8(Array1Dim Array1Par, Array2Dim Array2Par, OneToFifty IntParI1,
|
|
OneToFifty IntParI2)
|
|
{
|
|
OneToFifty IntLoc;
|
|
OneToFifty IntIndex;
|
|
|
|
IntLoc = IntParI1 + 5;
|
|
Array1Par[IntLoc] = IntParI2;
|
|
Array1Par[IntLoc+1] = Array1Par[IntLoc];
|
|
Array1Par[IntLoc+30] = IntLoc;
|
|
for (IntIndex = IntLoc; IntIndex <= (IntLoc+1); ++IntIndex)
|
|
Array2Par[IntLoc][IntIndex] = IntLoc;
|
|
++Array2Par[IntLoc][IntLoc-1];
|
|
Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc];
|
|
IntGlob = 5;
|
|
}
|
|
|
|
Enumeration Func1(CapitalLetter CharPar1, CapitalLetter CharPar2)
|
|
{
|
|
CapitalLetter CharLoc1;
|
|
CapitalLetter CharLoc2;
|
|
|
|
CharLoc1 = CharPar1;
|
|
CharLoc2 = CharLoc1;
|
|
if (CharLoc2 != CharPar2)
|
|
return (Ident1);
|
|
else
|
|
return (Ident2);
|
|
}
|
|
|
|
bool Func2(String30 StrParI1, String30 StrParI2)
|
|
{
|
|
OneToThirty IntLoc;
|
|
CapitalLetter CharLoc;
|
|
|
|
IntLoc = 1;
|
|
while (IntLoc <= 1)
|
|
if (Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1)
|
|
{
|
|
CharLoc = 'A';
|
|
++IntLoc;
|
|
}
|
|
if (CharLoc >= 'W' && CharLoc <= 'Z')
|
|
IntLoc = 7;
|
|
if (CharLoc == 'X')
|
|
return(TRUE);
|
|
else
|
|
{
|
|
if (strcmp(StrParI1, StrParI2) > 0)
|
|
{
|
|
IntLoc += 7;
|
|
return (TRUE);
|
|
}
|
|
else
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
bool Func3(Enumeration EnumParIn)
|
|
{
|
|
Enumeration EnumLoc;
|
|
|
|
EnumLoc = EnumParIn;
|
|
if (EnumLoc == Ident3) return (TRUE);
|
|
return (FALSE);
|
|
}
|
|
|
|
|