Repository navigation
fix(webgpu): fall back to the CPU for Sum where the GPU reduction is wrong - #159
Merged
Merged
Conversation
…wrong The sum kernels reduce through workgroup memory shared across a workgroupBarrier. The gogpu/wgpu software backend does not implement that yet: up to wgpu v0.34.6 each invocation sees its own copy, so Sum of 4096 ones returned 16, and v0.34.7 refuses the pipeline. Software is also what New() falls back to without a usable GPU, so large sums were silently wrong on GPU-less machines (TASK-181). The backend now checks both sum kernels once, on the first Sum that would use them, against a known input spanning several workgroups. If the pipeline is refused or the result is wrong, Sum runs on the CPU. Keying on the result instead of a version or error value covers released wgpu, v0.34.7 and the fixed v0.34.8 alike. The check also catches DX12 on wgpu v0.34.4, where the kernel reads back 0. compileShader and getOrCreatePipeline gain error-returning variants that wrap the device error; the panicking ones call them with unchanged messages. TestSumAcrossWorkgroups covers sizes 1..100001 across the threshold and the workgroup boundary, f32 and i32, eager and lazy; 21 of its cases fail on the old code on the software adapter.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On the gogpu/wgpu software adapter,
Sumreturns wrong values for tensors of 1024 elements or more. The GPU reduction (globalSumShader,globalSumShaderInt32) relies on workgroup memory shared acrossworkgroupBarrier, and the software backend doesn't implement that yet:Sumwould panic instead;Software isn't only for CI.
New()falls back to it when no hardware adapter comes up, so on a GPU-less server this silently corrupts any loss or metric that sums a large tensor.Changes
Sumnow checks the sum kernels once per backend, on the firstSumthat would use them. It runs them on a known input that spans several workgroups. If the pipeline is refused or the result is wrong,Sumruns on the CPU, which is correct on every device. The check is keyed on the result rather than a wgpu version or error value, so it works with released wgpu (silently wrong), v0.34.7 (refused) and v0.34.8 (fixed, GPU path used again).compileShaderandgetOrCreatePipelineget error-returning variants (tryCompileShader,tryGetOrCreatePipeline) that wrap the device error with%w. The panicking versions call them, and their messages are unchanged.sumKernelhelper.TestSumAcrossWorkgroups: sizes 1, 1023, 1024, 1025, 4096, 100000 and 100001, f32 and i32, eager and lazy, compared exactly against the CPU sum. Against the old code on the software adapter, 21 of its cases fail.The check also caught DX12 on wgpu v0.34.4 here, where the kernel read back 0, and fell back to the CPU there too.
Test plan
TestSumAcrossWorkgroupson software (fallback taken: "globalSum kernel returned -2 for a sum of -6"), Vulkan and DX12 locally-short, where GPU tests skip)