// File RTCG8.java --- sparse matrices // sestoft@itu.dk * 2002-09-19 // Using the gnu.bytecode package from http://www.gnu.org/software/kawa // 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. import gnu.bytecode.*; import java.io.*; // IOException import java.util.*; // Random, ArrayList etc public class RTCG8 { public static void main(String[] args) throws IOException, NoSuchMethodException, IllegalAccessException, java.lang.reflect.InvocationTargetException { final int dim1 = Integer.parseInt(args[0]), dim2 = Integer.parseInt(args[1]), dim3 = Integer.parseInt(args[2]), nonzero = Integer.parseInt(args[3]), count = Integer.parseInt(args[4]); // Generate some random matrices final double[][] A = randomSparse(dim1, dim2, dim1*dim2), B = randomSparse(dim2, dim3, nonzero), R1 = new double[dim1][dim3], R2 = new double[dim1][dim3], R3 = new double[dim1][dim3], R4 = new double[dim1][dim3]; // Generate a specialized sparse multiplication method ClassType co = new ClassType("MyClass"); co.setSuper("java.lang.Object"); co.setModifiers(Access.PUBLIC); Class ty = null; // Build: public static void sparseMultB(double[][] A, double[][] R) // and possibly additional copies (for timing) { final Timer t = new Timer(); final SparseMatrix sparseB = new SparseMatrix(B); sparseMultGen(co, "sparseMultB", dim1, dim2, sparseB); // If there are 6 or more arguments, build the method repeatedly final int methodCount = args.length >= 6 ? Integer.parseInt(args[5]) : 1; for (int i=methodCount-1; i>0; i--) sparseMultGen(co, "sparseMultB"+i, dim1, dim2, sparseB); // Output class file to array: byte[] classFile = co.writeToArray(); // Load the class file into the JVM ty = new ArrayClassLoader().loadClass("MyClass", classFile); System.out.println("Generating " + methodCount + " copies of sparseMultB: " + t.Check() + " sec"); } { Timer t = new Timer(); for (int i=count; i>0; i--) matrixMult(A, B, R1); System.out.println("matrixMult: " + t.Check() + " sec"); } { Timer t = new Timer(); for (int i=count; i>0; i--) sparseMult(A, B, R2); System.out.println("sparseMult: " + t.Check() + " sec"); } { Timer t = new Timer(); SparseMatrix sparseB = new SparseMatrix(B); for (int i=count; i>0; i--) sparseMult(A, sparseB, R3); System.out.println("sparseMult, two-phase: " + t.Check() + " sec"); } { java.lang.reflect.Method m = ty.getMethod("sparseMultB", new Class[] { double[][].class, double[][].class }); Timer t = new Timer(); for (int i=count; i>0; i--) m.invoke(null, new Object[] { A, R4 }); System.out.println("Generated sparseMultB: " + t.Check() + " sec"); } { Timer t = new Timer(); for (int i=count; i>0; i--) matrixMult(A, B, R1); System.out.println("matrixMult: " + t.Check() + " sec"); } System.out.println("R1 == R2 is " + equal(R1, R2)); System.out.println("R2 == R3 is " + equal(R2, R3)); System.out.println("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) { final 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 Error("Matrix dimension mismatch"); else { for (int i=0; i