我一直在尝试Math.imul()方法,我发现它在输入很少的情况下速度更快,在输入很多的情况下速度更慢。为什么会这样呢?
(也许它与Math.imul()本身无关,但这并不重要,我仍然对理解我得到的结果感兴趣。)
代码:
const base_multiplier = 40;
const input_counts = [
base_multiplier,
base_multiplier * 10,
base_multiplier * 100,
base_multiplier * 1000
];
for (const input_count of input_counts) {
const value_pairs = Array
.from({ length: input_count })
.map(() => [
Math.round(Math.random() * 100),
Math.round(Math.random() * 100)
])
console.time(`${input_count} inputs | Standart multiplication`);
eval('value_pairs.forEach(([x, y]) => x * y)')
console.timeEnd(`${input_count} inputs | Standart multiplication`);
console.time(`${input_count} inputs | Imul multiplication`);
eval('value_pairs.forEach(([x, y]) => Math.imul(x, y))')
console.timeEnd(`${input_count} inputs | Imul multiplication`);
}
Chrome控制台的输出:
40 inputs | Standart multiplication: 0.048ms
40 inputs | Imul multiplication: 0.043ms
400 inputs | Standart multiplication: 0.031ms
400 inputs | Imul multiplication: 0.063ms
4000 inputs | Standart multiplication: 0.826ms
4000 inputs | Imul multiplication: 3.604ms
40000 inputs | Standart multiplication: 0.834ms
40000 inputs | Imul multiplication: 0.898msNode的输出:
40 inputs | Standart multiplication: 0.510ms
40 inputs | Imul multiplication: 0.064ms
400 inputs | Standart multiplication: 0.569ms
400 inputs | Imul multiplication: 0.108ms
4000 inputs | Standart multiplication: 0.172ms
4000 inputs | Imul multiplication: 3.253ms
40000 inputs | Standart multiplication: 0.502ms
40000 inputs | Imul multiplication: 0.762ms发布于 2017-03-23 09:33:04
基本的答案是,Math.imul和*的乘法是不同的,因此不应该像这样进行比较。Math.imul执行32位整数乘法,但仍然必须接受java脚本编号作为输入。因此,它必须执行额外的操作来转换和/或确保输入是整数。(参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul )
这意味着Math.imul(a,b)接受Js浮点数并产生类似于Math.floor(a) * Math.floor(b)的结果
为了使测试更准确,我们可以尝试使用Uint32数组,对Math.random结果进行舍入,确保所有分配发生在循环开始处,并在结束时计算和,以防止编译器优化mul操作。
结果仍然不明确,我怀疑这归结于整数运算带来的imul速度增益与转换和函数调用的损失之间的平衡。而这种平衡是大小相关的。
var base = 40;
var input = [base, base * 10, base * 100, base * 1000];
for (var j = 0; j < input.length; ++j) {
var length = input[j];
var arrayX = new Uint32Array(length);
var arrayY = new Uint32Array(length);
var im = new Uint32Array(length);
var sm = new Uint32Array(length);
for (var i = 0; i < input[j]; ++i) {
arrayX[i] = Math.round(Math.random() * 100);
arrayY[i] = Math.round(Math.random() * 100)
}
console.time(input[j] + ' inputs | Standard multiplication');
for (var i = 0; i < length; ++i) {
sm[i] = arrayX[i] * arrayY[i];
}
console.timeEnd(input[j] + ' inputs | Standard multiplication');
console.time(input[j] + ' inputs | Imul multiplication');
for (var i = 0; i < length; ++i) {
im[i] = Math.imul(arrayX[i], arrayY[i]);
}
console.timeEnd(input[j] + ' inputs | Imul multiplication');
// Prevent multiplication from being optimized away
var sum = 0;
for (var i = 0; i < length; ++i) {
sum += sm[i];
sum += im[i];
}
console.log(sum);
}
在我的机器上的Chrome中,对于40000或更大的输入大小,imul现在比标准的*乘法略快一些。而4000大小的情况对于imul来说仍然很慢。但是,如果基数更改为35,则它们大致相等。如果基数更改为55,则*将比imul慢得多。
40 inputs | Standard multiplication: 0.120ms
40 inputs | Imul multiplication: 0.035ms
203634
400 inputs | Standard multiplication: 0.045ms
400 inputs | Imul multiplication: 0.050ms
1967184
4000 inputs | Standard multiplication: 0.290ms
4000 inputs | Imul multiplication: 2.935ms
20062298
40000 inputs | Standard multiplication: 0.605ms
40000 inputs | Imul multiplication: 0.450ms
199130538
55 inputs | Standard multiplication: 0.130ms
55 inputs | Imul multiplication: 0.040ms
237716
550 inputs | Standard multiplication: 0.070ms
550 inputs | Imul multiplication: 0.060ms
2638770
5500 inputs | Standard multiplication: 3.175ms
5500 inputs | Imul multiplication: 0.095ms
27218460
55000 inputs | Standard multiplication: 0.850ms
55000 inputs | Imul multiplication: 0.575ms
277160962https://stackoverflow.com/questions/42353622
复制相似问题