【问题标题】:Counting number of floating point operations in javascript在javascript中计算浮点运算的数量
【发布时间】:2023-04-03 07:03:02
【问题描述】:

我正在尝试写一篇关于我用 javascript 开发和编码的算法的科学文章。我希望将旧的慢版本与新的快速版本进行各种输入的比较,并能够报告一些指标,例如对 Math.log 的调用次数、对 Math.exp 的调用次数、乘法运算的次数,除法运算次数、加法次数、减法次数等

我意识到 javascript 引擎的 JIT 编译器可以做一些优化来稍微改变这些数字,但我并不真正关心每个指标的确切细节,我只是在比较苹果和苹果两者算法。

是否有任何工具或方法可以在 javascript 中自动计算这些操作?是否有任何 javascript 引擎可以生成某种类型的中间字节码,从而允许自动计算这些操作?如果不是javascript,那么c++呢?

【问题讨论】:

  • Chrome 可能会在其个人资料结果中显示对 Math.x 的调用次数。
  • Javascript 允许您重新定义内置方法。例如 -> var oLog = Math.log; Math.log = (x) => { console.log('log'); return oLog(x); } 将控制台输出 log 并返回原始日志。所以如果你没有太多想要分析的函数,这个简单的方法可能会做。

标签: javascript profiling time-complexity


【解决方案1】:

这是一个包装原始 Math.sin 和 Math.log 的非常简单的示例,并记录调用次数。

这很有效,因为在 Javascript 中你甚至可以替换内置的..

let counts = {};

function profileProc(root, name, proc) {
  let oProc = proc;
  root[name] = function() {
    counts[name] = counts[name] ? counts[name] + 1 : 1;
    return oProc.apply(proc, arguments);
  }
}

profileProc(Math, 'log', Math.log);
profileProc(Math, 'sin', Math.sin);

console.log(Math.log(10));
console.log(Math.sin(10));
console.log(Math.sin(20));

console.log(counts);

【讨论】:

  • 谢谢,我肯定会将它用于 Math.x 函数。我更担心基本的 * / + - 操作。对这些有什么想法吗?
【解决方案2】:

嗯,看来我找到了一些可行的方法。作为 paper.js 的一部分,有一种名为 PaperScript 的脚本语言,它解析用 javascript 语法编写的代码并添加运算符重载,如 here 所述。基本上,paper.js 提供了paper.PaperScript.compile(code) 函数,该函数采用 javascript 代码并将每个数学运算替换为对

的调用
function __$__(left, operator, right) {...}

所以像 var var c = a * b; 这样的表达式变成了var c = __$__(a, '*', b); 一旦进行了这种转换,修改__$__ 函数以计算操作很简单:

window.operatorCounts = {};
window.operatorCounts['+'] = 0;
window.operatorCounts['-'] = 0;
window.operatorCounts['*'] = 0;
window.operatorCounts['/'] = 0;
window.operatorCounts['%'] = 0;
window.operatorCounts['=='] = 0;
window.operatorCounts['!='] = 0;

function __$__(left, operator, right) {
  window.operatorCounts[operator]++;
  switch (operator) {
  case '+': return left + right;
  case '-': return left - right;
  case '*': return left * right;
  case '/': return left / right;
  case '%': return left % right;
  case '==': return left == right;
  case '!=': return left != right;
  default:
    throw new Error('Implement Operator: ' + operator);
  }
};

在定义了这个经过检测的操作符版本之后,运行新编译的函数就很简单了。通过将此与 Keith 对 Math.x 函数的回答相结合,我能够完成我打算做的事情。

【讨论】:

    猜你喜欢
    • 2018-07-07
    • 2012-09-21
    • 2012-09-12
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    • 2011-01-10
    相关资源
    最近更新 更多