装订大小'...'大于最大装订大小 (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的大小通常与当前设备的存储器大小有关。以下是我用wgpu:测试的一些数字

设备 maxBufferSize
M1 max MacBook Pro(64G内存( 36864MB=36GB
英特尔MacBook Pro(2018,32G内存( 3072MB=3GB
iPhone 6 Plus 256MB
iPad Mini 4 497MB
iPhone 8 plus 747MB
iPad Pro 2018 947MB
iPhone 12 Pro 1433MB

最新更新