gpu.js与BigDecimal或float64array可能吗?



我在gpu.js的帮助下编写了一个mandelbrot计算器,直到现在,一切都运行得很好。我面临的唯一问题是,GPU只想计算32位浮点数。至少官方文件是这么告诉我的。
但是当用pythonnumba做同样的计算时——它们也在同一GPU上运行——在渲染mandelbrot分形时要精确得多。
使用Python,我能够接近1e-15,而在Javascript中,图像在1e-7左右变得模糊。

Python内核:

@cuda.jit(device=True)
def mandel(x, y, max_iters):
c = complex(x, y)
z = 0.0j
for i in range(max_iters):
z = z * z + c
if (z.real * z.real + z.imag * z.imag) >= 4:
return i
return max_iters

Javascript内核:

const recalculateMandelbrot = gpu.createKernel(function(x_start, x_end, y_start, y_end, iters){
let c_re = x_start + (x_end - x_start) * this.thread.x / 1024;
let c_im = y_start + (y_end - y_start) * this.thread.y / 1024;
let z_re = 0, z_im = 0;
let z_re_prev = 0;
for(let i = 0; i < iters; i++) {
z_re_prev = z_re;
z_re = z_re * z_re - z_im * z_im + c_re;
z_im = z_re_prev * z_im + z_re_prev * z_im + c_im;
if ((z_re * z_re + z_im * z_im) >= 4) {
return i;
}
}
return iters;
}).setOutput([1024, 1024]).setPrecision('single');

这些算法彼此相等,除了在Python中,我可以使用其内置的complex类型。

所以我考虑使用BigDecimal,在那里我可以实现任意精度(所以我可以放大到我想要的程度),但我不知道如何将其添加到我的gpu内核。

更新:

python之所以工作得更精确,是因为complex类型由两个64位浮点数组成。JavaScript的计算不那么精确的原因在于JavaScript本身。
我现在的问题集中在添加big.js到我的gpu内核?

这里有自定义内核测试文件:https://github.com/gpujs/gpu.js/blob/1be50c09ed4edb7c7e846b1815414ef504089ab6/test/features/add-custom-native-function.js

const glslDivide = `float divide(float a, float b) {
return a / b;
}`;

也许可以用"double"代替"float"用它来代替简单的乘法和加法。

我不知道如何使用glsl,但如果后端可以以某种方式连接到glsl,这应该工作。还"double"需要GLSL 4.0,所以可能无法工作。

即使它工作,它仍然需要所有的迭代递归,因为没有"状态变量";double的定义。就像调用同一个函数,直到达到最大迭代。应该有两个函数参数来跟踪虚部和实部,还有两个函数参数来跟踪迭代次数,可能还有c值。考虑到递归的深度是有限的,它可能无法工作。


即使在webgl后端,https://github.com/gpujs/gpu.js/blob/1be50c09ed4edb7c7e846b1815414ef504089ab6/src/backend/web-gl/fragment-shader.js看起来你可以只是编辑一些函数的字符串(如模块),并使用它像乘法/加法。

您也可以在这里阅读关于将四个32位值模拟的两个64位值相乘/相加的灵感:https://github.com/visgl/luma.gl/blob/master/modules/shadertools/src/modules/fp64/fp64-arithmetic.glsl.ts

在任何情况下,缓冲区(Js环境&GPU驱动程序)可能根本不工作,你被困在内核中100%的函数式编程(没有64位变量的状态处理)。

这些都不是好的选择。你应该使用一个库,让你把本地内核写成一个字符串(如https://github.com/kashif/node-cuda/blob/master/test/test.js),并直接从Javascript中使用它,这样你就可以做几乎任何你在CUDA/OpenCL中做的事情。

相关内容

  • 没有找到相关文章

最新更新