oop_v1p5.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 623 行 · 第 1/2 页

C
623
字号
//=============================================================================
//
//  OOPACK - a benchmark for comparing OOP vs. C-style programming.
//  Copyright (C) 1995 Arch D. Robison
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  For a copy of the GNU General Public License, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//=============================================================================
//
// OOPACK: a benchmark for comparing OOP vs. C-style programming.
// 
// Version: 1.5
// 
// Author: Arch D. Robison (robison@kai.com)
//         Kuck & Associates 
//         1906 Fox Dr.
//         Champaign IL 61820
//              
// Web Info: http://www.kai.com/oopack/oopack.html
//
// Last revised: Oct 11, 1995
//
// This benchmark program contains a suite of tests that measure the relative 
// performance of object-oriented-programming (OOP) in C++ versus just writing
// plain C-style code in C++.  All of the tests are written so that a 
// compiler can in principle transform the OOP code into the C-style code.  
// After you run this benchmark and discover just how much you are paying to 
// use object-oriented programming, you will probably say: OOP? ACK!
// (Unless, of course, you have Kuck & Associates' Photon C++ compiler.)
//
// TO COMPILE
//
//      Compile with your favorite C++ compiler.  E.g. ``CC -O2 oopack.C''.
//      On most machines, no special command-line options are required.  
//      For Suns only, you need to define the symbol ``sun4''.  
//      E.g. ``g++ -O -Dsun4 oopack.C''.
//
// TO RUN
//
//      To run the benchmark, run ``a.out Max=50000 Matrix=500 Complex=20000 Iterator=50000''.
//      This runs the four tests for the specified number of iterations.
//      E.g., the Max test is run for 50000 iterations.  You may want to 
//      adjust the number of iterations to be small enough to get
//      an answer in reasonable time, but large enough to get a reasonably
//      accurate answer.
//
// INTERPRETING THE RESULTS
//      
//      Below is an example command line and the program's output.
//
//      $ a.out Max=5000 Matrix=50 Complex=2000  Iterator=5000
//      Version 1.5               Seconds       Mflops         
//      Test       Iterations     C    OOP     C    OOP  Ratio
//      ----       ----------  -----------  -----------  -----
//      Max              5000    1.3   1.3    3.8   4.0    1.0
//      Matrix             50    1.5   2.8    8.6   4.5    1.9
//      Complex          2000    1.5   5.3   10.8   3.0    3.6
//      Iterator         5000    1.1   1.6    9.4   6.3    1.5
//      
//      The ``Test'' column gives the names of the four tests that are run.  
//      The ``Iterations'' column gives the number of iterations that a test 
//      was run.  The The two ``Seconds'' columns give the C-style 
//      and OOP-style running times for a test.  The two ``Mflops'' columns
//      give the corresponding megaflop rates.  The ``Ratio'' column gives
//      the ratio between the times.  The value of 1.5 at the bottom, for 
//      example, indicates that the OOP-style code for Iterator ran 1.5 times 
//      more slowly than the C-style code.
//
//      Beware that a low ``Ratio'' could indicate either that the OOP-style
//      code is compiled very well, or that the C-style code is compiled poorly.
//      OOPACK performance figures for KAI's Photon C++ and some other compilers
//      can be found in http://www.kai.com/oopack/oopack.html.
//
// Revison History
//      9/17/93         Version 1.0 released
//      10/5/93         Allow results to be printed even if checksums do not match.
//      10/5/93         Increased ``Tolerance'' to allow 10-second runs on RS/6000.  
//      10/5/93         Version 1.1 released
//      1/10/94         Change author's address from Shell to KAI
//      1/13/94         Added #define's for conditional compilation of individual tests
//      1/21/94         Converted test functions to virtual members of class Benchmark.
//     10/11/94         Added routine to inform user of command-line usage.
//     10/11/94         Version 1.5 released.

//=============================================================================

#include <assert.h>
#include <ctype.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

//
// The source-code begins with the benchmark computations themselves and
// ends with code for collecting statistics.  Each benchmark ``Foo'' is
// a class FooBenchmark derived from class Benchmark.  The relevant methods
// are:
//
//      init - Initialize the input data for the benchmark
//
//      c_style - C-style code
//
//      oop_style - OOP-style code
//
//      check - computes number of floating-point operations and a checksum.
//
const int BenchmarkListMax = 4;

class Benchmark {
public:
    void time_both( int iteration_count, double limit ) const;
    void time_one( void (Benchmark::*function)() const, int iterations, double& sec, double& Mflop, double& checksum ) const;
    virtual const char * name() const = 0;
    virtual void init() const = 0;
    virtual void c_style() const = 0; 
    virtual void oop_style() const = 0;
    virtual void check( int iterations, double& flops, double& checksum ) const = 0;
    static Benchmark * find( const char * name );
private:
    static Benchmark * list[BenchmarkListMax];
    static int count;
protected:
    Benchmark() {list[count++] = this;}
};

// The initializer for Benchmark::count *must* precede the declarations
// of derived of class Benchmark.
int Benchmark::count = 0;
Benchmark * Benchmark::list[BenchmarkListMax];

//
// The ``iterations'' argument is the number of times that the benchmark 
// computation was called.  The computed checksum that ensures that the
// C-style code and OOP code are computing the same result.  This 
// variable also prevents really clever optimizers from removing the
// the guts of the computations that otherwise would be unused.
//

// Each of the following symbols must be defined to enable a test, or
// undefined to disable a test.  The reason for doing this with the
// preprocessor is that some compilers may choke on specific tests.
#define HAVE_MAX 1
#define HAVE_MATRIX 1
#define HAVE_COMPLEX 1 
#define HAVE_ITERATOR 1

const int N = 1000;

#if HAVE_MAX
//=============================================================================
//
// Max benchmark
//
// This benchmark measures how well a C++ compiler inlines a function that 
// returns the result of a comparison.  
//
// The functions C_Max and OOP_Max compute the maximum over a vector.
// The only difference is that C_Max writes out the comparison operation
// explicitly, and OOP_Max calls an inline function to do the comparison.
//
// This benchmark is included because some compilers do not compile 
// inline functions into conditional branches as well as they might.  
//
const int M = 1000;             // Dimension of vector
double U[M];                    // The vector
double MaxResult;               // Result of max computation

class MaxBenchmark: public Benchmark {
private:
    const char * name() const {return "Max";}
    void init() const;
    void c_style() const; 
    void oop_style() const;
    void check( int iterations, double& flops, double& checksum ) const;
} TheMaxBenchmark;

void MaxBenchmark::c_style() const              // Compute max of vector (C-style)
{               
    double max = U[0];
    for( int k=1; k<M; k++ )                    // Loop over vector elements
        if( U[k] > max )  
            max=U[k];
    MaxResult = max;
}

inline int Greater( double i, double j ) 
{
    return i>j;
}

void MaxBenchmark::oop_style() const            // Compute max of vector (OOP-style)
{       
    double max = U[0];
    for( int k=1; k<M; k++ )                    // Loop over vector elements
        if( Greater( U[k], max ) ) 
            max=U[k];
    MaxResult = max;
}

void MaxBenchmark::init() const                         
{
    for( int k=0; k<M; k++ ) 
        U[k] = k&1 ? -k : k;
}

void MaxBenchmark::check( int iterations, double& flops, double& checksum ) const
{
    flops = (double)M*iterations;
    checksum = MaxResult;
}
#endif /* HAVE_MAX */

#if HAVE_MATRIX
//=============================================================================
//
// Matrix benchmark
//
// This benchmark measures how well a C++ compiler performs constant propagation and 
// strength-reduction on classes.  C_Matrix multiplies two matrices using C-style code; 
// OOP_Matrix does the same with OOP-style code.  To maximize performance on most RISC 
// processors, the benchmark requires that the compiler perform strength-reduction and 
// constant-propagation in order to simplify the indexing calculations in the inner loop.
//
const int L = 50;               // Dimension of (square) matrices.

double C[L*L], D[L*L], E[L*L];  // The matrices to be multiplied.

class MatrixBenchmark: public Benchmark {
private:
    const char * name() const {return "Matrix";}
    void init() const;
    void c_style() const; 
    void oop_style() const;
    void check( int iterations, double& flops, double& checksum ) const;
} TheMatrixBenchmark;

void MatrixBenchmark::c_style() const {         // Compute E=C*D with C-style code.
    for( int i=0; i<L; i++ )
        for( int j=0; j<L; j++ ) {
            double sum = 0;
            for( int k=0; k<L; k++ )
                sum += C[L*i+k]*D[L*k+j];
            E[L*i+j] = sum;
        }
}

class Matrix {  // Class Matrix represents a matrix stored in row-major format (same as C).
private:
    double *data;       // Pointer to matrix data
public:
    int rows, cols;     // Number of rows and columns

    Matrix( int rows_, int cols_, double * data_ ) :
        rows(rows_), cols(cols_), data(data_)
    {}

    double& operator()( int i, int j ) {        // Access element at row i, column j
        return data[cols*i+j];
    }
};

void MatrixBenchmark::oop_style() const {       // Compute E=C*D with OOP-style code.
    Matrix c( L, L, C );                        // Set up three matrices
    Matrix d( L, L, D );
    Matrix e( L, L, E );
    for( int i=0; i<e.rows; i++ )               // Do matrix-multiplication
        for( int j=0; j<e.cols; j++ ) {
            double sum = 0;
            for( int k=0; k<e.cols; k++ )
                sum += c(i,k)*d(k,j);
            e(i,j) = sum;
        }
}

void MatrixBenchmark::init() const      
{
    for( int j=0; j<L*L; j++ ) {
        C[j] = j+1;
        D[j] = 1.0/(j+1);
    }
}

void MatrixBenchmark::check( int iterations, double& flops, double& checksum ) const
{
    double sum = 0;
    for( int k=0; k<L*L; k++ )
        sum += E[k];
    checksum = sum;
    flops = 2.0*L*L*L*iterations;
}
#endif /* HAVE_MATRIX */

#if HAVE_ITERATOR
//=============================================================================
//
// Iterator benchmark 
//
// Iterators are a common abstraction in object-oriented programming, which

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?