How to tune numerical D? (matrix multiplication is faster in g++ vs gdc)

J private at private-dont-email-dont-spam.com
Mon Mar 4 04:28:24 PST 2013


On Monday, 4 March 2013 at 08:02:46 UTC, J wrote:
> That's a really good point. I wonder if there is a canonical 
> matrix that would be preferred?

I'm not sure if they are the recommended/best practice for matrix 
handling in D at the moment (please advise if they are not), but 
with a little searching, I found that the SciD library has nice 
matrices and MattrixViews (column-major storage, LAPACK 
compatible).

Now I like MatrixViews because they let me beat the original 
(clearly non-optimal) C matrix multiplication by a couple 
seconds, and the D code with operator overloading in place makes 
matrix multiplication look elegant.

One shootout benchmark down, eleven to go. :-)

- J

p.s. Am I right in concluding there are no multimethods (multiple 
dispatch) in D... it seemed a little awkward to have to wrap the 
MatrixView in a new struct solely in order to overload 
multiplication. Is there a better way that I've missed?

#beating the C/malloc/shootout based code that ran in 1m32sec:

$ time ./scid_matrix_test
-1015380632 859379360 -367726792 -1548829944

real    1m27.967s
user    1m27.930s
sys 0m0.030s
$ time ./scid_matrix_test
-1015380632 859379360 -367726792 -1548829944

real    1m28.259s
user    1m28.230s
sys 0m0.020s
$

module scid_matrix_test;

// compile: gdmd -O -release -inline -noboundscheck 
scid_matrix_test.d -L-L/home/you/pkg/scid/scid/ -L-lscid 
-L-L/usr/lib/x86_64-linux-gnu/ -L-lgfortran -L-lblas -L-llapack 
-L-L.

import scid.matrix;

import std.stdio, std.string, std.array, std.conv;
const int SIZE = 2000;

import std.stdio;


// Doesn't seem to have multiple dispatch / multimethods, so
// I guess we have to wrap MatrixView to implement 
opBinary!"*"(lhs,rhs)

struct Multipliable (T) {
   MatrixView!(T) _m;
   alias _m this;
   this(MatrixView!(T) src) {
     _m = src;
   }

   Multipliable!(T) opBinary(string op : "*")(ref Multipliable 
rhs) if (op == "*") {
     auto r = Multipliable!int(matrix!int(_m.rows,rhs.cols));
     return mmult(this, rhs, r);
   }

}


Multipliable!(int) mkmatrix(int rows, int cols)
{
     auto m = Multipliable!int();
     m._m = matrix!int(rows,cols);

     int count = 1;
     for(int i = 0; i < rows; ++i)
     {
         for(int j = 0; j < cols; ++j)
         {
             m[i,j] = count++;
         }
     }
     return(m);
}



Multipliable!(int) mmult(ref Multipliable!(int) m1, ref 
Multipliable!(int) m2, ref Multipliable!(int) m3) {
     int i, j, k, val;
     ulong rows = m1.rows;
     ulong cols = m1.cols;
     for (i=0; i<rows; i++) {
     for (j=0; j<cols; j++) {
         val = 0;
         for (k=0; k<cols; k++) {
         val += m1[i,k] * m2[k,j];
         }
         m3[i,j] = val;
     }
     }
     return(m3);
}


void main()
{
     auto m1 = mkmatrix(SIZE,SIZE);
     auto m2 = mkmatrix(SIZE,SIZE);
     auto mm = mkmatrix(SIZE,SIZE);

     mm = m1 * m2;

     writefln("%d %d %d %d",mm[0,0],mm[2,3],mm[3,2],mm[4,4]);

}


More information about the Digitalmars-d mailing list