You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GPU.js绘制曼德博集合时CPU与GPU模式计算结果不一致

问题:GPU.js绘制曼德博集合时CPU与GPU模式计算结果不一致

尝试用GPU.js绘制曼德博集合,CPU模式下每个像素的iters值符合预期,但GPU模式下iters始终为0。核心代码如下:

function inlineTestPoint(initialReal, initialImag, maxIterations) {
  let currentReal = initialReal;
  let currentImag = initialImag;

  let i = 0;
  for (;i < maxIterations; i++) {
    const curRealSq = (currentReal * currentReal);
    const curImagSq = (currentImag * currentImag);
    if (curRealSq + curImagSq <= 4) {
      currentImag = (2 * currentReal * currentImag) + initialImag;
      currentReal = (curRealSq - curImagSq) + initialReal;
    } else {
      break;
    }
  }

  return i;
}

function mapRange(n, sourceMin, sourceMax, targetMin, targetMax) {
  const sourceRatio = (n - sourceMin) / (sourceMax - sourceMin);

  return (sourceRatio * (targetMax - targetMin)) + targetMin;
}

const canvasWidth = 1000;
const canvasHeight = 1000;

const gpu = new GPU({mode: "gpu"});
gpu.addFunction(mapRange, {argumentTypes: ['Float', 'Float', 'Float', 'Float', 'Float'], returnType: 'Float'});
gpu.addFunction(inlineTestPoint, {source: inlineTestPoint, argumentTypes: ['Float', 'Float', 'Float'], returnType: 'Integer'});
const kernel = gpu.createKernel(function(canvasWidth,canvasHeight) {
  const canvasX = this.thread.x;
  const canvasY = this.thread.y;
  const real = mapRange(canvasX, 0, canvasWidth, -2, 2);
  const imag = mapRange(canvasY, 0, canvasHeight, -2, 2);

  const iters = inlineTestPoint(real, imag, 200);
  this.color(iters / 50, iters / 100, iters / 200);
  //return [real, imag, iters];
})
  .setGraphical(true)
  .setLoopMaxIterations(200)
  .setOutput([canvasWidth, canvasHeight]);

kernel(canvasWidth, canvasHeight);

原因与解决方案

核心问题1:参数类型不匹配

inlineTestPoint的第三个参数maxIterations被声明为Float类型,但实际传入的是整数200。GPU的GLSL对类型匹配要求严格,浮点数与整数的比较逻辑可能导致循环未正确执行。

核心问题2:let变量声明的兼容性

GPU.js会将JavaScript函数转换为GLSL代码,而GLSL中没有let关键字,部分GPU驱动对转换后的代码兼容性不佳,导致变量初始化或循环逻辑出错。

修复步骤:

  1. 修正参数类型:将inlineTestPoint的参数类型数组中第三个元素从'Float'改为'Integer':
    gpu.addFunction(inlineTestPoint, {source: inlineTestPoint, argumentTypes: ['Float', 'Float', 'Integer'], returnType: 'Integer'});
    
  2. 替换let为var:修改inlineTestPoint内部的变量声明,确保GLSL转换正常:
    function inlineTestPoint(initialReal, initialImag, maxIterations) {
      var currentReal = initialReal;
      var currentImag = initialImag;
    
      var i = 0;
      for (;i < maxIterations; i++) {
        const curRealSq = (currentReal * currentReal);
        const curImagSq = (currentImag * currentImag);
        if (curRealSq + curImagSq <= 4) {
          currentImag = (2 * currentReal * currentImag) + initialImag;
          currentReal = (curRealSq - curImagSq) + initialReal;
        } else {
          break;
        }
      }
    
      return i;
    }
    

完成上述修改后,GPU模式下的计算结果应与CPU模式一致,正常渲染曼德博集合。


内容的提问来源于stack exchange,提问作者Carcigenicate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 19:10:32