Document:         memspeed.txt
File Group:       Classic Benchmarks
Creation Date:    15 May 1997
Revision Date:

Title:            Memory Data Transfer Rate Tests
Keywords:         BENCHMARK PERFORMANCE MEMORY CACHE  

Abstract:         This document contains details of pre-compiled C
                  programs that measure memory and cache data transfer
                  rates. Windows 95/NT, OS/2 and DOS versions are supplied.
                  The main purpose is to identify performance
                  peculiarities when running the Classic Benchmarks. Some
                  Operating System overheads are also identified. 

Note:             The programs are still under test and should be treated
                  as beta test software.  Please submit feedback directly
                  directly to Roy, or as a posting in Section 12.

                  The programs have been tested on various PCs including
                  486, Pentium and Pentium Pro systems. They have also
                  been run via Windows 95 and  NT 4.0. The DOS versions
                  have also been run directly in the associated DOS mode
                  and when booted as DOS only with MS DOS 6.2.

                  The programs use greater than 6 megabytes of memory.

 Contributor:     Roy_Longbottom@compuserve.com



MEMORY DATA TRANSFER RATE TESTS

0.  SUMMARY

The program employs three different sequences of operations, on 64 bit 
double precision floating point numbers, 32 bit single precision numbers 
and 32 bit integers via data arrays. The memory loading speed is calculated 
in terms of millions of bytes per second. Ten sets of measurements are made 
using between 4000 and 2048000 memory bytes to produce speed ratings via 
data from different levels of cache and from RAM. Running time is normally 
about ten minutes to produce 90 results.

Pre-compiled versions MDTRNT95.EXE, MDTROS2.EXE and MDTRDOS.EXE are 
provided for Windows 95 or NT, OS/2 and MS DOS. Windows 3.1 users can run 
the DOS version. Results are displayed as the program is running and saved 
in file XFERMBPS.TXT which should appear in the same directory as the EXE 
files. The DOS version requires DOS4GW.EXE the protected run-time program.

Before running, all other applications should be closed. To run, click on 
the appropriate EXE icon or enter the program name at the command prompt. 
The most consistent speed measurements are likely to be produced when the 
PC is booted directly with DOS.

Results should be sent to Roy_Longbottom@compuserve.com and details of the 
system under test should be included. The configuration details can be 
provided via program SYSTEMxx.EXE as supplied with the Classic Benchmarks. 


1.  INTRODUCTION

On examining results from the Classic Benchmarks, performance comparisons 
between various PCs are sometimes different to those obtained by other 
standard benchmarks that measure CPU speeds. The memory data transfer rate 
test has been produced to help to identify reasons for the differences.

The program measures performance in terms of millions of bytes per second 
(not megabytes per second where mega is usually defined as 1024 * 1024) of 
increasing memory block sizes from defined arrays. The concept is based on 
the wonderful CACHECHK program. However, using a high level language, there 
is no control on absolute memory addressing. Also, with an optimising 
compiler, it is not normally possible to make measurements where only 
memory reading is carried out - if results are not used outside the timing 
loop the compiler will probably not include the code. For example, on 
finding a loop with a = x[loop_variable], the compiler is likely to ignore 
all the assignments except the last one.

The measurements made are for 64 bit double precision floating point 
numbers, 32 bit single precision and 32 bit integers with the following 
assignments and calculations in inner timing loops:

               sum  = sum  + x[m] * y[m] (+y[m] integers as faster)
               x[m] = x[m] + y[m]
               x[m] = y[m]

Pre-compiled versions, via Watcom C/C++ 10.5, MDTRNT95.EXE, MDTROS2.EXE and 
MDTRDOS.EXE are available for Windows 95 or NT, OS/2 and MS DOS. Windows 
3.1 users can run the DOS version. The DOS version requires DOS/4GW the 
protected run-time program - Copyright (c) Rational Systems Inc.


2.  PROGRAM DETAILS

The program declares the following arrays. With double precision numbers 
being eight bytes and the others four, memory used is approximately 6 * 
256000 * 4 or 6,144,000 bytes.

With the Watcom compiler, the arrays are inserted in the stack at the end 
of the data segment and aligned on 16 byte boundaries. 

main()
  {
      double xd[128008];    
      double yd[128008];
      float  xs[256008];
      float  ys[256008];
      long   xi[256008];   
      long   yi[256008];

Nine separate measurements of millions of bytes per second are made using 
ten parameters (loop variable m maximum) of 250, 500, 1000, 2000, 4000, 
8000, 16000, 32000, 64000 and 128000. Each measurement uses two arrays, so 
double precision tests occupy 4000, 8000, 16000, 32000, 64000, 128000, 
256000, 512000, 1024000 and 2048000 bytes. The maximum value of m is 
doubled for single precision and integer measurements to use the same 
memory capacity. The sizes chosen are such that slightly less than a given 
sized cache will be occupied.

Each measurement is self calibrating, via an outer loop, to run for 
approximately 5 seconds on Pentium CPUs or faster. This is to produce a 
timing resolution within 1% using the standard PC timer. Some measurements 
can take greater than 10 seconds on 80486DX2/66 based PCs. With 90 
measurements, calibration and other overheads, total running time is about 
10 to 11 minutes on any 80486DX2/66 system or faster.  

Each timing loop is partially unrolled with a loop increment of four and 
four sequential statements. This is to reduce looping overheads and 
maximise memory transfers.

The data transfer rates calculated are based on the data read. The last six 
measurements also write to memory.


3.1  ARRAY AND ARITHMETIC TO VARIABLE

The double and single precision tests carry out the following calculations 
(using the appropriate arrays). The multiply and add produces a 
significantly higher data throughput than two adds. The integer test is of 
the form sumi = sumi + xi[m+] + yi[m+] as multiplication produces lower 
throughput with integers. 

for (m=0; m<kd; m=m+4)
  {
      sumd = sumd + xd[m]   * yd[m];
      sumd = sumd + xd[m+1] * yd[m+1];
      sumd = sumd + xd[m+2] * yd[m+2];
      sumd = sumd + xd[m+3] * yd[m+3];
  }


3.1.1  DOUBLE PRECISION INSTRUCTIONS

The compiler produces the following code for the first double precision 
test. The loop with 18 instructions executes 8 floating point arithmetic 
operations per 64 bytes used for computing the MB per second transfer rate 
so:

  Millions of Instructions per second    (MIPS)   = MB per sec * 18/64
  Millions of Floating Point Ops Per Sec (MFLOPS) = MB per sec *  8/64

An explanation of some of the instructions is given later.

                                            sumd is in register R7	
L9	fld     qword ptr +0fa040H[esp+eax]   load x[m] to register R6
	fmul    qword ptr [esp+eax]           multiply by y[m]
	fld     qword ptr +0fa048H[esp+eax]   x[m+1]*y[m+1] to register R5
	fmul    qword ptr +8H[esp+eax]
	fld     qword ptr +0fa050H[esp+eax]   x[m+2]*y[m+2] to register R4
	fmul    qword ptr +10H[esp+eax]
	fld     qword ptr +0fa058H[esp+eax]   x[m+3]*y[m+3] to register R3
	fmul    qword ptr +18H[esp+eax]
	add     eax,00000020H                 increment loop counter 32 bytes
	fxch    st(3)                         R3<xy[m] R6<xy[m+3]
	faddp   st(4),st                      sumd R7=R7+R3
	fxch    st(1)                         R4<xy[m+2] r5<xy[m+3]
	faddp   st(3),st                      sumd R7=R7+R4
	faddp   st(2),st                      sumd R7=R7+R5
	faddp   st(1),st                      sumd R7=R7+R6
	cmp     eax,edx                       compare loop counter
	jge     L10                           jump out
	jmp     L9                               or repeat loop


3.1.2   SINGLE PRECISION INSTRUCTIONS

This is similar to the above but uses 4 byte double words with 16 
instructions per 32 bytes.

      MIPS   = MB per sec * 16/32
      MFLOPS = MB per sec *  8/32
                                            sums is in register R7  
L19	fld     dword ptr +4e20e4H[esp+edx*4] x[m+1]*y[m+1] to R6
	fmul    dword ptr +2ee0a4H[esp+edx*4]
	fld     dword ptr +4e20e8H[esp+edx*4] x[m+2]*y[m+2] to R5
	fmul    dword ptr +2ee0a8H[esp+edx*4]
	fld     dword ptr +4e20ecH[esp+edx*4] x[m+3]*y[m+3] to R4
	fmul    dword ptr +2ee0acH[esp+edx*4]
	fld     dword ptr +4e20e0H[esp+edx*4] x[m]*y[m] to R3
	fmul    dword ptr +2ee0a0H[esp+edx*4]
	add     edx,ebx                       increment loop counter
	faddp   st(4),st                      sums R7=R7+R3
	fxch    st(2)                         R6<xy[m+3] R4<xy[m=1]
	faddp   st(3),st                      sums R7=R7+R4
	faddp   st(2),st                      sums R7=R7+R5
	faddp   st(1),st                      sums R7=R7+R6
	cmp     edx,edi                       compare loop counter
	jl      L19                           repeat loop


3.1.3  INTEGER INSTRUCTIONS

This tests carries out 8 integer adds (OPS) to register edx, each 4 bytes 
long and uses 11 instructions. 
      
      MIPS = MB per sec * 11/32
      MOPS = MB per sec *  8/32

for (m=0; m<ki; m=m+4)
  {
      sumi = sumi + xi[m]   + yi[m];
      sumi = sumi + xi[m+1] + yi[m+1];
      sumi = sumi + xi[m+2] + yi[m+2];
      sumi = sumi + xi[m+3] + yi[m+3];
  }


L29	add     edx,+1f4080H[esp+ecx*4]  add xi[m] to edx
	add     edx,+3e80c0H[esp+ecx*4]  add yi[m] to edx
	add     edx,+1f4084H[esp+ecx*4]  repeat xi[m+1]
	add     edx,+3e80c4H[esp+ecx*4]         yi[m+1]
	add     edx,+1f4088H[esp+ecx*4]         xi[m+2]
	add     edx,+3e80c8H[esp+ecx*4]         yi[m+2]
	add     edx,+1f408cH[esp+ecx*4]         xi[m+3]
	add     edx,+3e80ccH[esp+ecx*4]         yi[m+3]
	add     ecx,ebx                  loop control
	cmp     ecx,+5dc26cH[esp]
	jl      L29
	

3.2  ARRAY PLUS ARRAY TO ARRAY

In this case, all three sections carry out the same operations with the 
appropriate data type.

for (m=0; m<kd; m=m+4)
  {
      xd[m]   = xd[m]   + yd[m];
      xd[m+1] = xd[m+1] + yd[m+1];
      xd[m+2] = xd[m+2] + yd[m+2];
      xd[m+3] = xd[m+3] + yd[m+3];
  }


3.2.1  DOUBLE PRECISION INSTRUCTIONS

This time 21 instructions are used to execute four floating point 
arithmetic operations on 64 bytes.

      MIPS   = MB per sec * 21/64
      MFLOPS = MB per sec *  4/64

L37	fld     qword ptr +0fa040H[esp+edx*8]  load x[m] to register R7
	fld     qword ptr +0fa048H[esp+edx*8]  load x[m+1] to R6  
	fld     qword ptr +0fa050H[esp+edx*8]  load x[m+2] to R5
	fld     qword ptr +0fa058H[esp+edx*8]  load x[m+3] to R4
	fxch    st(3)                          R4<x[m] R7<x[m+3]
	fadd    qword ptr [esp+edx*8]          R4=R4+y[m]
	fxch    st(2)                          R4<x[m+1] R6<x+y[m]
	fadd    qword ptr +8H[esp+edx*8]       R4=R4+y[m+1]
	fxch    st(1)                          R4<x[m+2] R5<x+y[m+1]
	fadd    qword ptr +10H[esp+edx*8]      R4=R4+y[m+2]
	fxch    st(3)                          R4<x[m+3] R7<x+y[m+2]
	fadd    qword ptr +18H[esp+edx*8]      R4=R4+y[m+3]
	fxch    st(2)                          R4<x+y[m] R6<x+y[m+3]
	fstp    qword ptr +0fa040H[esp+edx*8]  store x[m] R4
	fstp    qword ptr +0fa048H[esp+edx*8]  store x[m+1] R5
	fxch    st(1)                          R6<x+y[m+2] R7<x+y[m+3]
	fstp    qword ptr +0fa050H[esp+edx*8]  store x[m+2] R6
	fstp    qword ptr +0fa058H[esp+edx*8]  store x[m+3] R7
	add     edx,ebx                        loop control
	cmp     edx,eax
	jl      L37


3.2.2   SNGLE PRECISION INSTRUCTIONS

As double precision but 8 * 4 bytes.

      MIPS   = MB per sec * 21/32
      MFLOPS = MB per sec *  4/32

L46	fld     dword ptr +4e20e0H[esp+edx*4]
	fld     dword ptr +4e20e4H[esp+edx*4]
	fld     dword ptr +4e20e8H[esp+edx*4]
	fld     dword ptr +4e20ecH[esp+edx*4]
	fxch    st(3)
	fadd    dword ptr +2ee0a0H[esp+edx*4]
	fxch    st(2)
	fadd    dword ptr +2ee0a4H[esp+edx*4]
	fxch    st(1)
	fadd    dword ptr +2ee0a8H[esp+edx*4]
	fxch    st(3)
	fadd    dword ptr +2ee0acH[esp+edx*4]
	fxch    st(2)
	fstp    dword ptr +4e20e0H[esp+edx*4]
	fstp    dword ptr +4e20e4H[esp+edx*4]
	fxch    st(1)
	fstp    dword ptr +4e20e8H[esp+edx*4]
	fstp    dword ptr +4e20ecH[esp+edx*4]
	add     edx,ebx
	cmp     edx,edi
	jl      L46


3.2.3  INTEGER INSTRUCTIONS

This uses 14 instructions for 4 operations on 4 * 8 bytes.

      MIPS = MB per sec * 14/32
      MOPS = MB per sec *  4/32

L56	mov     ecx,+1f4080H[esp+edx*4]   load xi[m] to ecx
	mov     eax,+3e80c0H[esp+edx*4]   load yi[m] to eax
	add     ecx,eax                   add
	mov     +1f4080H[esp+edx*4],ecx   store xi[m] from ecx
	mov     eax,+3e80c4H[esp+edx*4]   load yi[m+1] to eax
	add     +1f4084H[esp+edx*4],eax   add eax to xi[m+1]
	mov     eax,+3e80c8H[esp+edx*4]   load yi[m+2]
	add     +1f4088H[esp+edx*4],eax   add to xi[m+2]
	mov     eax,+3e80ccH[esp+edx*4]   load yi[m+3]
	add     +1f408cH[esp+edx*4],eax   add to xi[m+3]
	mov     ecx,+5dc26cH[esp]         loop limit to ecx
	add     edx,ebx                   loop control
	cmp     edx,ecx
	jl      L56


3.3  ARRAY TO ARRAY

Again all three sections carry out the same operations on the appropriate 
data types. For comparison with Assignment MOPS results in the Whetstone 
Benchmark, each assignment is considered to be an operation (OP).

for (m=0; m<kd; m=m+4)
  {
      xd[m]   = yd[m];
      xd[m+1] = yd[m+1];
      xd[m+2] = yd[m+2];
      xd[m+3] = yd[m+3];
  }


3.3.1  DOUBLE PRECISION INSTRUCTIONS

This first loads the four elements of xd[] sequentially then stores them to 
yd[] sequentially. It uses 13 instructions for the 4 operations on 32 bytes 
loaded.

      MIPS = MB per sec * 13/32
      MOPS = MB per sec *  4/32


L65	fld     qword ptr [esp+edx*8]            load y[m] to register R7 
	fld     qword ptr +8H[esp+edx*8]         load y[m+1] to R6
	fld     qword ptr +10H[esp+edx*8]        load y[m+2] to R5
	fld     qword ptr +18H[esp+edx*8]        load y[m+3] to R4
	fxch    st(3)                            R4<y[m] R7<y[m+3]
	fstp    qword ptr +0fa040H[esp+edx*8]    store x[m] R4
	fxch    st(1)                            R5<y[m+1] R6<y[m+2]
	fstp    qword ptr +0fa048H[esp+edx*8]    store x[m+1] R5
	fstp    qword ptr +0fa050H[esp+edx*8]    store x[m+2] R6
	fstp    qword ptr +0fa058H[esp+edx*8]    store x[m+3] R7
	add     edx,ebx                          loop control
	cmp     edx,eax
	jl      L65


3.3.2  SINGLE PRECISION INSTRUCTIONS

As double precision but on 16 bytes loaded.

      MIPS = MB per sec * 13/16
      MOPS = MB per sec *  4/16

L74	fld     dword ptr +2ee0a0H[esp+edx*4]
	fld     dword ptr +2ee0a4H[esp+edx*4]
	fld     dword ptr +2ee0a8H[esp+edx*4]
	fld     dword ptr +2ee0acH[esp+edx*4]
	fxch    st(3)
	fstp    dword ptr +4e20e0H[esp+edx*4]
	fxch    st(1)
	fstp    dword ptr +4e20e4H[esp+edx*4]
	fstp    dword ptr +4e20e8H[esp+edx*4]
	fstp    dword ptr +4e20ecH[esp+edx*4]
	add     edx,ebx
	cmp     edx,eax
	jl      L74


3.3.3  INTEGER INSTRUCTIONS

This uses 12 instructions to read 16 bytes with alternate loads and stores.

      MIPS = MB per sec * 12/16
      MOPS = MB per sec *  4/16

L83	mov     ecx,+3e80c0H[esp+edx*4]      load  yi[m] to ecx
	mov     +1f4080H[esp+edx*4],ecx      store xi[m]
	mov     ecx,+3e80c4H[esp+edx*4]      load  yi[m+1]
	mov     +1f4084H[esp+edx*4],ecx      store xi[m+1]
	mov     ecx,+3e80c8H[esp+edx*4]      load  yi[m+2]
	mov     +1f4088H[esp+edx*4],ecx      store xi[m+2]
	mov     ecx,+3e80ccH[esp+edx*4]      load  yi[m+3]
	mov     +1f408cH[esp+edx*4],ecx      store xi[m+3]
	mov     ecx,+5dc26cH[esp]            load loop limit
	add     edx,ebx                      loop control
	cmp     edx,ecx
	jl      L83


4.  OUTPUT DISPLAY

When the program is running, the results are displayed using the following 
format. The figures in the results column are derived from the 
calculations. The first result would be Passes x 250 but could be slightly 
less on a faster computer. The second result is likely to be somewhat less 
than Passes x 500. The inaccuracies are due to adding multiple calculations 
of 1.0 x 1.0 in floating point. All other results should be the same as 
Passes or max m. 


   Memory Reading Speed Test Win 3.1 Version 1 Sun May  4 15:35:32 1997
                 Copyright (C) 1997, Roy Longbottom

Test                  Passes     max m   Bytes  Secs   MB/Sec       Result

s=s+x[m]*y[m]    Dbl  1113043 x    250    4000  4.89   910.46    278260750
s=s+x[m]*y[m]    Sng   556521 x    500    4000  4.95   449.71    276833728
s=s+x[m]+y[m]    Int   775757 x    500    4000  4.94   628.14       775757
x[m]=x[m]+y[m]   Dbl  1113043 x    250    4000  5.00   890.43      1113043
x[m]=x[m]+y[m]   Sng   646464 x    500    4000  4.95   522.40       646464
x[m]=x[m]+y[m]   Int   731428 x    500    4000  5.17   565.90       731428
x[m]=y[m]        Dbl  1939393 x    250    4000  5.11   759.06          250
x[m]=y[m]        Sng  1007874 x    500    4000  5.21   386.90          500
x[m]=y[m]        Int  1292929 x    500    4000  5.22   495.38          500


5.0  RESULTS FILE

Results are appended to file XFERMBPS.TXT which should appear in the same 
directory as the EXE file. The results are in the following format. For 
comparison purposes, result from CACHECHK V 6 are also shown.


5.1  200 MHz PENTIUM PRO WINDOWS NT 4.0

Dell XPS Pro 200n, PentiumPro 200 MHz, 32 MB EDO RAM, 440FX PCIset, cache 
L1 8K/8K L2 256K, NT 4.0

             CACHECHK V6 MB/S  L1 244.3, L2 231.5, RAM 110.8

   Memory Reading Speed Test Win95/NT Version 1 by Roy Longbottom

               Start of test Sun May  4 17:22:55 1997

  Memory    s=s+x[m]*y[m] Int+     x[m]=x[m]+y[m]         x[m]=y[m]
   Bytes    Dble   Sngl   Int    Dble   Sngl   Int    Dble   Sngl   Int
    Used    MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S

    4000   869.5  448.2  627.0 1032.3  420.6  614.4  843.2  391.5  286.0
    8000   894.0  452.0  632.1 1053.6  422.2  625.6  881.0  395.6  288.2
   16000   676.4  461.0  527.2  436.6  303.9  305.7  295.9  234.9  224.1
   32000   667.9  462.4  525.1  433.1  302.4  303.5  292.0  233.5  222.2
   64000   669.3  462.7  526.8  434.0  351.7  305.1  293.8  228.9  222.2
  128000   544.7  463.1  524.5  393.8  348.8  304.5  236.9  233.7  223.0
  256000   222.6  167.5  204.4  155.8  124.1  168.1   78.7   78.9  113.0
  512000   142.7  120.4  131.3   97.3   86.2   92.0   49.0   49.0   51.6
 1024000   142.7  119.0  126.9   96.8   84.9   87.6   48.8   48.2   48.3
 2048000   142.4  118.8  126.9   96.8   85.2   87.8   48.5   48.1   48.5

                End of test Sun May  4 17:33:00 1997


5.2  200 MHz PENTIUM PRO BOOT WITH MS DOS 6.2 

        Memory Reading Speed Test DOS Version 1 by Roy Longbottom

               Start of test Mon May  5 18:10:43 1997

  Memory    s=s+x[m]*y[m] Int+     x[m]=x[m]+y[m]         x[m]=y[m]
   Bytes    Dble   Sngl   Int    Dble   Sngl   Int    Dble   Sngl   Int
    Used    MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S

    4000   852.9  449.7  624.1 1034.3  423.1  615.9  843.2  392.6  286.3
    8000   890.4  450.6  630.2 1042.7  419.9  628.1  883.4  396.6  287.6
   16000   669.3  443.7  506.0  400.7  356.2  303.9  294.4  233.5  235.8
   32000   664.9  444.2  504.4  396.0  362.4  303.9  290.9  231.0  231.8
   64000   669.3  443.3  504.4  393.0  358.0  301.2  290.9  230.4  222.7
  128000   673.0  447.8  508.0  400.2  354.5  301.2  290.9  231.0  224.9
  256000   664.9  439.9  504.4  393.0  355.4  304.8  290.9  230.4  230.3
  512000   140.5  107.7  123.3  100.6   89.0   89.0   50.6   51.1   49.8
 1024000   139.7  107.7  123.2  100.5   88.9   88.9   51.0   51.2   49.3
 2048000   139.1  108.5  123.5  100.9   88.9   90.1   51.1   51.6   49.3

                End of test Mon May  5 18:21:06 1997


5.3  100 MHz PENTIUM WINDOWS 95

Escom, Pentium 100 MHz,  Neptune chipset, 16 MB RAM, cache L1 8K/8K L2 
256K, Windows 95

             CACHECHK V6 MB/S  L1 136.7, L2 85.7, RAM 59.4

    Memory Reading Speed Test Win95/NT Version 1 by Roy Longbottom

               Start of test Sun May  4 17:24:22 1997

  Memory    s=s+x[m]*y[m] Int+     x[m]=x[m]+y[m]         x[m]=y[m]
   Bytes    Dble   Sngl   Int    Dble   Sngl   Int    Dble   Sngl   Int
    Used    MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S

    4000   222.6  140.1  154.4  280.9  153.1  177.3   66.3   32.7   37.4
    8000   251.0  143.9  162.3  306.4  158.5  180.6   77.2   34.1   34.8
   16000   118.4   87.1   73.1   91.6   73.1   58.3   76.9   35.3   35.3
   32000   102.0   86.4   83.6   73.0   72.1   66.8   58.9   33.5   33.5
   64000    95.6   74.7   85.0   66.6   57.0   66.6   58.8   32.8   33.0
  128000    86.2   70.3   78.2   61.3   52.7   59.7   47.8   32.5   32.1
  256000    78.0   60.1   69.9   56.3   45.8   51.5   46.5   27.8   28.2
  512000    63.2   54.5   59.5   45.7   41.6   43.5   38.1   23.9   24.5
 1024000    60.0   50.8   54.8   43.4   38.8   40.2   32.4   21.8   22.3
 2048000    59.8   50.2   54.1   43.3   38.6   39.8   30.7   20.6   21.7

                End of test Sun May  4 17:34:21 1997


5.4  100 MHz PENTIUM BOOT WITH MS DOS 6.2

     Memory Reading Speed Test DOS Version 1 by Roy Longbottom

               Start of test Mon May  5 18:10:58 1997

  Memory    s=s+x[m]*y[m] Int+     x[m]=x[m]+y[m]         x[m]=y[m]
   Bytes    Dble   Sngl   Int    Dble   Sngl   Int    Dble   Sngl   Int
    Used    MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S

    4000   245.6  143.9  166.1  294.4  155.7  186.2  106.0   52.9   53.5
    8000   266.7  147.5  169.9  312.9  162.3  197.2  104.7   52.7   52.7
   16000   122.2   88.5  102.2   93.9   73.9   83.0  102.4   46.7   52.2
   32000   121.0   88.5  100.0   92.8   74.0   82.0   60.4   37.4   42.8
   64000   104.7   88.4  102.2   75.6   73.9   82.3   60.4   36.1   39.4
  128000    81.6   79.5   89.0   56.0   64.0   68.5   60.2   34.8   33.4
  256000    68.5   64.8   70.9   48.2   50.4   52.9   59.8   33.2   32.6
  512000    60.2   51.0   54.3   42.8   39.6   41.9   60.2   32.9   32.9
 1024000    58.9   49.8   53.5   41.8   38.7   41.4   30.4   20.7   21.6
 2048000    58.8   49.8   53.8   41.8   38.9   40.9   29.8   20.7   21.5

                End of test Mon May  5 18:20:47 1997


5.5  66 MHz 80486DX2 WINDOWS 95

Escom, 80486DX2 66.7 MHz, CIS chipset, 20 MB RAM, cache L1 8K L2 128K, 
Windows 95

            CACHECHK V6 MB/S  L1 67.2, L2 29.3, RAM 23.6

      Memory Reading Speed Test Win95/NT Version 1 by Roy Longbottom

               Start of test Sun May  4 17:18:08 1997

  Memory    s=s+x[m]*y[m] Int+     x[m]=x[m]+y[m]         x[m]=y[m]
   Bytes    Dble   Sngl   Int    Dble   Sngl   Int    Dble   Sngl   Int
    Used    MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S

    4000    35.6   18.7   36.5   32.4   16.9   62.8   18.2   15.2   17.8
    8000    34.2   18.1   59.2   30.4   16.2   54.5   17.8   15.2   17.4
   16000    23.5   14.5   27.2   18.6   12.7   25.0   16.4   14.3   15.4
   32000    23.5   13.4   27.1   18.6   11.0   24.6   10.3    8.7   11.5
   64000    22.4   13.6   26.6   16.5   11.5   23.1    9.8    8.2   11.9
  128000    18.8   12.0   12.0   12.1    9.1   14.2    8.8    7.5   11.1
  256000    17.4   11.6   20.9   11.2    8.7   13.5    8.9    7.6    9.8
  512000    16.7   11.3   20.0   10.8    8.2   12.4    8.5    7.0    9.5
 1024000    16.8   11.6   18.6   10.8    8.2   12.0    8.3    7.1    8.8
 2048000    16.5   11.4   17.9   10.7    8.2    8.4    8.2    7.0    8.4

                End of test Sun May  4 17:29:09 1997


5.6  66 MHz 80486DX2 BOOT WITH DOS 6.2

           Memory Reading Speed Test DOS Version 1 by Roy Longbottom

               Start of test Mon May  5 18:03:18 1997

  Memory    s=s+x[m]*y[m] Int+     x[m]=x[m]+y[m]         x[m]=y[m]
   Bytes    Dble   Sngl   Int    Dble   Sngl   Int    Dble   Sngl   Int
    Used    MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S

    4000    37.4   19.6   70.9   33.9   17.9   64.4   29.4   16.4   29.7
    8000    36.6   19.2   63.1   32.7   17.3   58.2   30.7   16.2   27.9
   16000    24.9   15.4   28.3   19.8   13.5   26.7   27.0   15.7   27.7
   32000    24.9   15.4   28.7   19.8   13.4   26.6   14.0   10.1   18.0
   64000    23.6   15.4   28.7   17.1   13.4   26.6   11.6    9.2   15.9
  128000    20.7   14.9   27.1   13.7   12.1   21.4   10.3    9.1   12.1
  256000    16.5   11.7   18.3   11.4    8.8   12.5   10.2    9.1   11.6
  512000    16.4   11.7   17.9   11.2    8.6   12.4    8.3    7.1    8.4
 1024000    16.4   11.6   17.9   11.2    8.7   12.4    8.4    7.1    8.3
 2048000    16.4   11.7   17.9   11.2    8.6   12.3    8.4    7.1    8.3

                End of test Mon May  5 18:14:01 1997


6.  ANALYSIS  OF RESULTS

6.1  CONSISTENCY

The programs were run three times on each PC via the Operating System and 
when booted with just MS DOS 6.2. On a given PC, measurements via DOS were 
within 2% of each other on the three tests. Tests via the Operating system 
had some variations, probably due to the OS interrupting the data flow. An 
indication of variations can be obtained by comparing the DOS and OS 
results.

Pentium Pro / NT 4.0
              
  L1 cache  Consistent results                         4000 - 8000
  L2 cache  Consistent results                        16000 -  64000
            Some variations up to 50%                 128000
            Most results varying by at least 20%      256000
  RAM       Results within +5% to -5%                 512000 + 

  DOS clear performance change L1 cache to L2 cache to RAM


Pentium 100 / Win95

  L1 cache  Some variations up to 40%, 27 out of 36 +5%  to -5%
  L2 cache  Some variations up to 30%, 54 out of 72 +10% to -10%
  RAM       Results within +5% to -5%


80486 Results 

Only integer operations reflect speed of caches due to slow CPU.


6.2  MFLOPS, MOPS and MIPS

Conversion ratios are given above so that data transfer rates can be 
converted to Millions of Floating Point Operations Per Second (MFLOPS), 
MOPS for non-floating operations and real machine code Millions of 
Instructions Per Second (MIPS). The following shows derived speeds with 
minimum results from RAM access, maximum from L1 cache results and average 
based on mean L2 cache figures.

               MIPS        Integer MOPS       SP MFLOPS     DP MFLOPS

     MHz   Min  Avg  Max   Min  Avg  Max   Min  Avg  Max   Min  Avg  Max
             
Ppro 200    21  173  359    11   82  158    11   78  113     6   54  111
Pent 100    12   35  107     5   17   42     5   15   37     3    9   33
486   66     3    8   28     2    5   18     1    2    5     1    2    5

Notes:

1  Pentium Pro performance gains are more pronounced with average L2 cache
   results.

2  Pentium floating point speed improvement is higher than that with
   integer arithmetic.

3  Range of DP MFLOPS is similar to Livermore benchmark results.

4  Linpack benchmark results are similar to L2 cache average DP MFLOPS.

5  Maximum MIPS are quite similar to calculated VAX MIPS in Whetstone
   benchmark.

6  Benchmark results such as Intel's iComp2, SPECint95 and SPECfp95 have
   PPro200/P100 ratios of about 2.5. These may be more dependent on
   accessing memory than cache.


7.  DEVELOPMENT COMPLICATIONS

During development of the program, significant changes in measured speeds 
were produced after making simple changes outside the main timing loops. In 
most cases, instructions used for timing were unchanged and data arrays 
appeared to be stored at the same memory addresses. The effect may have 
been influenced by differences between the relative addresses of data and 
instructions. The speed changes were mainly apparent with L1 cache 
transfers where about a third of the results were higher or lower by about 
20%. The exception was on the last measurement with integer array to array 
transfers where results on the Pentium Pro could be 80% faster than the 286 
MB/S shown above.


8.  MULTITASKING

As indicated above, variations in speeds can be caused by operating system 
interference when running the benchmark by itself. When multitasking two 
copies of the program, further variations can be produced.

On running two copies, each program could be expected to produce equal 
speed measurements of half the single program results. A test on the 
Pentium Pro showed this effect with L1 cache and RAM dependent measurements 
but the following sort of MB/sec variations via L2 cache.


   Memory    s=s+x[m]*y[m] Int+     x[m]=x[m]+y[m]         x[m]=y[m]
   Bytes    Dble   Sngl   Int    Dble   Sngl   Int    Dble   Sngl   Int
    Used    MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S   MB/S
Copy1
   64000   333.1  229.6  256.2  212.0  174.6  149.2  142.8  115.3  111.1
  128000   327.5  117.4* 256.0  214.7   88.1* 149.1  143.4   64.0* 109.2
  256000   145.1   86.0   99.7   89.4   63.8   68.7   45.7   43.8   44.4
  512000    73.6   60.7   64.7   49.9   43.2   46.1   25.0   24.8   25.5
Copy2
   64000   334.9  230.1  257.7  214.7  172.4  151.2  143.5  113.0  108.5
  128000   328.4  151.8* 254.1  212.9  116.1* 147.5  142.7   85.8* 108.2
  256000   134.2   85.1   94.6   82.2   62.8   67.2   43.7   42.0   45.4
  512000    73.2   60.4   63.6   48.9   43.1   45.4   25.0   24.5   25.9
NT4 1 job
   64000   669.3  462.7  526.8  434.0  351.7  305.1  293.8  228.9  222.2
  128000   544.7  463.1  524.5  393.8  348.8  304.5  236.9  233.7  223.0
  256000   222.6  167.5  204.4  155.8  124.1  168.1   78.7   78.9  113.0
  512000   142.7  120.4  131.3   97.3   86.2   92.0   49.0   49.0   51.6
DOS
   64000   669.3  443.3  504.4  393.0  358.0  301.2  290.9  230.4  222.7
  128000   673.0  447.8  508.0  400.2  354.5  301.2  290.9  231.0  224.9
  256000   664.9  439.9  504.4  393.0  355.4  304.8  290.9  230.4  230.3
  512000   140.5  107.7  123.3  100.6   89.0   89.0   50.6   51.1   49.8

It could be concluded that some strange benchmark results could be expected 
if tasks have a L2 cache dependency.


9.  PC FLOATING POINT INSTRUCTIONS

As defined for the IBM Personal Computer XT (1983 version Technical 
Reference Manual), the Math Coprocessor has eight 80 bit registers (0-7) 
which can be used as a stack. These can hold temporary real numbers of 19 
significant decimal digits.

Loading the first number places it in register 7, the latest register 
referenced being referred to as ST(0) or ST. A second number would be 
loaded to register 6 which now becomes ST(0), the first one being referred 
to as ST(1). On a store instruction, the register pointed to by ST(0) is 
stored and the next higher number register becomes ST(0). The ST pointer 
can also be changed by some arithmetic operations.

All coprocessor instruction mnemonics start with the letter F.

fld   qword ptr +0fa040H[esp+eax]   This loads 8 bytes to new ST(0)
from address pointed to by number + stack pointer + loop count register

With register 3 as ST(0), register 7 will be ST(4)
faddp st(4), st   adds register 3 to register 7
Now register 4 is ST(0) and register 7 is ST(3)

With register 4 as ST(0)
fstp    qword ptr +0fa048H[esp+edx*8] stores register 4
Now register 5 is ST(0)


10. SUBMITTING RESULTS

Results should be sent to Roy_Longbottom@compuserve.com and the following 
information on the system under test should be included.

               PC Supplier/model 
               CPU chip           
               Clock MHz        
               Cache size           
               Chipset & H/W Options
               OS/DOS version       
               Run by (name)        
               Company/Location 
               E-Mail address 

The configuration details can be provided via program SYSTEMxx.EXE as 
supplied with the Classic Benchmarks. 


