Javascript中的性能矩阵乘法

Javascript中的性能矩阵乘法,javascript,matrix-multiplication,Javascript,Matrix Multiplication,我正在尝试将一些基本的MATLAB移植到Javascript,对JS的性能有点失望,无论是Chrome还是Firefox。我通过转换其中一个矩阵、展开内部循环和使用浮点数组进行了轻微优化: function vvdot_body(rollsize) { var body = ''; body += ' var acc, ni, nj, nr, rs, lo, i;\n'; body += ' acc = 0.0;\n'; body += ' rs = ' + rollsize + ';

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

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);
    }
   }
 }
}
功能vvdot_主体(卷尺寸)
{
变量体=“”;
正文+='var acc,ni,nj,nr,rs,lo,i;\n';
正文+='acc=0.0;\n';
body+='rs='+rollsize+';\n';
正文+='nr=数学楼层(n/rs);\n';
正文+='lo=n-(nr*rs);\n';

body+='for(i=0;i您可以尝试使用SIMD.JS。它目前在Firefox中受支持,但在Chrome中尚不受支持。另一方面,Crosswalk()是使用Chrome源代码库构建的,在许多平台上都可用

SIMD指令可在Intel®Core中访问™ 和英特尔®;Atom™ 处理器,以及ARM*处理器。

在Firefox中试试这个(每晚)

您也可以在Chrome中使用标志--js flags=“--harmony simd”来尝试此操作


在firefox中,SIMD的速度快了3倍,在Chrome中慢了20倍(Chrome仍然使用polyfill?)

您是否已经尝试过使用Web Workers?您是否已经看过现有的performant javascript线性代数库?此外,JS中的乘法运算速度很慢,请尝试避免乘法运算。请遵循一般的JS性能技巧,例如编写i | 0而不是数学。floor(i)。查看asm.js以获得更好的FF性能。感谢您提供的提示:将代码放入worker中提高了~8%。asm.js使FF提高了10%,但降低了Chrome的速度。i | 0技巧没有多大帮助,但不在内部循环中。带动画基准的最终JSFIDLE:我没有详细阅读您的代码,但有改进的潜力:例如,将nr=(n/rs)| 0替换为nr=(n*'+1/rollsize+)|0;要消除非常慢的除法,请使用类似的技术来消除内部循环中的乘法,例如,不是每个循环计算两次i*R,而是通过“+rollsize+”;…将计数器增量推到“+rollsize+”;…您可能还可以将nr=…;lo=…;计算推到预计算等。您的“模板化”技术仍然让人印象深刻;性能有很大提高吗?Firefox每晚(而且只有在您使用Chrome的情况下)使用一个标志--js flags=“--harmony simd”。不确定这是在polyfill上运行还是在real simd上运行