为什么我的WebAssembly函数比JavaScript等效函数慢?
为这个宽泛的问题道歉!我正在学习WASM,并用C语言创建了一个Mandelbrot算法:为什么我的WebAssembly函数比JavaScript等效函数慢?,webassembly,Webassembly,为这个宽泛的问题道歉!我正在学习WASM,并用C语言创建了一个Mandelbrot算法: int iterateEquation(float x0, float y0, int maxiterations) { float a = 0, b = 0, rx = 0, ry = 0; int iterations = 0; while (iterations < maxiterations && (rx * rx + ry * ry <= 4.0)) {
int iterateEquation(float x0, float y0, int maxiterations) {
float a = 0, b = 0, rx = 0, ry = 0;
int iterations = 0;
while (iterations < maxiterations && (rx * rx + ry * ry <= 4.0)) {
rx = a * a - b * b + x0;
ry = 2.0 * a * b + y0;
a = rx;
b = ry;
iterations++;
}
return iterations;
}
void mandelbrot(int *buf, float width, float height) {
for(float x = 0.0; x < width; x++) {
for(float y = 0.0; y < height; y++) {
// map to mandelbrot coordinates
float cx = (x - 150.0) / 100.0;
float cy = (y - 75.0) / 100.0;
int iterations = iterateEquation(cx, cy, 1000);
int loc = ((x + y * width) * 4);
// set the red and alpha components
*(buf + loc) = iterations > 100 ? 255 : 0;
*(buf + (loc+3)) = 255;
}
}
}
我正在加载JavaScript,编译,然后调用,如下所示:
instance.exports.mandelbrot(0, 300, 150)
正在将输出复制到画布,这使我能够验证它是否正确执行。在我的电脑上,执行上述功能大约需要120毫秒
但是,这里有一个JavaScript等价物:
const iterateEquation = (x0, y0, maxiterations) => {
let a = 0, b = 0, rx = 0, ry = 0;
let iterations = 0;
while (iterations < maxiterations && (rx * rx + ry * ry <= 4)) {
rx = a * a - b * b + x0;
ry = 2 * a * b + y0;
a = rx;
b = ry;
iterations++;
}
return iterations;
}
const mandelbrot = (data) => {
for (var x = 0; x < 300; x++) {
for (var y = 0; y < 150; y++) {
const cx = (x - 150) / 100;
const cy = (y - 75) / 100;
const res = iterateEquation(cx, cy, 1000);
const idx = (x + y * 300) * 4;
data[idx] = res > 100 ? 255 : 0;
data[idx+3] = 255;
}
}
}
const iterateEquation=(x0,y0,maxiterations)=>{
设a=0,b=0,rx=0,ry=0;
设迭代次数=0;
而(迭代次数<最大迭代次数&(rx*rx+ry*ry{
对于(变量x=0;x<300;x++){
对于(变量y=0;y<150;y++){
常数cx=(x-150)/100;
常数cy=(y-75)/100;
常数res=迭代方程(cx,cy,1000);
常数idx=(x+y*300)*4;
数据[idx]=res>100?255:0;
数据[idx+3]=255;
}
}
}
只需约62毫秒即可执行
现在我知道WebAssembly是一个非常新的产品,它并没有得到非常好的优化。但我还是忍不住觉得它应该比这个更快
有人能发现我可能错过的东西吗
此外,我的C代码从“0”开始直接写入内存-我想知道这是否安全?堆栈存储在分页线性内存中的什么位置?我是否要冒覆盖它的风险
这里有一把小提琴来说明:
运行时,它会记录两个等效实现(WASM和JavaScript)的时间安排。General
通常,与优化的JS相比,您可以希望在繁重的数学计算中获得约10%的提升。这包括:
- 利润
- 内存输入/输出复制费用
.set()
在wasm中尝试按字读/写像素(rgba)与读/写字节(r、g、b、a)的速度相同。我没有发现差异
当使用node.js
进行开发时(和我一样)下一个版本将v8升级到v6.0,并为这类数学引入了严重的速度倒退。对于8.2.1,不要使用现代ES6功能,如const
,=>
等。改用ES5。下一个版本使用v8 v6.2可能会解决这些问题
示例注释
benchmark.js
,这更准确简言之:在继续之前,清理东西是值得的
你可能会发现挖掘源代码或在实验中使用它很有用。我专门为CPU密集型的小事情创建了它,以通过适当的模块初始化、内存管理、js回退等简化问题。它包含“反锐化掩码”实现作为示例和基准。在那里采用你的代码应该不难。我有一个webassembly速度较慢的情况。编译时启用了安全堆选项。删除该选项后,速度大约是本机速度的两倍,因此编译选项也值得寻找。您可以提供类似JSFIDLE链接的内容进行尝试吗?您在哪个浏览器中测试?回答了堆栈问题,使用0是安全的在WebAssembly,但是C++编译时可能会不高兴。我只是想让它在WasmFiddle工作,我会尽快处理这个问题。浏览器是Chrome 61。谢谢链接到栈答案。@ JFBASTIAN -我增加了小提琴:我检查了C版本,在初始化浮点数时,我确保它有“.0f”而且性能显著提高。通过这次更改,WebAssembly版本比我笔记本电脑上的JS版本快。但是,在我的桌面上,JS版本仍然比WebAssembly版本快。修改后的fiddle:老实说,很难在文本中解释所有细节。检查多重数学将非常有用这些都是小的,经过战斗考验的,并且有很好的评论。但是规则禁止用单个链接回复:)
const iterateEquation = (x0, y0, maxiterations) => {
let a = 0, b = 0, rx = 0, ry = 0;
let iterations = 0;
while (iterations < maxiterations && (rx * rx + ry * ry <= 4)) {
rx = a * a - b * b + x0;
ry = 2 * a * b + y0;
a = rx;
b = ry;
iterations++;
}
return iterations;
}
const mandelbrot = (data) => {
for (var x = 0; x < 300; x++) {
for (var y = 0; y < 150; y++) {
const cx = (x - 150) / 100;
const cy = (y - 75) / 100;
const res = iterateEquation(cx, cy, 1000);
const idx = (x + y * 300) * 4;
data[idx] = res > 100 ? 255 : 0;
data[idx+3] = 255;
}
}
}