Repository navigation
Vulkan: pick direct convolution whenever its output check passes, not by a timing race #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: sync-upstream-a77d362
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -65,6 +65,15 @@ bool sd_probe_conv_direct(ggml_backend_t backend, bool conv3d) { | |
| return false; | ||
| } | ||
| if (sd_backend_is(backend, "Vulkan")) { | ||
| // The decision must not depend on how busy the machine is. The two probe shapes run in well under a | ||
| // millisecond, so on a loaded host both paths measure the same submit overhead and the old 5% race | ||
| // flipped from run to run, changing the pixels of a fixed seed. Direct 3D convolution stays off: it is | ||
| // a tie on NVIDIA in the probe and fails its output check on RADV. Direct 2D convolution is on whenever its | ||
| // output matches im2col: measured faster and far smaller in VAE decodes on RADV (gfx1151) and NVIDIA. | ||
| if (conv3d) { | ||
| LOG_INFO("conv3d direct auto: %s -> off (Vulkan)", name); | ||
| return false; | ||
| } | ||
| std::vector<BackendProbeCase> cases; | ||
| for (const auto& shape : {std::pair<int, int>{32, 64}, {16, 128}}) { | ||
| BackendProbeCase test; | ||
|
|
@@ -74,14 +83,22 @@ bool sd_probe_conv_direct(ggml_backend_t backend, bool conv3d) { | |
| test.initialize = [conv3d](BackendProbeGraph& graph) { return initialize_conv_probe(graph, conv3d); }; | ||
| cases.push_back(std::move(test)); | ||
| } | ||
| const auto result = sd_run_backend_probe(backend, 0, cases); | ||
| // Only the output check decides, so one timed run each and no time budget a busy host could exhaust. | ||
| // No free-memory cutoff either: the probe graphs need a few MB, and the default 128 MiB floor would turn | ||
| // direct convolution off whenever another workload holds the VRAM. A device too full to allocate them | ||
| // still fails the probe (allocation failure -> off). | ||
| BackendProbeOptions options; | ||
| options.measurement_runs = 1; | ||
| options.time_budget_ms = 1e9; | ||
| options.min_free_device_bytes = 0; | ||
| const auto result = sd_run_backend_probe(backend, 0, cases, options); | ||
|
Comment on lines
+90
to
+94
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a Vulkan device has less than 128 MiB free at context initialization—for example, because another workload is using VRAM—this call still inherits Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, fixed in a2c3b97: the Vulkan conv probe now sets min_free_device_bytes = 0. The probe graphs need a few MB, so the only remaining memory dependence is a device too full to allocate them at all, which still fails the probe and selects off. The changed files compile cleanly; I could not rerun the Vulkan leg on this host this round. |
||
| if (!result.completed) { | ||
| LOG_WARN("conv%dd direct auto: %s -> off (%s)", dims, name, result.error.c_str()); | ||
| return false; | ||
| } | ||
| LOG_INFO("conv%dd direct auto: %s -> %s (probe: im2col %.3f ms, direct %.3f ms)", | ||
| dims, name, result.candidate_faster ? "on" : "off", result.reference_ms, result.candidate_ms); | ||
| return result.candidate_faster; | ||
| LOG_INFO("conv%dd direct auto: %s -> on (output check passed; probe: im2col %.3f ms, direct %.3f ms)", | ||
| dims, name, result.reference_ms, result.candidate_ms); | ||
| return true; | ||
| } | ||
| if (sd_backend_supports_conv_implicit_gemm(backend, conv3d)) { | ||
| LOG_INFO("conv%dd direct auto: %s -> on (implicit GEMM)", dims, name); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new rule contradicts
docs/performance.md:35-36, which still tells users that automatic Vulkan selection uses small benchmarks. Timing now has no effect on the 2D decision and 3D is always disabled, so users following the tuning guide receive an obsolete description ofauto; update that relevant guide together with these two documentation changes.AGENTS.md reference: AGENTS.md:L74-L76
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in a2c3b97: docs/performance.md now says Vulkan auto checks direct 2D output against im2col, does not use timing, and keeps direct 3D off.