Skip to content

dasLLAMA vulkan: record-once decode, 3B resident arming; dasSpirv f16acc coopmat - #3559

Merged
borisbat merged 5 commits into
masterfrom
bbatkin/dasllama-vk-record-once
Jul 24, 2026
Merged

dasLLAMA vulkan: record-once decode, 3B resident arming; dasSpirv f16acc coopmat#3559
borisbat merged 5 commits into
masterfrom
bbatkin/dasllama-vk-record-once

Conversation

@borisbat

Copy link
Copy Markdown
Collaborator

Three slices from the Vulkan tier / tensor-extension arc, each measured and gated:

1. Record-once resident decode — one submit per token. The token cmd records once per set_layer/set_cls epoch; a decode step is two host memcpys (x, rope row — copied in-cmd from host-visible staging), 3 uint position words per layer, and one submit. Previously every token re-recorded all 333 dispatches, refilled every meta buffer, and paid 5 submits (4 of them synchronous staging round-trips for constant scalars). Also fixes a latent stage-mask gap (the cmd's transfer copies were ordered only by compute-to-compute barriers) and groups q|k|v and gate|up into shared barrier levels (bit-exact; measured perf-neutral, kept as dependency documentation). Measured on tinyllama Q8 resident: 115.7 to 129.9 tok/s (+12%), logits bit-identical (DECHASH equal), submits/tok 5 to 1. New lifetime vk_dispatch_count / vk_submit_count instruments (all dispatches already funnel through one helper). 34/34 test_vulkan_tier synthetic suite green.

2. 3B-class dense models can arm the resident driver. The first mid-size dense model hit two artificial walls: the arena shard cap was a 2 GiB literal (the device reports maxStorageBufferRange = 4 GiB — now queried), and the auto-cap ctx floor of 4096 rejected the 3B's computed 3429-ctx fit (DASLLAMA_GPU_MIN_CTX overrides; default unchanged). Llama-3.2-3B Q8 now arms: 28 layers, dim 3072, ctx 3429, pp512 ~1157 tok/s resident (for reference: llama.cpp Vulkan coopmat-on runs 984 on the same card/model).

3. dasSpirv: f16 cooperative-matrix accumulator + coopmatConvert. coopmatAcc_f16_16x16 (one coopmat_info row — the MulAdd/Store emit arms were already structural), MulAdd/Store overloads, and coopmatConvert = componentwise OpFConvert over the tile then OpStore (llama.cpp's f16acc cast-then-store form). Golden fixture + spirv-val arm added to tests/spirv/test_coopmat.das; the full 338-test spirv suite stays byte-identical. Exercised on a 3060 Ti in the mul_mm probe arc (compiles, runs, validates bit-clean).

Context for reviewers: the f16acc rail was built while porting llama.cpp's mul_mm coopmat design; the measured conclusion of that arc is that dp4a-sdot4 remains the strongest Q8_0 GEMM on Ampere-class Vulkan (our sdot4 3.8 TFLOP/s vs llama.cpp's coopmat MUL_MAT 1.79 in isolation via test-backend-ops), so no kernel swap ships here — the emitter capability lands for the K-quant/f16-model follow-ups.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XmDdP6jrhyRkz1UaKaP6v6

borisbat and others added 3 commits July 24, 2026 04:59
The token cmd records once per set_layer/set_cls epoch; a step is two host
memcpys (x/cos, copied in-cmd), 3 uint position words per layer, one submit.
Was: full re-record (333 dispatches) + every meta refilled + 5 submits/token
(4 of them synchronous staging round-trips for constant scalars). tinyllama
Q8 resident tg 115.7 -> 129.9 tok/s (+12%), logits bit-identical, 34/34 suite.

Decode owns its ffn-meta host source so batch-rail fills between tokens can't
poison the recorded copy; the cmd's transfer copies now get real transfer<->
compute stage masks (were ordered by compute-only barriers). q|k|v and
gate|up share a barrier level (bit-exact, perf-neutral — kept as structure).
New lifetime vk_dispatch_count / vk_submit_count instruments.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmDdP6jrhyRkz1UaKaP6v6
Two walls the first mid-size dense model hit: the arena shard cap was a
2GiB literal (the device reports maxStorageBufferRange = 4GiB — ask it),
and the auto-cap ctx floor of 4096 rejected the 3B's computed 3429-ctx fit
(DASLLAMA_GPU_MIN_CTX overrides; default unchanged). Llama-3.2-3B Q8 now
arms: 28 layers, dim 3072, ctx 3429, pp512 ~1157 tok/s resident.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmDdP6jrhyRkz1UaKaP6v6
coopmatAcc_f16_16x16 (one coopmat_info row — the MulAdd/Store emit arms were
already structural) + coopmatMulAdd/coopmatStore overloads + coopmatConvert
(componentwise OpFConvert over the tile, then OpStore — llama.cpp's f16acc
cast-then-store form). Golden fixture + spirv-val arm in tests/spirv; the
338-test suite stays byte-identical. Exercised on a 3060 Ti in the mul_mm
probe arc: compiles, runs, validates bit-clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmDdP6jrhyRkz1UaKaP6v6
Copilot AI review requested due to automatic review settings July 24, 2026 12:00

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.

Pull request overview

This PR advances the Vulkan resident-driver path in dasLLAMA and extends dasSpirv cooperative-matrix support to match llama.cpp’s f16-accumulator flow, with test coverage to keep SPIR-V output validated.

Changes:

  • Refactors resident decode to record the full token command buffer once per set_layer / set_cls epoch, reducing per-token work to host memcpys + per-layer position word updates + a single submit; adds lifetime dispatch/submit counters.
  • Removes two “artificial wall” caps for mid-size dense models by querying maxStorageBufferRange and allowing an env override for the resident-driver min context floor.
  • Adds f16 accumulator coopmat support in dasSpirv (coopmatAcc_f16_16x16, emitter recognition, and coopmatConvert emission) plus a validating golden test.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/spirv/test_coopmat.das Adds a new validation case asserting the expected op mix for the f16-accumulator + widening-to-f32 store path.
tests/spirv/_spirv_common.das Introduces a new coopmat fixture kernel and *_words() provider for the f16-accumulator + convert sequence.
modules/dasSpirv/spirv/spirv_emit.das Teaches the SPIR-V emitter about coopmatAcc_f16_16x16 and emits coopmatConvert via OpFConvert + OpStore.
modules/dasSpirv/spirv/spirv_builtins.das Adds the f16 accumulator coopmat type and builtin stubs for MulAdd/Store plus coopmatConvert.
modules/dasLLAMA/dasllama/dasllama_math_vulkan.das Implements record-once resident decode, fixes/clarifies barriers, adds dispatch/submit counters, and queries device storage-buffer range cap.
modules/dasLLAMA/dasllama/dasllama_common.das Adds DASLLAMA_GPU_MIN_CTX override for the resident-driver min-ctx floor and uses it in the resident upload decision.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

vkGetPhysicalDeviceProperties(g_gpu.phys, lp)
let shard_cap = int64(lp.limits.maxStorageBufferRange)
if (qbytes > shard_cap || sbytes > shard_cap) {
to_log(LOG_WARNING, "dasLLAMA vulkan arena: fmt {fmt} needs {qbytes} quant bytes — over the device's {shard_cap}B storage-range cap\n")

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in e190f99 - the warning now reports both quant and scale byte counts.

Comment thread modules/dasLLAMA/dasllama/dasllama_math_vulkan.das Outdated
…cpy cast form

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmDdP6jrhyRkz1UaKaP6v6

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.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

modules/dasLLAMA/dasllama/dasllama_math_vulkan.das:4385

  • These memcpy calls strip const from the source pointers via addr<void? -const>(...). Since memcpy accepts const sources elsewhere in the codebase, this can be tightened to avoid unnecessary const-laundering and make the intent (read-only source) explicit.
        memcpy(g_rd.x_host.mapped, addr<void? -const>(x[0]), int(g_rd.dim * 4l))
        memcpy(g_rd.cos_host.mapped, addr<void? -const>(cossin[0]), int(g_rd.head_size * 4l))

Comment on lines +2057 to +2060
def private rdec_min_ctx : int64 {
let e = get_env_variable("DASLLAMA_GPU_MIN_CTX")
return empty(e) ? RDEC_MIN_CTX : max(int64(to_int(e)), 256l)
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 41440a1 - non-numeric (to_int -> 0) now keeps the default floor; only positive values clamp to >=256.

Comment on lines +4236 to +4260
// coopmatConvert(dst_f32_acc, src_f16_acc): componentwise OpFConvert over the tile — the
// f16-accumulate path's widening before an f32 store (llama.cpp's cast-then-coopMatStore)
if (name == "coopmatConvert") {
if (ctx.stage != ShaderStage.Compute) {
errs |> push("coopmatConvert is only valid in a compute shader")
return expr
}
if (length(expr.arguments) != 2) {
errs |> push("coopmatConvert expects (dst, src)")
return expr
}
let dst = coop_local_ptr(expr.arguments[0])
let vs = coop_local_val(expr.arguments[1])
if (dst.id == 0u || dst.pty == 0u || vs == 0u) {
errs |> push("coopmatConvert: both arguments must be coopmat locals")
return expr
}
let res = alloc_id(bm)
var cops <- [dst.pty, res, vs]
emit_n(bm, SEC_FUNCS, SpvOp.FConvert, cops)
delete cops
var sops <- [dst.id, res]
emit_n(bm, SEC_FUNCS, SpvOp.Store, sops)
delete sops
return expr

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 41440a1 - the arm now validates via coopmat_info that dst is an f32 accumulator and src an f16 accumulator of the same tile shape before emitting; golden suite re-run green.

…rt validates tile types

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmDdP6jrhyRkz1UaKaP6v6
@borisbat
borisbat merged commit 29b239e into master Jul 24, 2026
35 checks passed
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