Matrix multiply transpose vs direct multiplication (v3)

Revision 3 of this benchmark created on


Description

Matrix multiplication normally and with transpose then dot product

Setup

var a = [
[1,2,3,4,1,2,3,4],
[5,6,7,8,5,6,8,8],
[11,12,13,14,11,12,13,14],
[15,16,17,18,15,16,17,18],
[1,2,3,4,1,2,3,4],
[5,6,7,8,5,6,8,8],
[11,12,13,14,11,12,13,14],
[15,16,17,18,15,16,17,18]
]
  
var b = [
[21,22,23,24,21,23,24,25],
[35,36,37,38,35,36,37,38],
[41,42,43,44,41,42,43,44],
[45,46,47,48,45,46,47,48],
[21,22,23,24,21,23,24,25],
[35,36,37,38,35,36,37,38],
[41,42,43,44,41,42,43,44],
[45,46,47,48,45,46,47,48]
]

const initialize = (rows, columns) => {
  //let final = []
  //for (let i = 0; i < rows; i++){
    //let temp = []
    //for (let j = 0; j < columns; j++){
      //temp.push(0)
    //}
    //final.push(temp)
  //}
  //return final
  var result = new Array(columns).fill(0).map(row => new Array(rows).fill(0));
  return result;
}

const dotProduct = (v1,v2) => {
  let sum = 0;
  for (let i = 0; i < v1.length; i++){
    sum += v1[i] * v2[i]
  }
  return sum
}
//const transpose = matrix => {
  //let trans = [];
  //for (let i = 0; i < matrix[0].length; i++){
    //let temp = [];
    //for (let j = 0; j < matrix.length; j++){
      //temp.push(matrix[j][i])
    //}
    //trans.push(temp)
  //}
  //return trans
//}
function transpose(matrix) {  for (var i = 0; i < matrix.length; i++) {    for (var j = 0; j < i; j++) {      const temp = matrix[i][j];      matrix[i][j] = matrix[j][i];      matrix[j][i] = temp;    }  }}


const mult = (X,Y) => {
  let initial = initialize(X.length, Y[0].length)
  //let YTranspose = 
  transpose(Y)
  for (let i = 0; i < X.length; i++){
    for (let j = 0; j < Y.length; j++){
      initial[i][j] = dotProduct(X[i], Y[j])
    }
  }
  return initial
}

function proposed_multiply(a, b) {
    let aRows = a.length;
    let aCols = a[0].length;
    let bCols = b[0].length;
    let result = new Array(aRows); 
    for (let r = 0; r < aRows; ++r) {
        const row = new Array(bCols);
        result[r] = row;
        const ar = a[r];
        for (let c = 0; c < bCols; ++c) {
            let sum = 0.;     
            for (let i = 0; i < aCols; ++i) {
                sum += ar[i] * b[i][c];
            }
            row[c] = sum;  
        }
    }
    return result;
}

//schoolbook matrix multiplication
function schoolbook_multiply(m1, m2) {
    var result = [];
    for (var i = 0; i < m1.length; i++) {
        result[i] = [];
        for (var j = 0; j < m2[0].length; j++) {
            var sum = 0;
            for (var k = 0; k < m1[0].length; k++) {
                sum += m1[i][k] * m2[k][j];
            }
            result[i][j] = sum;
        }
    }
    return result;
}

function matrixDot (A, B) {
    var result = new Array(A.length).fill(0).map(row => new Array(B[0].length).fill(0));

    return result.map((row, i) => {
        return row.map((val, j) => {
            return A[i].reduce((sum, elm, k) => sum + (elm*B[k][j]) ,0)
        })
    })
}

Test runner

Ready to run.

Testing in
TestOps/sec
Plain multiply
schoolbook_multiply(a, b)
ready
Better plain multiply
proposed_multiply(a,b)
ready
Transpose then dot product
mult(a, b)
ready
Map reduce
matrixDot(a, b)
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.