Skip to content

docs: make gpu.md executable (#885, part 1) - #941

Merged
ocots merged 2 commits into
mainfrom
docs/gpu-executable
Sep 2, 2026
Merged

docs: make gpu.md executable (#885, part 1)#941
ocots merged 2 commits into
mainfrom
docs/gpu-executable

Conversation

@ocots

@ocots ocots commented Sep 2, 2026

Copy link
Copy Markdown
Member

Part 1 of #885. docs/src/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 now executes, on every runner, following the pattern getting-started/guided-tour.md already proves on ubuntu-latest.

Read this first: the CUDA downgrade

Adding CUDSS to the docs environment moves CUDA 6.3.1 → 6.2.0. That is forced upstream, not chosen here:

CUDSS requires
0.6.0 – 0.6.7 CUDA = 5.4.0 - 5, GPUToolbox = [0.3, 1]
0.7.0 CUDACore = 6, GPUToolbox = [0.3, 1]
0.8.0 (latest release) 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 root Project.toml already pins CUDSS = "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.

CUDSS is missing from docs/Project.toml today, which means no documentation build, CPU or GPU, could get past ExtensionError: Missing CUDSS. Part 2 of #885 (a GPU-backed docs build) was unreachable before it started.

Measured delta:

ADDED   : CUDSS 0.7.0, CUDSS_jll 0.7.1+0
REMOVED : CompilerCaching, Grisu, tree_sitter_{gcn,llvm,ptx,spirv}_jll
CHANGED : CUDA 6.3.1 → 6.2.0 (+ CUDACore, CUDATools, CUPTI, NVML, cuBLAS,
                               cuFFT, cuRAND, cuSOLVER, cuSPARSE)
          GPUToolbox 3.0.0 → 1.1.1, GPUCompiler 2.5.0 → 1.23.0
          CUDA_Runtime_jll 0.24.2 → 0.23.0, CUDA_Compiler_jll 0.6.0 → 0.4.4
          + 8 unrelated float-ups (Documenter 1.17→1.18, HTTP, SciMLBase, …)

When does the ceiling lift? Two upstream moves are needed, and only one exists: CUDSS master (0.8.1, unreleased) already widens to GPUToolbox = "0.3, 1, 2, 3", but LinearSolve 5.15.1 — including its master — still caps its weak CUDSS compat 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 prints CUDA.functional().

On a runner with no device, the explicit-mode block still prints the live configuration banner:

├─ Modeler: exa (backend = CUDACore.CUDAKernels.CUDABackend(false, false) [gpu-dependent])
└─ Solver:  madnlp (linear_solver = MadNLPGPUCUDAExt.CUDSSSolver [gpu-dependent])
▫ Exception: CUDA driver not found

The extension is armed; the page is one device away from real numbers, not one using away. That is precisely what part 2 needs.

print_level=MadNLP.ERROR became display=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 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. binder/Project.toml gets the same entry — the tour is exported as a notebook and its using lines sit outside the try.

Upstream defects this surfaced

Making the page execute exposed two display bugs in CTBase.Descriptions.complete, both visible verbatim in the built output:

  1. complete.jl:74 passes max_show=10 and similarity.jl:129 does a plain descriptions[1:10] — head truncation with no ellipsis. Our registry has 12 methods and the two :gpu ones are last, so the diagnostic hides exactly the entries this page is about. Measured: length(methods()) == 12, candidates listed == 10.
  2. complete.jl:72 computes similar_descs and 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:

  • 0 Cannot resolve @ref
  • 6 @extref — the unchanged pre-existing backlog (Plots.plot(::CTModels…) ×4, CTBase.Strategies.parameter ×2)
  • no generated .png; docs/src/assets/Manifest.toml regenerated carrying CUDSS 0.7.0

🤖 Generated with Claude Code

ocots and others added 2 commits September 2, 2026 10:49
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation run documentation Trigger the Documentation workflow on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant