UML软件工程组织


Figure 2 矩阵乘法不调用垃圾收集
using System;

/// <summary>
/// A class representing a Matrix
/// </summary>
class Matrix
{
    double[,] matrix;
    int rows, columns;
    
    // This will not be called till before the application terminates
    ~Matrix()
    {
        Console.WriteLine("Finalize");
    }

    public Matrix(int sizeA, int sizeB)
    {
        rows = sizeA;
        columns = sizeB;
        matrix = new double[sizeA, sizeB];
    }
    
    // Indexer for setting/getting internal array elements
    public double this[int i, int j]
    {
        set { matrix[i,j] = value; }
        get { return matrix[i,j]; }
    }
    
    // Return number of rows in the matrix
    public int Rows
    {
        get { return rows; }
    }
    
    // Return number of columns in the matrix
    public int Columns
    {
        get { return rows; }
    }

}

/// <summary>
/// Matrix Multiplication Example
/// </summary>
class MatMulTest
{

    [STAThread]
    static void Main(string[] args)
    {
        int i, size, loopCounter;
        Matrix MatrixA, MatrixB, MatrixC;
        size = 200;
        
        MatrixA = new Matrix(size,size);
        MatrixB = new Matrix(size,size);
        MatrixC = new Matrix(size,size);

        /* Initialize matrices to random values */
        for (i=0; i<size; i++)
        {
            for (int j=0; j<size; j++) 
            {
                MatrixA [i,j]= (i + j) * 10;
                MatrixB [i,j]= (i + j) * 20;
            }
        }
        
        loopCounter = 1000;
        for (i=0; i < loopCounter; i++) Matmul(MatrixA, 
            MatrixB, MatrixC);
        
        Console.WriteLine("Done.");
        Console.ReadLine();
    }

    // Matrix multiplication routine
    public static void Matmul(Matrix A, Matrix B, Matrix C)
    {
        int i, j, k, size;
        double tmp;
        
        size = A.Rows;
        for (i=0; i<size; i++)
        {
            for (j=0; j<size; j++)
            {
                tmp = C[i,j];
                for (k=0; k<size; k++)
                {
                    tmp += A[i,k] * B[k,j];
                }
                C[i,j] = tmp;
            }
        }
    }
}


Figure 3 用户定义复数类型
using System;

/// <summary>
/// Implementation of a single-precision Complex Number
/// </summary>
public struct Complex
{

    // Real and Imaginary parts of a complex number
    private float real, imaginary;

    public Complex(float real, float imaginary) 
    {
        this.real = real;
        this.imaginary = imaginary;
    }

    // Accessor methods for accessing/setting private variables
    public float Real
    {
        get { return real; }
        set { real = value; }
    }
    
    public float Imaginary
    {
        get { return imaginary; }
        set { imaginary = value; }
    }

    //////////////////////////////////////////////
    //
    //  Implicit and Explicit conversion operators
    //
    
    // Implicit conversion of Complex-to-float
    public static implicit operator float(Complex c) 
    {
        return c.Real;
    }
    
    // Explicit conversion of float-to-complex (requires 
    // explicit cast)
    public static explicit operator Complex(float f) 
    {
        return new Complex(f, 0);
    }

    //////////////////////////////////////////////
    //
    //  Arithmetic overloaded operators:
    //  +, -, *, /, ==, !=
    //
    
    public static Complex operator +(Complex c) 
    {
        return c;
    }

    public static Complex operator -(Complex c) 
    {
        return new Complex(-c.Real, -c.Imaginary);
    }

    public static Complex operator +(Complex c1, Complex c2) 
    {
        return new Complex(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
    }

    public static Complex operator +(Complex c1, float num) 
    {
        return new Complex(c1.Real + num, c1.Imaginary);
    }

    public static Complex operator +(float num, Complex c1) 
    {
        return new Complex(c1.Real + num, c1.Imaginary);
    }

    public static Complex operator -(Complex c1, float num) 
    {
        return new Complex(c1.Real - num, c1.Imaginary);
    }

    public static Complex operator -(float num, Complex c1) 
    {
        return new Complex(c1.Real - num, c1.Imaginary);
    }

    public static Complex operator -(Complex c1, Complex c2) 
    {
        return new Complex(c1.Real - c2.Real, c1.Imaginary - 
            c2.Imaginary);
    }

    public static Complex operator *(Complex c1, Complex c2) 
    {
        return new Complex((c1.Real * c2.Real) - 
           (c1.Imaginary * c2.Imaginary), 
                    (c1.Real * c2.Imaginary) + (c1.Imaginary * 
                     c2.Real));
    }

    public static Complex operator *(Complex c1, float num) 
    {
        return new Complex(c1.Real*num, c1.Imaginary*num);
    }

    public static Complex operator *(float num, Complex c1) 
    {return new Complex(c1.Real * num, c1.Imaginary*num);}

    public static Complex operator /(Complex c1, Complex c2)
    {
        float div = c2.Real*c2.Real + c2.Imaginary*c2.Imaginary;
        if (div == 0) throw new DivideByZeroException();
            
        return new Complex((c1.Real*c2.Real + 
            c1.Imaginary*c2.Imaginary)/div,
                            (c1.Imaginary*c2.Real - 
                             c1.Real*c2.Imaginary)/div);
    }

    public static bool operator ==(Complex c1, Complex c2) 
    {
        return (c1.Real == c2.Real) && (c2.Imaginary == c2.Imaginary);
    }

    public static bool operator !=(Complex c1, Complex c2) 
    {
        return (c1.Real != c2.Real) || (c2.Imaginary != c2.Imaginary);
    }

    public override int GetHashCode()
    {
        return (Real.GetHashCode() ^ Imaginary.GetHashCode());
    }

    public override bool Equals(object o)
    {
        return (o is Complex)? (this == (Complex)o): false;
    }

    // Display the Complex Number in natural form:
    // ------------------------------------------------------------------
    // Note that calling this method will box the value into a string 
    // object and thus cause it to be allocated on the heap with a size of 
    // 24 bytes
    public override string ToString()
    {
        return(String.Format("{0} + {1}i", real, imaginary));
    }
}

/// <summary>
/// Class for testing the Complex Number type
/// </summary>
public class ComplexNumbersTest
{
    public static void Main() 
    {

        // Create two complex numbers
        Complex c1 = new Complex (2,3);
        Complex c2 = new Complex (3,4);

        // Perform some arithmetic operations
        Complex eq1 = c1 + c2 * -c1;
        Complex eq2 = (c1==c2)? 4*c1: 4*c2;
        Complex eq3 = 73 - (c1 - c2) / (c2-4);
        
        // Implicit conversion of Complex-to-float
        float real = c1;
        
        // Explicit conversion of float-to-Complex (requires 
        // explicit cast)
        Complex c3 = (Complex) 34;

        // Print complex numbers c1 and c2
        Console.WriteLine ("Complex number 1:  {0}", c1);
        Console.WriteLine ("Complex number 2: {0}\n", c2);
    
        // Print results of arithmetic operations
        Console.WriteLine ("Result of equation 1: {0}", eq1);
        Console.WriteLine ("Result of equation 2: {0}", eq2);
        Console.WriteLine ("Result of equation 3: {0}", eq3);
        Console.WriteLine ();
        
        // Print results of conversions
        Console.WriteLine ("Complex-to-float conversion: {0}", 
                           real);
        Console.WriteLine ("float-to-Complex conversion: {0}", 
                            c3);
        Console.ReadLine ();
    }
}


Figure 4 顺序和对角访问的基准测试
using System;

namespace PerfCounter {

    /// <summary>
    /// The class provides a "stop watch" for applications 
    /// requiring accurate timing measurements
    /// </summary>
    public class Counter
    {

        [System.Runtime.InteropServices.DllImport("KERNEL32")]
        private static extern bool QueryPerformanceCounter(ref 
            long lpPerformanceCount);
    
        [System.Runtime.InteropServices.DllImport("KERNEL32")]
        private static extern bool 
            QueryPerformanceFrequency(ref long lpFrequency); 
    
        long totalCount = 0;
        long startCount = 0;
        long stopCount  = 0;
        long freq       = 0;
    
        public void Start()
        {
            startCount = 0;
            QueryPerformanceCounter(ref startCount);
        }
    
        public void Stop()
        {
            stopCount = 0;
            QueryPerformanceCounter(ref stopCount);
            totalCount += stopCount - startCount;
        }
    
        public void Reset()
        {
            totalCount = 0;
        }
    
        public float TotalSeconds
        {
            get
            {
                freq = 0;
                QueryPerformanceFrequency(ref freq);
                return((float) totalCount / (float) freq);
            }
        }
    
        public double MFlops(double total_flops)
        {
            return (total_flops / (1e6 * TotalSeconds));
        }
        
        public override string ToString()
        {
            return String.Format("{0:F3} seconds", TotalSeconds);
        }
    }
}

using System;
using PerfCounter;

namespace BenchArrays
{
    /// <summary>
    /// Test sequential and diagonal access on jagged and 
    /// rectangular arrays
    /// </summary>
    class TestArrays
    {

        [STAThread]
        static void Main(string[] args)
        {
            int loopCounter = 1000;
            int dim         = 1000;
            double temp;
            
            // Declare a jagged two-dimensional array
            double[][] arrJagged = new double[dim][];
            
            // Declare a rectangular two-dimensional array
            double[,] arrRect = new double[dim, dim];

            /* Instantiateand Initialize Arrays */
            for (int i=0; i<arrJagged.Length; i++)
            {
                arrJagged[i] = new double[dim];
                for (int j=0; j<arrJagged[i].Length; j++)
                {
                    arrJagged[i][j] = arrRect[i, j] = i*j;
                }
            }
            
            Counter counter = new Counter();

            // LOOP 1
            // Measure sequential access for rectangular array
            counter.Reset();
            counter.Start();
            Console.WriteLine("Starting loop 1...");
            for(int i=0; i<loopCounter; i++)
            {
                for(int j=0; j<dim; j++) 
                {
                    for(int k=0; k<dim; k++)
                    {
                        temp = arrRect[j, k];
                    }
                }
            }
            counter.Stop();
            Console.WriteLine("Time for rect sequential access: 
                              {0}", counter);
            Console.WriteLine();
            
            // LOOP 2
            // Measure diagonal access for rectangular array
            Console.WriteLine("Starting loop 2...");
            counter.Reset();
            counter.Start();
            for(int i=0; i<loopCounter; i++)
            {
                for(int j=0; j<dim; j++) 
                {
                    for(int k=0; k<dim; k++)
                    {
                        temp = arrRect[k, k];
                    }
                }
            }
            counter.Stop();
            Console.WriteLine("Time for rect diagonal access: 
                              {0}", counter);
            Console.WriteLine();        
            
            // LOOP 3
            // Measure sequential access for jagged array
            counter.Reset();
            counter.Start();
            Console.WriteLine("Starting loop 3...");
            for(int i=0; i<loopCounter; i++)
            {
                for(int j=0; j<arrJagged.Length; j++) 
                {
                    for(int k=0; k<arrJagged[j].Length; k++)
                    {
                        temp = arrJagged[j][k];
                    }
                }
            }
            counter.Stop();
            Console.WriteLine("Time for jagged sequential 
                              access: {0}", counter);
            Console.WriteLine();

            // LOOP 4
            // Measure diagonal access for jagged array
            counter.Reset();
            counter.Start();
            Console.WriteLine("Starting loop 4...");
            for(int i=0; i<loopCounter; i++)
            {
                for(int j=0; j<arrJagged.Length; j++) 
                {
                    for(int k=0; k<arrJagged[j].Length; k++)
                    {
                        temp = arrJagged[k][k];
                    }
                }
            }
            counter.Stop();
            Console.WriteLine("Time for jagged diagonal access: 
                              {0}", counter);
            Console.WriteLine("End Of Benchmark.");
            Console.ReadLine();
        }
    }
}


Figure 6 使用不规则数组的矩阵乘法
using System;
using System.Diagnostics;
using PerfCounter;

namespace BenchJaggedMatrix
{
    /// <summary>
    /// Matrix Multiplication using Jagged Arrays
    /// </summary>
    class MatrixMul
    {

        [STAThread]
        static void Main(string[] args)
        {
            int i, n;

            // Declare jagged matrices
            double[][] MatrixA, MatrixB, MatrixC;
            Random r = new Random(50);
            n = 1000;

            MatrixA = new double[n][];
            MatrixB = new double[n][];
            MatrixC = new double[n][];

            /* Instantiate and Initialize Arrays */
            for (i=0; i<MatrixA.Length; i++) {
                MatrixA[i] = new double[n];
                MatrixB[i] = new double[n];
                MatrixC[i] = new double[n];
                for (int j=0; j<MatrixA[i].Length; j++) {
                    MatrixA[i][j]=(double)r.Next(50);
                    MatrixB[i][j]=(double)r.Next(50);
                }
            }

            Counter counter = new Counter();

            /* Call and measure Matdot */
            Console.WriteLine("Starting counter...");
            counter.Reset();
            counter.Start();
            Matdot(MatrixA, MatrixB, MatrixC);  // call MatDot
            counter.Stop();

            Console.WriteLine("Time taken: {0}", counter);
            Console.WriteLine("Obtained {0:F2} MFlops", 
                              counter.MFlops(2*n*n*n));
            Console.ReadLine();
        }

        public static void Matdot(double [][]a, double [][]b, 
                                  double [][]c)
        {
            int i,j,k;
            double tmp;

            for (i=0; i<a.Length; i++)
            {
                for (j=0; j<c[i].Length; j++)
                {
                    tmp = c[i][j];
                    for (k=0; k<b[i].Length; k++)
                    {
                        tmp += a[i][k]*b[k][j];
                    }
                    c[i][j]=tmp;
                }
            }
        }
    }
}


Figure 7 使用矩形数组的矩阵乘法
using System;
using System.Diagnostics;
using PerfCounter;

namespace BenchRectMatrix
{
    /// <summary>
    /// Matrix Multiplication using Rectangular Arrays
    /// </summary>
    class MatrixMul
    {

        [STAThread]
        static void Main(string[] args)
        {
            int i, n;

            // Declare rectangular matrices
            double[,] MatrixA, MatrixB, MatrixC;
            Random r = new Random(50);
            n = 1000;

            MatrixA = new double[n,n];
            MatrixB = new double[n,n];
            MatrixC = new double[n,n];

            /* Initialize to Random Values */
            for (i=0; i<n; i++) 
            {
                for (int j=0; j<n; j++) 
                {
                    MatrixA[i,j]=(double)r.Next(50);
                    MatrixB[i,j]=(double)r.Next(50);
                }
            }

            Counter counter = new Counter();

            /* Call and measure Matdot */        
            Console.WriteLine("Starting counter...");
            counter.Reset();
            counter.Start();
            Matdot(n, MatrixA, MatrixB, MatrixC); // call 
                                                  // MatDot
            counter.Stop();

            Console.WriteLine("Time taken: {0}", counter);
            Console.WriteLine("Obtained {0:F2} MFlops", 
                               counter.MFlops(2*n*n*n));
            Console.ReadLine();
        }

        public static void Matdot(int n, double [,]a, double 
                                  [,]b, double [,]c)
        {
            int i,j,k;
            double tmp;

            for (i=0; i<n; i++)
            {
                for (j=0; j<n; j++)
                {
                    tmp = c[i,j];
                    for (k=0; k<n; k++)
                    {
                        tmp += a[i,k] * b[k,j];
                    }
                    c[i,j]=tmp;
                }
            }
        }
    }
}
 

版权所有:UML软件工程组织