docs: make gpu.md executable (#885, part 1) - #941
Merged
Conversation
The CTSolversMadNLPGPU extension is armed by MadNLPGPU, CUDA *and* CUDSS together. CUDSS was missing from docs/Project.toml, so no documentation build -- CPU or GPU -- could get past `ExtensionError: Missing CUDSS`, and the GPU-backed docs build of #885 part 2 was unreachable before it started. Adding it pins CUDA down a generation, and that is not our choice to make: every published CUDSS caps GPUToolbox at [0.3, 1] (0.7.0 and 0.8.0 both require CUDACore = 6, GPUToolbox = [0.3, 1]), while CUDA 6.3.x pulls GPUToolbox 3.0.0. No released CUDSS works with CUDA 6.3. The docs environment therefore resolves to CUDA 6.2.0 -- exactly what the root Project.toml's `CUDSS = "0.7"` test pin already implies for the GPU test environment, so this aligns the two rather than diverging from them. Until now the docs were built on a CUDA generation the GPU CI never tests and on which the GPU stack cannot load at all. Measured delta: + CUDSS 0.7.0, CUDSS_jll 0.7.1; CUDA 6.3.1 -> 6.2.0 with its family (CUDACore, CUDATools, CUPTI, NVML, cuBLAS, cuFFT, cuRAND, cuSOLVER, cuSPARSE), GPUToolbox 3.0.0 -> 1.1.1, GPUCompiler 2.5.0 -> 1.23.0. docs/src/assets/{Project,Manifest}.toml regenerated by the build, per the standing snapshot rule. The pin is `"0.7"`, mirroring the root Project.toml: LinearSolve's weak `CUDSS` compat caps at 0.7 anyway, so 0.8.0 is unreachable in this environment regardless. binder/Project.toml gets the same entry -- the guided tour is exported as a notebook and its `using` lines sit outside the try/catch. Refs #885. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
solve/gpu.md was the only page on the site whose code never ran: 43 pages
carry `Draft = false`, it alone carried `Draft = true`. It read as accurate
prose, and nothing in the build would have caught it going stale.
It now executes 12 blocks -- 9 `@example gpu`, 3 `@repl gpu` -- following
the pattern getting-started/guided-tour.md already proves on
ubuntu-latest: load the GPU stack for real, guard the device-dependent
calls with try/catch, and print a different but still true story depending
on the machine that built the page. A note at the top says which of the two
the reader is looking at, and the first block prints CUDA.functional().
What is now executed rather than asserted:
- the `@def` problem, coordinatewise for `:exa`;
- both descriptive-mode solves and the explicit-mode one, each reporting
either real objective/iterations or the exception it really raises;
- `describe(:gpu)`, which is device-independent;
- the three "what does not work" cases, using the house exception
convention -- ADNLP{GPU}() and Ipopt{GPU}() (TypeError, the parameter is
<:CPU) and solve(ocp, :adnlp, :gpu) (AmbiguousDescription).
On a machine with no device the explicit-mode block still prints the live
configuration banner naming MadNLPGPUCUDAExt.CUDSSSolver, which is the
proof the extension is armed -- the page is one device away from real
numbers, not one `using` away.
`print_level=MadNLP.ERROR` is replaced by `display=false`: the page's whole
point is that exactly three loads arm the extension, so it must not need a
fourth to run its own example. The MadNLP option is mentioned in prose,
pointing at solve/options.md.
The guided tour gains the third load. Its prose has always promised that
the failure shown is a missing *device*, but with only MadNLPGPU and CUDA
loaded the exception was `Missing CUDSS` -- a setup mistake, not a device
one. It now prints `CUDA driver not found`. This also removes an invisible
coupling: package loading is process-global while @example modules are
per page, so with CUDSS loaded on one page and not the other, which error
the tour displayed depended on page execution order.
One reader-facing note records an upstream display bug the executed output
exposes: CTBase's AmbiguousDescription lists the first ten of the twelve
entries methods() returns, with no marker -- dropping exactly the two
`:gpu` ones -- and its "closest matches" hint is empty.
Closes part 1 of #885.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 2, 2026
Merged
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.
Part 1 of #885.
docs/src/solve/gpu.mdwas the only page on the site whose code never ran — 43 pages carryDraft = false, it alone carriedDraft = true. It now executes, on every runner, following the patterngetting-started/guided-tour.mdalready proves onubuntu-latest.Read this first: the CUDA downgrade
Adding
CUDSSto the docs environment moves CUDA 6.3.1 → 6.2.0. That is forced upstream, not chosen here:CUDA = 5.4.0 - 5,GPUToolbox = [0.3, 1]CUDACore = 6,GPUToolbox = [0.3, 1]CUDACore = 6,GPUToolbox = [0.3, 1]CUDA 6.3.x pulls
GPUToolbox 3.0.0, so no released CUDSS works with CUDA 6.3. Since the rootProject.tomlalready pinsCUDSS = "0.7"in its test target, the GPU test environment was necessarily on CUDA 6.2 all along — the docs were the odd one out, building on a generation the GPU CI never tests and on which the GPU stack cannot load at all. This aligns them.CUDSSis missing fromdocs/Project.tomltoday, which means no documentation build, CPU or GPU, could get pastExtensionError: Missing CUDSS. Part 2 of #885 (a GPU-backed docs build) was unreachable before it started.Measured delta:
When does the ceiling lift? Two upstream moves are needed, and only one exists: CUDSS
master(0.8.1, unreleased) already widens toGPUToolbox = "0.3, 1, 2, 3", but LinearSolve 5.15.1 — including itsmaster— still caps its weakCUDSScompat at"0.7". So even a released CUDSS 0.8.1 would not be selectable here until LinearSolve widens too.What the page does now
12 executed blocks — 9
@example gpu, 3@repl gpu. The problem definition, both descriptive solves, the explicit-mode solve,describe(:gpu), and the three "what does not work" cases (ADNLP{GPU}(),Ipopt{GPU}(),solve(ocp, :adnlp, :gpu)) using the house exception convention. A note at the top tells the reader which story they are looking at, and the first block printsCUDA.functional().On a runner with no device, the explicit-mode block still prints the live configuration banner:
The extension is armed; the page is one device away from real numbers, not one
usingaway. That is precisely what part 2 needs.print_level=MadNLP.ERRORbecamedisplay=false— a page whose point is that exactly three loads arm the extension must not need a fourth to run its own example.The guided tour gains the third load
Its prose has always promised the failure shown is a missing device, but with only
MadNLPGPUandCUDAloaded the exception wasMissing CUDSS— a setup mistake, not a device one. It now printsCUDA driver not found.This also removes an invisible coupling: package loading is process-global while
@examplemodules are per page, so withCUDSSloaded on one page and not the other, which error the tour displayed depended on page execution order.binder/Project.tomlgets the same entry — the tour is exported as a notebook and itsusinglines sit outside thetry.Upstream defects this surfaced
Making the page execute exposed two display bugs in
CTBase.Descriptions.complete, both visible verbatim in the built output:complete.jl:74passesmax_show=10andsimilarity.jl:129does a plaindescriptions[1:10]— head truncation with no ellipsis. Our registry has 12 methods and the two:gpuones are last, so the diagnostic hides exactly the entries this page is about. Measured:length(methods()) == 12, candidates listed== 10.complete.jl:72computessimilar_descsand uses it only to pick the wording"Try one of the closest matches:"— it is never passed to the exception, so the hint line is followed by nothing.The page carries a short note rather than pretending the list is complete. Filed separately.
Verification
Two full local builds (
julia --project=. docs/make.jl), both exit 0, identical error profile:Cannot resolve @ref@extref— the unchanged pre-existing backlog (Plots.plot(::CTModels…)×4,CTBase.Strategies.parameter×2).png;docs/src/assets/Manifest.tomlregenerated carryingCUDSS 0.7.0🤖 Generated with Claude Code