首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gpu.js是否有BigDecimal或float64array可能?

gpu.js是否有BigDecimal或float64array可能?
EN

Stack Overflow用户
提问于 2022-06-03 19:33:11
回答 1查看 106关注 0票数 0

gpu.js的帮助下,我正在编写一个mandelbrot计算器,到目前为止,一切都很好。我面临的唯一问题是,GPU只想计算32位浮点数.或者至少这是官方文件告诉我的。

但是,当使用pythonnumba进行同样的计算时--它们也运行在相同的GPU上--在绘制mandelbrot分形时要精确得多。

有了Python,我就可以接近于1e-15,而在Javascript中,1e-7周围的图像变得模糊。

Python内核:

代码语言:javascript
复制
@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内核:

代码语言: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内核?

EN

回答 1

Stack Overflow用户

发布于 2022-07-16 13:11:21

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

对于这个内核示例:

代码语言:javascript
复制
const glslDivide = `float divide(float a, float b) {
  return a / b;
}`;

也许有一种方法可以用“双”代替“浮点”,用它来代替简单的乘法和加法。

我不知道如何使用glsl,但如果后端可以连接到glsl,这应该是可行的。此外,“双”需要glsl 4.0,因此它可能无法工作。

即使它工作,它仍然需要所有迭代递归,因为没有“状态变量”的双重定义。就像调用相同的函数直到达到最大迭代一样。应该有两个函数参数来跟踪虚部和实部,还有两个其他函数参数来跟踪迭代次数,也许还有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中执行任何操作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72494397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档