Javascript中的高性能矩阵 - 矩阵乘法

时间:2015-02-16 10:58:08

标签: javascript matrix-multiplication

我正在尝试将一些基本的MATLAB移植到Javascript,并且对JS的性能有点失望,无论是Chrome还是Firefox。通过转置其中一个矩阵,展开内部循环并使用Float64Arrays,我进行了略微优化:

function vvdot_body(rollsize)
{
 var body = '';

 body += ' var acc, ni, nj, nr, rs, lo, i;\n';
 body += ' acc = 0.0;\n';
 body += ' rs = ' + rollsize + ';\n';
 body += ' nr = Math.floor(n / rs);\n';
 body += ' lo = n - (nr * rs);\n';
 body += ' for (i=0; i<nr; i++) {\n';
 body += '  ni = aos + i * rs;\n';
 body += '  nj = bos + i * rs;\n';

 /* begin unroll */
 body += '  acc += a[ni] * b[nj] ';
 for (var i=1; i<rollsize; i++)
  body += ' + a[ni + ' + i + '] * b[nj + ' + i + ']';
 body += ';\n }\n'
 /* done unroll */

 /* handle leftover */
 body += ' ni = aos + nr * rs;\n';
 body += ' nj = bos + nr * rs;\n';
 body += ' for (i=0; i<lo; i++)\n';
 body += '  acc += a[ni + i] * b[nj + i];\n\n';

 body += ' return acc;';

 return body;
}

function mkvvdot(rollsize)
{
 var args = 'a,b,n,aos,bos'
   , body = vvdot_body(rollsize);
 return new Function(args, body);
}

/* transpose */
function T(b, n, bT) {
  for (var i = 0; i < n; i++) {
    for (var j = 0; j < n; j++) {
      bT[i * n + j] = b[j * n + i];
    }
  }
}

function mkmmm(unroll) {
  var vvdot = mkvvdot(unroll);
  return function(a, b, c, n) {
   var bT = new Float64Array(n*n);
   T(b, n, bT);
   for (var i = 0; i < n; i++) {
    for (var j = 0; j < n; j++) {
     c[i * n + j] = vvdot(a, bT, n, i * n, j * n);
    }
   }
 }
}

以下JS Fiddle运行基准

http://jsfiddle.net/42nmw4yx/2/

在我的机器上(E5-1650),在矢量点内循环中展开的变化显示在Chrome 40中的峰值性能为~2.6 Gflops,在Firefox 35中为~1.0,而MATLAB,单核心,运行15-20 Gflops。

将JS中的天真算法与供应商的线性代数库(MKL)进行比较似乎是不公平的,我可以接受50%的性能损失,但2015年的数量级似乎是不合理的。

除了(ab)使用WebGL进行计算外,我还能做什么?可能的答案属于1)Javascript的类别,即不使用匿名函数(实际上并不慢)2)线性代数技巧,即转置其中一个矩阵(我已经完成了,具有很好的加速) 3)其他?

编辑修正了flops / s以简单地触发。此外,我在引用NumPy安装(Debian软件包)上运行了bencmark,它显示了与Javascript相同的错误性能,因此由于MKL的全能性而出现了性能上的巨大差异。 MKL&amp;供应商调整库..

2 个答案:

答案 0 :(得分:0)

您可以尝试使用SIMD.JS.它目前在Firefox中受支持,但尚未在Chrome中支持。在这手牌上有Crosswalk(https://crosswalk-project.org/),它是使用Chromium源码基础构建的,可以在许多平台上使用。

SIMD指令可通过英特尔®酷睿™和英特尔®凌动™处理器以及ARM *处理器访问。

答案 1 :(得分:0)

在Firefox中尝试此操作(每晚) https://jsperf.com/simdmat4

您也可以在Chrome中使用标记--js-flags =“ - harmony-simd”

在Firefox中,SIMD的速度要快3倍,Chrome的速度要慢20倍(Chrome还在使用polyfill?)