Skip to content

dasCUDA, dasLLAMA: the CUDA home at parity on the dense slice - #4356

Merged
borisbat merged 1 commit into
masterfrom
bbatkin/dascuda
Oct 23, 2026
Merged

borisbat merged 1 commit into
masterfrom
bbatkin/dascuda

Conversation

@borisbat

@borisbat borisbat commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Behavior change: a box with an NVIDIA driver and NVRTC serves dasLLAMA's dense models on the new CUDA home under DASLLAMA_CUDA=1; nothing changes without the ask.

Why. The Vulkan home left the NVIDIA cards' native path on the table: on the 5060 Ti llama.cpp's CUDA build decoded Llama-3.2-1B Q8_0 at 254 tok/s against our Vulkan home's 253, and its prefill ran under ours only where the Vulkan tiles happened to win. dasLLAMA needed a home that speaks CUDA directly, built from the kernels both discrete homes already share.

What changes.

  • modules/dasCUDA: a pure-daslang module binding the CUDA driver API and NVRTC as late externs, a CUDA C emitter over the shader lingua franca the SPIR-V and MSL emitters read, a [cuda_kernel] / [cuda_dispatch] lens, a cubin cache, and its own suite under tests/cuda.
  • dasLLAMA's CUDA home takes the GPU tier's seats under DASLLAMA_CUDA=1: the dense slice - one arena a format, the f16 and block-codec mirrors, the token step as a captured graph replayed under programmatic launches, the N-row command, the peel, the window chain and the segmented window - and a decline by name for everything outside it.
  • Every kernel the home runs stamps a template both discrete homes share: dasllama_gpu_kernels_discrete.das holds the bodies Vulkan and CUDA stamp, the marker annotations live in the emitter-free spirv/spirv_markers, and the helpers the two text emitters (CUDA C, MSL) carried byte for byte sit in daslib/shader_emit_common.das.
  • The documents follow the split: three shared companions carry the sections the shared templates cite, and the dasLLAMA gate holds the shape with a stamp census, a markers-only require rule and a shared-citation rule.

Observable behavior.

  • DASLLAMA_GPU=1 DASLLAMA_CUDA=1 on a box with the driver -> the dense llama files serve on CUDA: tg128 at parity with llama.cpp's CUDA build on the 5060 Ti and the RTX PRO 4500 (0.99 to 1.05), pp512 ahead on every row (1.02 to 1.31).
  • DASLLAMA_GPU=1 without the ask -> the Vulkan home as before; its kernel cells, parity files and K-quant regions hold bit for bit where they held before.
  • A box without the driver -> cuda_available() false, the CUDA ask declines by name.

Where to look. modules/dasCUDA/cuda/cuda_emit.das is the emitter, dasllama_cuda_decode.das the graph-captured token step, dasllama_gpu_kernels_discrete.das the shared bodies, and modules/dasLLAMA/REVIEW.das's three new gates the shape rules.

Validation, claims, ledger

Validation

  • Linux: on the RunPod RTX PRO 4500 the dasCUDA suite 79 of 79, the CUDA kernel cells 44 of 44, the CUDA llama parity file 19 of 22 with the three unstocked mints skipping, the codec and batch files 6 of 6 each, the segments file 2 of 2 with the recurrent and E-series cells skipping by design; the pod's card runs on boost (the container refuses a clock lock), so its rates carry that drift.
  • The arc's measurements are debug-jit, untuned, direction-grade; no record store carries a CUDA row (the bench stamps the device tier vulkan, a ledger row below).
  • Vulkan SPIR-V against master (DASLLAMA_VK_SPV_DUMP over test_vulkan_kernels.das on both trees, harness/vk_spv_diff.das, then spirv-diff 1.4.357 on every differing pair): master 298 stamps, branch 302; 294 in common. Of those 42 are byte-identical, 88 hold the same instructions with the helper functions emitted in another order, 14 differ by one forwarding function (the leaf's method calling the shared template's, which the driver inlines), and 150 differ in the body - the per-format cm2 and KHR tiles by the binding declaration order and one guard's branch shape (7 instructions), the decode GEMV family and the token-table gathers by the loop shape of the shared column walk (9 to 20 instructions), actf16 / actf16_b and the q8 gate + up GEMVs by the most (32 to 106). The 8 stamps only the branch holds are the per-32 formats' cm2 l and m tiles; the 4 only master holds are their cm2e tiles. Every stamp's cell holds the CPU oracle on both trees (257 of 258 each side, the one skip a device skip). One Vulkan row branch against master, the 5060 Ti at 2392 MHz locked, Llama-3.2-1B Q8_0, lcpp_bench debug-jit untuned --ngl 0, 16 threads, 3 reps, the master tree run with the branch binary under -dasroot: tg128 252.93 ± 0.31 against 247.47 ± 0.38, pp512 21360 ± 235 against 21077 ± 47; the same argmax token, the warmup logit 7.8508 against 7.8498.
  • Windows, 5060 Ti, the model-backed CUDA files under -jit with DASLLAMA_MODELS_DIR=D:/Work/llama.cpp/models: the llama parity file 22 of 22, the batch file 6 of 6, the codec file 6 of 6, the segments file 2 of 2 with the four recurrent and E-series cells skipping by design (the dense slice declines them by name). The merged master's checkpoint-capture seat (rdec_prefill_caps) panicked every one of these cells until the CUDA home installed its own handler: an empty capture list passes, a non-empty one is refused by name.
  • Windows, 5060 Ti: tests/cuda 117 of 117 (the cubins into the run's temp dir), the CUDA kernel cells 44 of 44, the Vulkan kernel cells 257 of 258 (one device skip), tests/spirv 432 of 432 with spirv-val 1.4.357 on PATH and no "spirv-val not found" line, tests/msl 104 of 104 and tests/metal 71 of 71 (the text arms; the MSL compile arms need a Mac), the dasVulkan integration file 7 of 7, tests/dasbind 16 of 16, every folder gate (REVIEW.das) exit 0, lint over the changed set 0 issues. Preflight, one full run then each red gate fixed and rerun alone: format, lint (185 files clean on the host, Linux-mirror and Darwin-mirror rails, every added line within the length limits), review-md-tests (the walker fixture now writes the discrete kernel file the gate reads), md-ascii, ast-verify (103 files), ci-das, ci-matrix, compile-sweep (779 roots), dasgen, tests-cpp (184 of 184 after the emitter hash re-pin), docs (8 of 8 gates, the digest regenerated) pass. tests-interp 15376 of 15388 and tests-jit 15278 of 15291 with no assertion failure: the reds are the per-file 60-second budget on tests/watchdog/test_watchdog.das (73 to 75 s under the lane, 52 of 54 passing alone at 72 and 81 s - the known local-only budget red) and tests/jit_tests/jit_lib.das (75 s under the lane, 7 of 7 alone at 59 s). utils-tests: every suite green (516, 157, 98, 81 and the rest); the lane reads the failpkg negative test's own error : lines as msbuild errors - the known local-only parse. The full test_aot lane (preflight --only tests-aot on the rebuilt test_aot, every _aot_generated and the module cache wiped first): PASS, 14162 rows. Its first runs found three things: the AOT emitter spells a dasbind late extern by its proxy's mangled name, so cuda_driver.das, das_cuda_boost.das and the plumbing test are options no_aot with the reason beside the option (dasOpenGL's externs and the dasbind tests already sit outside AOT), a float %= reached C++ as %= - the emitter now routes it through the SetMod policy as it already did for %; and the cuda_intrinsics stand-ins the Intrin fixture's CPU replay reaches link with a stub hash that differs from the runtime's while cp_async_16 beside them links - the module is options no_aot with a modules/dasCUDA/LEDGER.md row for the localization (the SimNode dumps side by side), since the stand-ins run only inside a CPU replay.
  • [arch] citers changed beyond comments, one verdict each: vulkan_boost.das create_device_storage_8_16_int_dot_coopmat2 (#storage-8-16, #subgroup-pair) and create_compute_pipeline_full_subgroups (#subgroup-pair) - the executable-properties struct and its extension join the chain only under with_exec_props, the 1.3 block stays at the tail, both sections still describe the code, the other citers of both anchors untouched; msl_emit.das emit_tmm2d_tg_step_deva (#tmm2d-staging), emit_tmm2d_tg_begin_devab and emit_tmm2d_tg_step_devab (#tmm2d-device-pair) - the diagnostic sink renamed (err -> shader_error), the sections still describe the code, tmm2d_helper_text untouched.
  • doc/source/reference/embedding/advanced.rst: the ; candidate-list syntax is run by tests/dasbind/test_extern_abi.das ("a library candidate list binds through the first name that loads"); the example names nvrtc64_130_0 / libnvrtc.so.13 are the names cuda_driver.das loaded on the 5060 Ti box (Windows) and the RTX PRO 4500 pod (Linux).
  • LLVM_JIT_CODEGEN_VERSION 0x9E -> 0x9F: the dasbind proxy's modifyArgument flag now reaches build_interop_call, which drops nocapture on those arguments; a cached DLL from before keeps the old mark.
  • Two reds from master moving under the branch, fixed here: the new commit-message lint (the squash commit reworded to a 72-column subject and a wrapped body), and ubuntu-latest rolling from 24.04 to 26.04 between master's green run and this PR's, whose clang reports wstring_convert deprecated under -Werror in modules/dasUnitTest/test_handles.cpp (untouched by the PR; the deprecation is now silenced around that one use, the repo's dasAccelerate pattern).
  • The Darwin core lane found one of the PR's own: the review round's dead-constant cleanup in GkBiasGate spelled the gate's activation as the host global BIAS_ACT_SILU, which the SPIR-V and CUDA lenses fold and the MSL lens refuses (a kernel body reads no host global), so every Metal-stamping file was red on macOS; the literal is back with the note master carried, the Vulkan tower cell that stamps the gate holds. The Windows Darwin-mirror lint cannot see this (no dasMetal module built here), and a lens that folds what another refuses is an emitter asymmetry worth a shared rule.
  • The Windows 32-bit lane: [extern] refuses to apply where DAS_BIND_EXTERNAL is off (every 32-bit host), so the four tests/cuda files that reach cuda_driver.das failed to compile there. dasCUDA is 64-bit only now: the descriptor registers the cuda/ paths only where a pointer is 8 bytes (no CUDA driver exists for a 32-bit host), the engine's require is require ?cuda/cuda_driver dasllama/dasllama_math_cuda (a path guard, absent where the descriptor registered nothing; proven both ways on the 64-bit box with a resolvable and an unresolvable guard), and tests/.das_test gates the cuda folder as it gates dasbind.
  • Line length: modules/dasCUDA and tests/cuda carry the same folder policy as modules/dasLLAMA (the gate off until the tree-wide wrap the ledger names), since their kernel bodies and emit fixtures are written at the engine's width.

Claims - stated, not tested

  • The CUDA home's .dlim is the Vulkan lane's: the home serves off the lane's planar families, so a Vulkan-minted image serves the CUDA home and the reverse; held by the pod runs that mapped each other's mints, not by a cell.

Not done

  • The CUDA home answers to the Vulkan home's name in the bench record and the image lane (followup_general.md's row): a cuda backend value is a new leg of the records rig with its own llama.cpp pairing.
  • Nine discrete templates have a Vulkan stamp and no CUDA stamp - the families the dense slice does not serve (MXFP4, the towers, the batched attention past 512, the PLE act) - plus four intermediates the stamp census names; DISCRETE_ONE_HOME_STAMPS in REVIEW.das and the ledger row carry them.
  • The Vulkan home's own copies of shared bodies, the per-32 cm2 decode fold, the window rope-store fold, the unmeasured s-tile and min_blocks asymmetries, and the emitter's cross-home folds (modules/dasCUDA/LEDGER.md) stay ledgered.
  • phi (head size 96) and NVFP4 open the next arc.

Copilot AI balanced review requested due to automatic review settings October 23, 2026 17:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It is a very large, cross-platform change introducing a new GPU backend whose core emitter/driver/dasLLAMA logic is largely outside the shown diffs and depends on CUDA-hardware behavior that cannot be verified here, so it requires human review.

1 open issue
What changed in this PR

This PR adds modules/dasCUDA — a pure-daslang module that binds the CUDA driver API and NVRTC as late dasbind externs, emits CUDA C from the shared shader kernel vocabulary, and adds a [cuda_kernel]/[cuda_dispatch] lens plus a cubin cache — and wires it into dasLLAMA as a "CUDA home" that takes the GPU tier's seats under DASLLAMA_CUDA=1 for the dense model slice, at parity with the Vulkan home. To support this, shader-emitter logic common to the SPIR-V, MSL and new CUDA text emitters is hoisted into daslib/shader_emit_common.das, the SPIR-V marker annotations are split into an emitter-free spirv_markers module, and a large set of dasLLAMA architecture docs are renamed to *_SHARED_* companions. Supporting engine changes: dasbind [extern] now accepts a ;-separated library candidate list and propagates modifyArgument for non-const ref args (JIT codegen version bumped), and Windows loadDynamicLibrary is reworked to route bare names straight through LoadLibraryA.

Changes:

  • New dasCUDA module + tests/cuda suite, its REVIEW/LEDGER/ARCHITECTURE docs, and AOT/CMake wiring.
  • dasLLAMA CUDA home: new dasllama_cuda_* / dasllama_gpu_kernels_discrete modules, shared GEMM/ROWS/ATTN doc split, env knobs (cuda, cuda_mmq, cuda_pdl), Vulkan tier stands down when CUDA is asked.
  • Engine: dasbind candidate-list binding + non-const-ref write-back, shared shader-emit rail, SPIR-V coopmatScaleAcc op and spirv_markers split, Windows loader bare-name path.
File Description
modules/​dasCUDA/​* New pure-daslang CUDA module: kernel annotation, intrinsics, types, builtins, descriptor, REVIEW/LEDGER gates
src/​builtin/​module_builtin_dasbind.cpp ;-separated library candidate list, modifyArgument flag for non-const ref args, null guards
src/​misc/​sysos.cpp + ARCHITECTURE.md Bare library names loaded via LoadLibraryA; path names via GetFullPathNameA+LoadLibraryExA
daslib/​shader_emit_common.das consumers (msl_*, cuda_*, spirv_*) Shared emit rail: kernel_global_name, add_typed_global, pin_reachable_never_inline
modules/​dasSpirv/​spirv/​spirv_markers.das + spirv_shader.das Marker annotations split into emitter-free module; coopmatScaleAcc builtin added
modules/​dasVulkan/​daslib/​vulkan_boost.das Pipeline-executable-properties device chain + capture flags, set_pipeline_capture
modules/​dasLLAMA/​dasllama/​* CUDA home wiring, arm_say refactor, GkPatchIm2colArgs.h removal, RDEC_AR_MAX_DIM rename, base-module method resolution
modules/​dasLLAMA/​*ARCHITECTURE*/​README/​REVIEW/​followup *_SHARED_* companion renames and citation updates
tests/​{spirv,msl,metal,cuda,dasbind,aot}/​* New fixtures/tests for coopmatScaleAcc, lazy inline, candidate lists, ref write-back, CUDA census
modules/​dasLLVM/​*, daslib/​aot_cpp.das, CMakeLists.txt JIT codegen/emitter hash bump, float %= policy routing, 8 MB Windows stack, LEDGER install glob

Review effort: Balanced

Comment thread modules/dasLLAMA/dasllama/dasllama_math_vulkan.das Outdated
Copilot AI balanced review requested due to automatic review settings October 23, 2026 17:35
@borisbat borisbat changed the title dasCUDA, dasLLAMA: the CUDA home - the dense slice at parity with the Vulkan home and llama.cpp's CUDA build on two cards dasCUDA, dasLLAMA: the CUDA home at parity on the dense slice Oct 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It adds an entire new GPU backend plus cross‑cutting dasbind/JIT/AOT and Windows loader changes whose correctness depends on hardware‑ and platform‑specific behavior that cannot be verified here, so it needs expert human review.

1 open issue

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 23, 2026 17:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces an entire new CUDA GPU backend with a text emitter (not fully shown in the diff), graph-captured decode, cross-cutting shared-emitter/marker refactors, and ABI/JIT/AOT version bumps whose correctness rests on hardware-specific validation that cannot be verified here.

1 open issue

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 23, 2026 17:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces an entire new CUDA GPU backend (driver/NVRTC bindings, a C-text emitter, cross-cutting dasLLAMA integration, and runtime/ABI changes) whose correctness depends on hardware and emitter paths that cannot be verified here, warranting final human review.

1 open issue

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 23, 2026 17:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It modifies the compiler core (dasbind, dynamic-library loading, AOT emitter) and adds a large new GPU backend whose core emitter/driver/kernel code is outside the reviewable diff, so it needs human verification.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 23, 2026 18:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces a large new GPU backend module and deep cross-cutting emitter/driver refactors whose core implementation files are outside the reviewed slice, so hardware-dependent CUDA behavior and ABI/AOT interactions require human verification.

No open issues 🎉

Review effort: Balanced

dasCUDA is a pure-daslang module: the driver API and NVRTC as dasbind late
externs, a CUDA C emitter over the shader lingua franca the SPIR-V and MSL
emitters read, a [cuda_kernel] / [cuda_dispatch] lens, a cubin cache keyed on
the compute capability, and its own suite under tests/cuda.

dasLLAMA's CUDA home takes the GPU tier's seats under DASLLAMA_CUDA=1: one
arena a format, the f16 and block-codec mirrors, the token step as a captured
graph under programmatic launches, the N-row command, the peel, the window
chain and the segmented window, and a decline by name outside the slice.
Every kernel it runs stamps a template both discrete homes share in
dasllama_gpu_kernels_discrete.das; the helpers the two text emitters carried
byte for byte sit in daslib/shader_emit_common.das; three shared companions
carry the cited sections and the dasLLAMA gate holds the shape.

Measured on the 5060 Ti and the RTX PRO 4500: tg128 at parity with llama.cpp's
CUDA build (0.99 to 1.05), pp512 ahead on every row; the Vulkan home ahead of
master on the one row measured. A dasbind late extern AOTs as its proxy's
mangled name, so the driver binding is no_aot; a float %= now takes the SetMod
policy; LLVM_JIT_CODEGEN_VERSION 0x9F.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 23, 2026 18:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It spans a brand-new CUDA runtime module, C++ library-loading/dasbind changes, a cross-cutting shader-emitter refactor, and hardware-dependent serving behavior that CI cannot validate, so final human review is warranted.

No open issues 🎉

Review effort: Balanced

@borisbat
borisbat merged commit c247033 into master Oct 23, 2026
32 checks passed
@borisbat
borisbat deleted the bbatkin/dascuda branch October 23, 2026 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants