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;
}
}
}
}
}
|