metal: DSpark drafter working end-to-end (3 ops + 4 continuous/drafter fixes) - #2
Conversation
…oncat, markov_step) Ports the CUDA kernels dspark_capture_mean_kernel, dspark_gather_concat_kernel, and dspark_markov_step_kernel to Metal, replacing the CUDA-only stubs in ds4_metal.m. Shapes, dtypes, and the markov argmax tie-break (strict-greater scan, lowest index wins) match the CUDA originals; markov_step clamps its threadgroup to the largest power of two <= maxTotalThreadsPerThreadgroup. With these in place the drafter loads, arms, and validates (D1 gate) on a Metal build; the spec loop itself is still gated by the separate cont-prefill nonfinite-logits issue on Metal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Follow-up: we spent the evening root-causing bug 1 (cont prefill nonfinite seed logits at n >= 8 on Metal) and can narrow it considerably for you, though we have not fully killed it. Findings, all on M3 Ultra, q4 + q2 targets: Where it lives. The cont serving prefill (pos0=0) takes the What we ruled out empirically (each with the n=8/n=30 repro):
Two observations that should localize it for you:
Separate real bug found on the way (independent of the NaN): on the zero_prefix path, Happy to run any diagnostic build you want on the M3 Ultra — this box reproduces in seconds. |
Builds on the three DSpark Metal ops in this branch. Four correctness fixes on the continuous-batching + drafter path: - compressor_update_tensor: the banked emit wrote F32 pool/rms/rope output through an sizeof(float)-strided view of the F16 comp cache, corrupting one element per comp row -> 100% NaN at the first compressed-KV attention layer once n_comp crosses the boundary. Caller-scoped output_is_f16: the banked (F16-cache) caller emits into an F32 scratch then copy_f32_to_f16 into the row; every F32 caller is unchanged. - ds4_gpu_matmul_f32_tensor was GEMV-only (n_tok!=1 returned failure); the DSpark HC-mixer weight is F32 and the block runs it at n_tok=block size. Run n_tok independent GEMVs over per-row views; byte-identical for n_tok==1. - ds4_gpu_tensor_copy blits into the current batch cb and fails when none is open; the DSpark inject block ends the cb, so mtp_cont_rollback_restore_all's restore copies failed. Open a cb around the rollback only when none is open (begin_commands returns 0 when already open -> MTP path unchanged). - HC split/sinkhorn sigmoid: 0.5*tanh(0.5*z)+0.5 overflows to NaN under Metal fast-math tanh (exp-based) for large-positive z. Clamp the input to [-30,30] before the transcendental; sigmoid is saturated by +/-30 so in-range values are unchanged. See METAL_DSPARK.md for details, credits, and observed (content-dependent) acceptance. Root-cause analysis and fixes produced with AI assistance (Claude) and reviewed before submission. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bility Two CUDA-side fixes the Metal-only build could not see, plus the tier statement: - ds4_cuda.cu carries its own extern "C" signatures (deliberately no ds4_gpu.h include), so the PR's widened compressor_update(_tail)_tensor prototypes left a silent ABI mismatch: callers passed a trailing output_is_f16 the CUDA impls never declared. Mirror the parameter in both wrappers; CUDA resolves its comp-cache element tier internally, so the flag is accepted and unused there. - The rollback restore's optional command bracket is correct on Metal (begin returns 1 only when THIS call opened the cb) but poisonous on CUDA, whose begin stub always returns 1 and whose end stub is a device-wide sync + diag readback -- every cont-MTP rollback step would have gained a cudaDeviceSynchronize. New backend capability ds4_gpu_commands_scoped() (Metal 1, CUDA 0) gates optional bracketing; CUDA keeps its exact pre-PR rollback path. - README: Metal correctness on the fork's serving paths is a community-maintained tier -- gated by compile + isolated Metal kernel regressions; e2e measurements are contributors' own. Verified: Mac Metal build clean (pre-existing warnings only), ds4_test --metal-kernels OK on the merged+amended tree.
v0.5.6.1: continuation-hold session-kill fix Fast-follow on v0.5.6. After a tool turn the serial session's continuation reservation now sheds competing work only for a short seat window (DS4_CONT_HOLD_SHED_S, default 5s, honest Retry-After) instead of the full 60s grace window that could kill a long agent session after one dropped stream. Late continuations fall back to the documented 409-and-replay contract; queued hard pins unchanged. Also: Metal DSpark drafter end-to-end (community contribution, robotnursenyc, PR Entrpi#2) with two CUDA-side amendments keeping GB10 serving byte-identical; codex compaction transparency note + partial catalog workaround in ds4-on-spark. Battery: cont_registry ALL LEGS, 12k twins clean, teb 83/100/86/84 (== v0.5.6), live replay of the failing session to honest completion.
Makes the DSpark block drafter run end-to-end on Metal for DeepSeek-V4-Flash.
Two parts:
capture_mean,gather_concat,markov_step(original scope of this PR).compressor_update_tensor— the banked emit wrote F32 pool/rms/rope output through asizeof(float)-strided view of the F16 comp cache, corrupting one element per comp row → 100% NaN at the first compressed-KV attention layer oncen_compcrosses the boundary. Fixed with a caller-scopedoutput_is_f16flag (banked/F16 caller emits into an F32 scratch thencopy_f32_to_f16; F32 callers unchanged).ds4_gpu_matmul_f32_tensorwas GEMV-only (n_tok!=1→ failure); the DSpark HC-mixer weight is F32 atn_tok=block size. Now runs per-row GEMVs; byte-identical forn_tok==1.ds4_gpu_tensor_copyneeds an open batch cb; the DSpark inject block ends it, so the rollback's restore copies failed. Open a cb around the rollback only when none is open (MTP path unchanged).0.5*tanh(0.5*z)+0.5overflows to NaN under Metal fast-mathtanhfor large-positivez. Clamp input to[-30,30](saturated region → in-range values unchanged).With all applied, the continuous path serves without serial fallback and the drafter produces real, accepted drafts. Acceptance is content-dependent (~68% / ~2.4× on repetitive text down to ~13% / ~1.2× on free prose, single-run, M3 Ultra, public 2-bit DSpark drafter) — see
METAL_DSPARK.mdfor details, measurements, and credits.Builds clean on Metal. Root-cause analysis and fixes produced with AI assistance (Claude) and reviewed before submission; measurements are single-machine and should be reproduced independently.