繁体   English   中英

绑定大小“...”大于最大绑定大小 (134217728)

[英]Binding size '...' is larger than the maximum binding size (134217728)

我想处理 GPU 上的大量数据。我编写了简单的测试着色器,它只是使数组元素为负数。 这里是:

@group(0) @binding(0) var<storage, read> sourceArray : array<f32>;
@group(0) @binding(1) var<storage, read_write> resultArray : array<f32>;

@compute @workgroup_size(256, 1)
fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
    resultArray[global_id.x] = -sourceArray[global_id.x];
}

我想处理100000000元素。 这是我编写的 JS 代码:

const ELEMENTS_COUNT = 100000000

// Source array
const sourceArray = new Float32Array(ELEMENTS_COUNT);
for (let i = 0; i < sourceArray.length; i++) {
    sourceArray[i] = i;
}

const gpuSourceArrayBuffer = device.createBuffer({
    mappedAtCreation: true,
    size: sourceArray.byteLength,
    usage: GPUBufferUsage.STORAGE
});
const sourceArrayBuffer = gpuSourceArrayBuffer.getMappedRange();

new Float32Array(sourceArrayBuffer).set(sourceArray);
gpuSourceArrayBuffer.unmap();


// Result array
const resultArrayBufferSize = Float32Array.BYTES_PER_ELEMENT * (sourceArray.length);
const gpuResultArrayBuffer = device.createBuffer({
    size: resultArrayBufferSize,
    usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
});


// Compute shader code
const shaderModule = device.createShaderModule({
    code: shaderText
});

// Pipeline setup
const computePipeline = device.createComputePipeline({
    layout: "auto",
    compute: {
        module: shaderModule,
        entryPoint: "main"
    }
});

// Bind group
const bindGroup = device.createBindGroup({
    layout: computePipeline.getBindGroupLayout(0),
    entries: [
        {
            binding: 0,
            resource: {
                buffer: gpuSourceArrayBuffer
            }
        },
        {
            binding: 1,
            resource: {
                buffer: gpuResultArrayBuffer
            }
        }
    ]
});


// Commands submission
const commandEncoder = device.createCommandEncoder();
const passEncoder = commandEncoder.beginComputePass();
passEncoder.setPipeline(computePipeline);
passEncoder.setBindGroup(0, bindGroup);
passEncoder.dispatchWorkgroups(Math.ceil(ELEMENTS_COUNT / 256.0));
passEncoder.end();

// Get a GPU buffer for reading in an unmapped state.
const gpuReadBuffer = device.createBuffer({
    size: resultArrayBufferSize,
    usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
});

// Encode commands for copying buffer to buffer.
commandEncoder.copyBufferToBuffer(
    gpuResultArrayBuffer /* source buffer */,
    0 /* source offset */,
    gpuReadBuffer /* destination buffer */,
    0 /* destination offset */,
    resultArrayBufferSize /* size */
);

// Submit GPU commands.
const gpuCommands = commandEncoder.finish();
device.queue.submit([gpuCommands]);

// Read buffer.
await gpuReadBuffer.mapAsync(GPUMapMode.READ);
const arrayBuffer = gpuReadBuffer.getMappedRange();
console.log(new Float32Array(arrayBuffer));

我收到错误Binding size (400000000) is larger than the maximum binding size (134217728). 我该如何解决这个错误? 也许有一种方法可以为 GPU 创建一些连续的数据馈送(流),而不是将所有数据作为单个数据提供?

出现此问题是因为您创建的缓冲区的大小超过了maxBufferSize的大小。

使用device.limits.maxBufferSize查询当前设备可以支持的最大缓冲区大小。

maxBufferSize的大小通常与当前设备的memory大小有关。 下面是我用wgpu测试的一些数字:

设备 最大缓冲区大小
M1 最大 MacBook Pro(64G 内存) 36864 MB = 36 GB
英特尔 MacBook Pro(2018 年,32G 内存) 3072 MB = 3 GB
iPhone 6 Plus 256MB
iPad 迷你 4 497兆字节
iPhone 8 加 747兆字节
iPad 专业版 2018 947兆字节
iPhone 12 专业版 1433兆字节

问题未解决?试试以下方法:

绑定大小“...”大于最大绑定大小 (134217728)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2023 STACKOOM.COM