Repository navigation
dasCUDA, dasLLAMA: the CUDA home at parity on the dense slice - #4356
Conversation
84102e4 to
d093ff4
Compare
There was a problem hiding this comment.
🔵 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
dasCUDAmodule +tests/cudasuite, its REVIEW/LEDGER/ARCHITECTURE docs, and AOT/CMake wiring. - dasLLAMA CUDA home: new
dasllama_cuda_*/dasllama_gpu_kernels_discretemodules, 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
coopmatScaleAccop andspirv_markerssplit, 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
d093ff4 to
c187c98
Compare
There was a problem hiding this comment.
🔵 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
c187c98 to
19978c5
Compare
There was a problem hiding this comment.
🔵 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
There was a problem hiding this comment.
🔵 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
19978c5 to
9fac46a
Compare
There was a problem hiding this comment.
🔵 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
9fac46a to
b6bb062
Compare
There was a problem hiding this comment.
🔵 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>
b6bb062 to
3c92f5f
Compare
There was a problem hiding this comment.
🔵 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

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 undertests/cuda.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.dasllama_gpu_kernels_discrete.dasholds the bodies Vulkan and CUDA stamp, the marker annotations live in the emitter-freespirv/spirv_markers, and the helpers the two text emitters (CUDA C, MSL) carried byte for byte sit indaslib/shader_emit_common.das.Observable behavior.
DASLLAMA_GPU=1 DASLLAMA_CUDA=1on 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=1without the ask -> the Vulkan home as before; its kernel cells, parity files and K-quant regions hold bit for bit where they held before.cuda_available()false, the CUDA ask declines by name.Where to look.
modules/dasCUDA/cuda/cuda_emit.dasis the emitter,dasllama_cuda_decode.dasthe graph-captured token step,dasllama_gpu_kernels_discrete.dasthe shared bodies, andmodules/dasLLAMA/REVIEW.das's three new gates the shape rules.Validation, claims, ledger
Validation
debug-jit, untuned, direction-grade; no record store carries a CUDA row (the bench stamps the device tiervulkan, a ledger row below).DASLLAMA_VK_SPV_DUMPovertest_vulkan_kernels.dason both trees,harness/vk_spv_diff.das, thenspirv-diff1.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_band 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_benchdebug-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.-jitwithDASLLAMA_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.tests/cuda117 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/spirv432 of 432 with spirv-val 1.4.357 on PATH and no "spirv-val not found" line,tests/msl104 of 104 andtests/metal71 of 71 (the text arms; the MSL compile arms need a Mac), the dasVulkan integration file 7 of 7,tests/dasbind16 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 ontests/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) andtests/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 thefailpkgnegative test's ownerror :lines as msbuild errors - the known local-only parse. The fulltest_aotlane (preflight --only tests-aoton the rebuilttest_aot, every_aot_generatedand 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, socuda_driver.das,das_cuda_boost.dasand the plumbing test areoptions no_aotwith 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 theSetModpolicy as it already did for%; and thecuda_intrinsicsstand-ins theIntrinfixture's CPU replay reaches link with a stub hash that differs from the runtime's whilecp_async_16beside them links - the module isoptions no_aotwith amodules/dasCUDA/LEDGER.mdrow 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.dascreate_device_storage_8_16_int_dot_coopmat2(#storage-8-16,#subgroup-pair) andcreate_compute_pipeline_full_subgroups(#subgroup-pair) - the executable-properties struct and its extension join the chain only underwith_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.dasemit_tmm2d_tg_step_deva(#tmm2d-staging),emit_tmm2d_tg_begin_devabandemit_tmm2d_tg_step_devab(#tmm2d-device-pair) - the diagnostic sink renamed (err->shader_error), the sections still describe the code,tmm2d_helper_textuntouched.doc/source/reference/embedding/advanced.rst: the;candidate-list syntax is run bytests/dasbind/test_extern_abi.das("a library candidate list binds through the first name that loads"); the example namesnvrtc64_130_0/libnvrtc.so.13are the namescuda_driver.dasloaded on the 5060 Ti box (Windows) and the RTX PRO 4500 pod (Linux).LLVM_JIT_CODEGEN_VERSION0x9E -> 0x9F: the dasbind proxy'smodifyArgumentflag now reachesbuild_interop_call, which dropsnocaptureon those arguments; a cached DLL from before keeps the old mark.ubuntu-latestrolling from 24.04 to 26.04 between master's green run and this PR's, whose clang reportswstring_convertdeprecated under-Werrorinmodules/dasUnitTest/test_handles.cpp(untouched by the PR; the deprecation is now silenced around that one use, the repo's dasAccelerate pattern).GkBiasGatespelled the gate's activation as the host globalBIAS_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.[extern]refuses to apply whereDAS_BIND_EXTERNALis off (every 32-bit host), so the fourtests/cudafiles that reachcuda_driver.dasfailed to compile there. dasCUDA is 64-bit only now: the descriptor registers thecuda/paths only where a pointer is 8 bytes (no CUDA driver exists for a 32-bit host), the engine's require isrequire ?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), andtests/.das_testgates thecudafolder as it gatesdasbind.modules/dasCUDAandtests/cudacarry the same folder policy asmodules/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
.dlimis 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
followup_general.md's row): acudabackend value is a new leg of the records rig with its own llama.cpp pairing.DISCRETE_ONE_HOME_STAMPSinREVIEW.dasand the ledger row carry them.min_blocksasymmetries, and the emitter's cross-home folds (modules/dasCUDA/LEDGER.md) stay ledgered.