// File RTCG8.cs --- sparse matrices // sestoft@itu.dk * 2002-09-23 // A matrix A is an array of arrays (rows) of doubles, so A[i][j] is // row i column j. // We consider multiplications A*B where B is a sparse matrix, and // for given B generate code that computes A*B when given a matrix A. using System; using System.Collections; using System.Reflection; using System.Reflection.Emit; public class RTCG8 { public static void Main(string[] args) { int dim1 = int.Parse(args[0]), dim2 = int.Parse(args[1]), dim3 = int.Parse(args[2]), nonzero = int.Parse(args[3]), count = int.Parse(args[4]); // Generate some random matrices double[][] A = randomSparse(dim1, dim2, dim1*dim2), B = randomSparse(dim2, dim3, nonzero), R1 = newMatrix(dim1, dim3), R2 = newMatrix(dim1, dim3), R3 = newMatrix(dim1, dim3), R4 = newMatrix(dim1, dim3); // Generate a specialized sparse multiplication method AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "myassembly"; // Build: run-only assembly AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); // Build: module mymodule ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("mymodule"); // Build: public class MyClass { ... } TypeBuilder typeBuilder = moduleBuilder.DefineType("MyClass", TypeAttributes.Class | TypeAttributes.Public, typeof(Object)); Type ty; // Build: public static void sparseMultB(double[][] A, double[][] R) // and possibly additional copies (for timing) { Timer t = new Timer(); SparseMatrix sparseB = new SparseMatrix(B); sparseMultGen(typeBuilder, "sparseMultB", dim1, dim2, sparseB); // If there are 6 or more arguments, build the method repeatedly int methodCount = args.Length >= 6 ? int.Parse(args[5]) : 1; for (int i=methodCount-1; i>0; i--) sparseMultGen(typeBuilder, "sparseMultB"+i, dim1, dim2, sparseB); // Load the class file into the VM ty = typeBuilder.CreateType(); // Probably we need to call the method to convince CLR to JIT it? Console.WriteLine("Generating " + methodCount + " copies of sparseMultB: " + t.Check() + " sec"); } { Timer t = new Timer(); for (int i=count; i>0; i--) matrixMult(A, B, R1); Console.WriteLine("matrixMult: " + t.Check() + " sec"); } { Timer t = new Timer(); for (int i=count; i>0; i--) sparseMult(A, B, R2); Console.WriteLine("sparseMult: " + t.Check() + " sec"); } { Timer t = new Timer(); SparseMatrix sparseB = new SparseMatrix(B); for (int i=count; i>0; i--) sparseMult(A, sparseB, R3); Console.WriteLine("sparseMult, two-phase: " + t.Check() + " sec"); } { MethodInfo m = ty.GetMethod("sparseMultB"); Timer t = new Timer(); for (int i=count; i>0; i--) m.Invoke(null, new Object[] { A, R4 }); Console.WriteLine("Generated sparseMultB: " + t.Check() + " sec"); } Console.WriteLine("R1 == R2 is " + equal(R1, R2)); Console.WriteLine("R2 == R3 is " + equal(R2, R3)); Console.WriteLine("R3 == R4 is " + equal(R3, R4)); } // Compute A*B in R // Assume A, B and R are rectangular and non-empty public static void matrixMult(double[][] A, double[][] B, double[][] R) { int aRows = A.Length, aCols = A[0].Length, bRows = B.Length, bCols = B[0].Length, rRows = R.Length, rCols = R[0].Length; if (aCols != bRows || aRows != rRows || bCols != rCols) throw new Exception("Matrix dimension mismatch"); else { for (int i=0; i