Matrix multiply transpose vs direct multiplication

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
}

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
}

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], YTranspose[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.