Matrix multiplication in SaC

Set-notation

double[.,.] matMult(double[.,.] X, double[.,.] Y)
{
	res = { [i, j] -> sum(X[[i,.]] * Y[[.,j]]) };
	return(res);
}

Set-notation with transposing

double[.,.] matMult(double[.,.] X, double[.,.] Y)
{
	res = { [i,j] -> sum(X[[i,.]] * transpose(Y)[[j,.]]) };
	return(res);
}

With-loop

double[.,.] matMult(double[.,.] X, double[.,.] Y)
{
	res = with {
		(. <= [i,j] <= .): with {
			([0] <= [k] < [shape(X)[[1]]]): X[[i, k]] * Y[[k, j]];
		}: fold(+, 0.0);
	}: genarray([shape(X)[[0]], shape(Y)[[1]]], 0.0);

	return(res);
}

With-loop with transposing

double[.,.] matMult(double[.,.] X, double[.,.] Y)
{
	y = with {
		(. <= [i, j] <= .): Y[[j, i]];
	}: genarray(shape(Y), 0.0);
	res = with {
		(. <= [i,j] <= .): with {
			([0] <= [k] < [shape(X)[[1]]]): X[[i, k]] * y[[j, k]];
		}: fold(+, 0.0);
	}: genarray([shape(X)[[0]], shape(Y)[[1]]], 0.0);

	return(res);
}

Run-time results

Time for 1000×1000 matrices

Time for 2000×2000 matrices

Time for 4000×4000 matrices

Time for 8000×8000 matrices

Run-time results with explicit specialization

specialize double[1000,1000] matMult(double[1000,1000] X, double[1000,1000] Y);
specialize double[2000,2000] matMult(double[2000,2000] X, double[2000,2000] Y);
specialize double[4000,4000] matMult(double[4000,4000] X, double[4000,4000] Y);
specialize double[8000,8000] matMult(double[8000,8000] X, double[8000,8000] Y);

Time for 1000×1000 matrices

Time for 2000×2000 matrices

Time for 4000×4000 matrices

Time for 8000×8000 matrices

Measurements with PAPI timer

Time for 100×100 matrices

Time for 500×500 matrices

Time for 1000×1000 matrices