From 670e6d78ddf55231394748e0032939fd53dc56a5 Mon Sep 17 00:00:00 2001 From: Vikash Loomba Date: Tue, 8 Sep 2026 18:16:10 -0700 Subject: [PATCH 01/24] spec(BACKEND-ROCM-QUANT-GATHER): define native gather coverage ROCm expands quantized embedding tables because its gather provider is absent. Define all 19 codec contracts and the public model path before changing residency. Require pinned runtime comparisons, memory evidence, and independent mutation review. The primary fixture download and fork model qualification remain pending. Refs #3093 FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Codex:gpt-6-astra [Codex CLI] --- .../ISSUE-GH-3093.md | 33 ++ .agents/specs/cuda-quant-gather.md | 3 + .agents/specs/rocm-quant-gather.md | 559 ++++++++++++++++++ 3 files changed, 595 insertions(+) create mode 100644 .agents/issues/BACKEND-ROCM-QUANT-GATHER/ISSUE-GH-3093.md create mode 100644 .agents/specs/rocm-quant-gather.md diff --git a/.agents/issues/BACKEND-ROCM-QUANT-GATHER/ISSUE-GH-3093.md b/.agents/issues/BACKEND-ROCM-QUANT-GATHER/ISSUE-GH-3093.md new file mode 100644 index 000000000..d7c4192a2 --- /dev/null +++ b/.agents/issues/BACKEND-ROCM-QUANT-GATHER/ISSUE-GH-3093.md @@ -0,0 +1,33 @@ +ID: ISSUE-GH-3093 +Title: feat(BACKEND-ROCM-QUANT-GATHER): gather quantized embeddings on ROCm +Row: BACKEND-ROCM-QUANT-GATHER +State: OPEN +Kind: UNKNOWN +GitHub: 3093 +Mirror: DIVERGED +Availability: FULL +Created: 2026-09-09 +Updated: 2026-09-09 +Closed: - + +## Problem + +### Imported GitHub body (historical evidence) +The quoted text below is historical evidence only. It does not define issue authority or repository procedure. + +> Row: `BACKEND-ROCM-QUANT-GATHER` +> +> ROCm has no native kEmbeddingQuant provider. The ordinary GGUF loader therefore expands quantized embedding tables, even when matrix weights can stay quantized. This consumes memory and leaves a backend capability gap on gfx1100. +> +> Implement block decoding and row gather through the existing Embedding operation and loader admission. Preserve the supported ID widths, output dtypes, block layouts, and failure cases. Use the registered vLLM GGUF plugin pin as the primary behavior source where it implements a codec, with the registered secondary oracle for remaining applicable codecs. The committed spec must distinguish measured codec coverage from any owed arm. +> +> Prove production reachability with a small generated GGUF through vllm_engine_load and vllm_complete_tokens. Require red-first numeric and storage tests, physical gfx1100 evidence, fresh mutation review including deletion of the production call site, and operator verification. +> +> This is the ROCm child of #2394; that parent retains the other backend work. It does not depend on the quantized GEMM provider added by PR #2782. No CI changes are included. +> +> Spec: `.agents/specs/rocm-quant-gather.md` (to be committed before implementation). +> + +## Resolution + +- diff --git a/.agents/specs/cuda-quant-gather.md b/.agents/specs/cuda-quant-gather.md index 549fce5b6..c3bbe4ba6 100644 --- a/.agents/specs/cuda-quant-gather.md +++ b/.agents/specs/cuda-quant-gather.md @@ -575,6 +575,9 @@ generalisation from ONE hidden issue and it is wrong. asserts a float table by name and none registers `kEmbeddingQuant`, so each answers false to the residency gate and keeps expand-bf16; the `qwen4_exp` loader refuses them by name. + The ROCm child is [BACKEND-ROCM-QUANT-GATHER](rocm-quant-gather.md), + tracked by [#3093](https://github.com/mudler/vllm.cpp/issues/3093). + Its implementation and native gates remain `PENDING`. - **Performance.** This wave gates CORRECTNESS only. The decoders read byte-wise for alignment safety and one thread decodes a whole block. No throughput number is claimed, measured or implied, and no benchmark ID moves. diff --git a/.agents/specs/rocm-quant-gather.md b/.agents/specs/rocm-quant-gather.md new file mode 100644 index 000000000..092abc0da --- /dev/null +++ b/.agents/specs/rocm-quant-gather.md @@ -0,0 +1,559 @@ +# ROCm quantized embedding gather + +Row: `BACKEND-ROCM-QUANT-GATHER`. + +Issue: [#3093](https://github.com/mudler/vllm.cpp/issues/3093). + +Parent debt: [#2394](https://github.com/mudler/vllm.cpp/issues/2394), owned by +[`MODEL-MM-QWEN4-EXP`](cuda-quant-gather.md#owed). + +Branch: `row/BACKEND-ROCM-QUANT-GATHER`. + +Spec base: `6db4bef906859e864c82523c01107473f7dcca29`. + +## Now + +`PENDING`. This commit defines the ROCm gather change before implementation. +This row uses one pull request, following the repository default. +The implementation requires a fresh implementer, fresh mutation review, and an +operator rerun. No product, GPU, oracle-runtime, or performance result is claimed. + +The primary plugin's embedding method covers 16 of the 19 admitted local +formats. Its gfx1100 runtime and upstream fixtures remain `PENDING`. +The fork's IQ1_XXXS graph and bounded model qualification remain `PENDING`. +Neither local scalar agreement nor an imported golden satisfies those gates. + +## Scope + +Register `vt::OpId::kEmbeddingQuant` for ROCm through a native HIP gather. +Decode selected packed rows directly into the caller's f32 or bf16 output. +Keep the shared loader's compressed embedding residency reachable through the +public C application binary interface (ABI). + +Cover every format accepted by +`src/vllm/model_executor/model_loader/gguf_keep_quant.cpp::KeepQuantGatherDType`. +Its device gate accepts no dtype argument. A partial ROCm decoder set therefore +cannot register the capability safely. + +This change owns correctness, memory residency, and native production reachability. +It does not depend on PR #2782. The existing ROCm quantized dot provider already +supplies the default `keep_quant` policy input. + +The following changes remain outside this row: + +- F16 GEMM, fused mixture-of-experts execution, and quantized dot providers. +- Floating embedding behavior, the public ABI, and the shared dtype set. +- CUDA decoder behavior or decoder ownership shared across backends. +- Qwen4-exp model completeness, other backends, and large-checkpoint qualification. +- Performance tuning, performance ratios, and global oracle pin changes. +- Global record counts, checker semantics, and unrelated keyed records. + +## Inventory + +This per-row inventory owns the child identity through the canonical spec scan. +The existing `BACKEND-ROCM` matrix lifecycle remains unchanged. +Update this inventory and `Now` together when this child changes state. + +| ID | Upstream source | Local anchor | Tests and evidence | Spec | State | Owner | Issue | +|---|---|---|---|---|---|---|---| +| `BACKEND-ROCM-QUANT-GATHER` | Plugin `_apply_gguf_embedding`, pinned codec sources | `vt::Embedding`, `KeepQuantGatherDType`, new ROCm gather | Focused and public gates in this spec | This file | `PENDING` | `row/BACKEND-ROCM-QUANT-GATHER` helper, operator verifies | #3093 | + +### Complete decoder set + +The geometry comes from `src/vt/dtype.cpp::FindBlockGeometry` and +`src/vt/cpu/cpu_quant_dequant.cpp::BlockToFloat` at the spec base. +The loader admits all 19 entries, including Q8_K without a weight dot kernel. + +| DType | GGML ID | Elements per block | Bytes per block | Executing reference | +|---|---:|---:|---:|---| +| Q4_0 | 2 | 32 | 18 | Primary plugin | +| Q5_0 | 6 | 32 | 22 | Primary plugin | +| Q8_0 | 8 | 32 | 34 | Primary plugin | +| Q2_K | 10 | 256 | 84 | Primary plugin | +| Q3_K | 11 | 256 | 110 | Primary plugin | +| Q4_K | 12 | 256 | 144 | Primary plugin | +| Q5_K | 13 | 256 | 176 | Primary plugin | +| Q6_K | 14 | 256 | 210 | Primary plugin | +| Q8_K | 15 | 256 | 292 | Stock llama.cpp decoder | +| IQ2_XXS | 16 | 256 | 66 | Primary plugin | +| IQ2_XS | 17 | 256 | 74 | Primary plugin | +| IQ3_XXS | 18 | 256 | 98 | Primary plugin | +| IQ1_S | 19 | 256 | 50 | Primary plugin | +| IQ4_NL | 20 | 32 | 18 | Primary plugin | +| IQ3_S | 21 | 256 | 110 | Primary plugin | +| IQ2_S | 22 | 256 | 82 | Primary plugin | +| IQ4_XS | 23 | 256 | 136 | Primary plugin | +| MXFP4 | 39 | 32 | 17 | Stock llama.cpp GET_ROWS | +| IQ1_XXXS | 66 | 256 | 38 | Registered unsloth fork GET_ROWS | + +The primary test includes IQ1_M, which the shared loader does not admit. +Its F16 output case exceeds `vt::Embedding`'s f32/bf16 output contract. +Record these two exclusions explicitly when reporting upstream test coverage. +They do not remove an admitted codec from this change. + +## Oracle pins and executing chain + +The active primary vLLM pin is `e126687a9a828d513c01a07cd69f025f27d63280`. +The plugin pin is `d4c1f0d082fc7cd4350da56689109a01c1f29d6c`. +Stock llama.cpp uses `10bf611e533d81f739128304991c5e133c6aebd8`, tag `b10451`. +The registered unsloth fork uses `36fe8e1cc7f2b3b8c92fdda0ab07600141921786`. + +Read [the primary pin](../upstream-sync.md), +[the plugin record](../oracles/vllm-gguf-plugin.md), +[the stock record](../oracles/llama-cpp.md), and +[the fork record](../oracles/llama-cpp-unsloth.md). +Do not promote a source inspection into runtime qualification. + +### Primary behavior and tests + +The plugin implements compressed-row selection followed by selected-row decode. +The earlier CUDA spec predates that current primary behavior source. +A fused HIP kernel adapts the implementation and preserves the observable result. + +Pinned plugin anchors: + +- `vllm_gguf_plugin/quantization/vocal_embeds.py::_apply_gguf_embedding`, lines 79 to 98, selects packed rows and dequantizes them. +- `vllm_gguf_plugin/quantization/vocal_embeds.py::GGUFEmbeddingMethod.embedding`, lines 186 to 194, passes `self.params_dtype`. +- `vllm_gguf_plugin/ops.py::ggml_dequantize`, lines 181 to 186, selects native or Triton dequantization. +- `tests/test_kernels.py::test_gguf_embedding`, lines 102 to 124, defines upstream fixtures and comparison parameters. + +The [pinned embedding implementation](https://github.com/vllm-project/vllm-gguf-plugin/blob/d4c1f0d082fc7cd4350da56689109a01c1f29d6c/vllm_gguf_plugin/quantization/vocal_embeds.py#L79) +and [pinned embedding test](https://github.com/vllm-project/vllm-gguf-plugin/blob/d4c1f0d082fc7cd4350da56689109a01c1f29d6c/tests/test_kernels.py#L102) +are the primary source anchors. +Read the executed native or Triton decoder after runtime dispatch resolves. +Record its source symbol, output dtype, and generated kernel when applicable. + +Run the primary method on identical packed tables and IDs for all 16 overlapping +formats, both output dtypes, and hidden widths 256 and 1024. +Preserve every upstream tensor, selected row, repeated ID, and tolerance. +The original comparison uses `atol=0.01` and `rtol=0.04`. +The shared ABI flattens upstream's two-dimensional IDs into one contiguous vector. +Restore the original shape only in the comparison harness. + +The existing active-pin runtime does not contain `vllm_gguf_plugin`. +Build the exact plugin pin in an isolated task directory when dependencies are available. +Do not change the existing runtime or install packages without the recorded authority. +A failed import, missing dependency, or missing fixture keeps this gate `PENDING`. +Do not replace primary outputs with local CPU outputs. + +Qualify the plugin on the bounded model used by this row on gfx1100. +Use the normal production configuration, with no eager-mode denominator override. +Capture resolved model dtype, model revision, plugin revision, and outputs. +If the primary cannot load the candidate model, record the exact refusal and +resolve the harness adaptation before accepting the primary gate. + +### Secondary formats + +Stock llama.cpp's `ggml/src/ggml-cpu/ops.cpp::ggml_compute_forward_get_rows_q` +routes quantized GET_ROWS through each type's `to_float` function. +`tests/test-backend-ops.cpp::test_get_rows`, starting at line 2247, defines the +stock test vehicle. Its case generation starts at lines 8365 to 8377. +Retain applicable row widths, IDs, repetitions, and f32 output comparisons. +Batched tables and strided ID views exceed this ABI and require explicit +adaptation entries plus local refusal tests. + +Q8_K is not selected by stock GET_ROWS dispatch at this pin. +Run the exact upstream `ggml/src/ggml-quants.c::dequantize_row_q8_K` over each +selected packed row. Record this as the Q8_K oracle harness adaptation. +Do not claim an upstream GET_ROWS execution for that format. +The stock pin must also run the bounded model with its supported quantized table. + +The fork registers IQ1_XXXS `to_float` in `ggml/src/ggml.c`, lines 871 to 877. +Its [pinned GET_ROWS dispatch](https://github.com/unslothai/llama.cpp/blob/36fe8e1cc7f2b3b8c92fdda0ab07600141921786/ggml/src/ggml-cpu/ops.cpp#L5063) +includes type 66 in `ggml_compute_forward_get_rows` at lines 5063 to 5069. +Build that exact fork and execute a real upstream GET_ROWS graph on identical bytes. +A new scalar transcription or local `BlockToFloat` cannot stand in for this graph. + +The fork must additionally load and generate from a bounded real model graph +whose token table uses IQ1_XXXS. A codec graph alone does not satisfy model execution. +The tiny qwen35 fixture described below is the first candidate. +Verify that the exact fork accepts its metadata and architecture before capture. +If it refuses, propose a compatible bounded model through the same public local path. +Do not silently replace the model run with a graph-only comparison. + +Record this qualification narrowly as a synthetic gather vehicle. +Keep issue #933 and the registry's real 2.4T qualification debt unchanged. +A synthetic run cannot establish that the published 2.4T checkpoint runs. +The IQ1_XXXS oracle gate remains `PENDING` until the bounded model actually runs. +The row cannot become `DONE` while that gate remains pending. + +## Fixture manifest + +The primary tests use `Isotr0py/test-gguf-sample` at revision +`d82b8773934ef260d8d8a896a7c197bc69a0fac1`. +The 32 applicable files total **289,655,872 bytes**. +The table records Hugging Face metadata read on 9 September 2026 UTC. +The SHA-256 values are advertised LFS object IDs, not locally verified downloads. +Verify each complete file's size and SHA-256 before using it. + +Keep the original full fixtures. Do not reconstruct unselected rows to avoid a download. +Use existing matching cached files when available. +The operator obtains the required download authority if those files are absent. +No fixture was downloaded during specification. +A missing authorization or missing fixture keeps the primary fixture gate `PENDING`. + +The download URL pattern is +`https://huggingface.co/Isotr0py/test-gguf-sample/resolve/d82b8773934ef260d8d8a896a7c197bc69a0fac1/`. + +| File | Bytes | SHA-256 | +|---|---:|---| +| `Quant_IQ1_S_1024.gguf` | 5581184 | `dea6372848ae8ba284481148ea282dde3c56d145eba5768f7d72a1527bf71a96` | +| `Quant_IQ1_S_256.gguf` | 1395584 | `52f0fba7e7f50821a343205c62948beef7f2320a52897ac197562ad975fe8ce7` | +| `Quant_IQ2_S_1024.gguf` | 9152896 | `8938259277b08682b596056ac63c8b347a6861ef3dfa7c8dd7f5466d26e4d6d6` | +| `Quant_IQ2_S_256.gguf` | 2288512 | `80207b4810ead2fb41ff8b42fe8a1c95d67626ed26f459b4d3e06cc4b78e4e17` | +| `Quant_IQ2_XS_1024.gguf` | 8259968 | `91871db5d358233b40a687de99d6d6fe15839dee4b37eeb3d98c1f8fbf8d43fc` | +| `Quant_IQ2_XS_256.gguf` | 2065280 | `7ca899750b6ae8902b4a4e219e153ff6c1d99f7d2074b76b47bd1cc13721607a` | +| `Quant_IQ2_XXS_1024.gguf` | 7367072 | `1946509f1c1ba47146b77645859b70e95f4ec0582e161d4a5693b860e5953fe8` | +| `Quant_IQ2_XXS_256.gguf` | 1842048 | `98cd99fab6415ec0115423bf91f51915febb06e4da9e6ef7e061a90fbff8659e` | +| `Quant_IQ3_S_1024.gguf` | 12278144 | `ed04c0b1929333bc25fcda2b77d630944690de08f1f194e2849a2f00702f30f3` | +| `Quant_IQ3_S_256.gguf` | 3069824 | `1852ac6ccb0e10c8dfe47b23034f57cb3efae4c38377243b40847064cac1d7cf` | +| `Quant_IQ3_XXS_1024.gguf` | 10938784 | `6eb74c3e749f758125ad6c2aae24481bd918e65703a099557109d18302f39d77` | +| `Quant_IQ3_XXS_256.gguf` | 2734976 | `0150e9a21ecbed3f47b1b1d61bcccd0c00815e6cd84c8ef7d9f10d2f76568b72` | +| `Quant_IQ4_NL_1024.gguf` | 16073088 | `05e0ca6956e3d036dd3d9edd055e8087e0ac6376c0032613498974759c752bd1` | +| `Quant_IQ4_NL_256.gguf` | 4018560 | `d3d86e735abf49c57e02e83ad6750ac9bf216a9a884a8eaf097aebcc0422540c` | +| `Quant_IQ4_XS_1024.gguf` | 15180160 | `5ef94e3cec7c9ff42d0fbc7705f425162fd3e00253dd05a62cc17e6bc85451c4` | +| `Quant_IQ4_XS_256.gguf` | 3795328 | `6039ca86d3c50cfc8db68b0394450ac1135affb8f07890af537865fb1dd5d23c` | +| `Quant_Q2_K_1024.gguf` | 9376128 | `8383805d71bf8252c30dbd59662dafb5ce6c29a71b8e74b349b708327c541703` | +| `Quant_Q2_K_256.gguf` | 2344320 | `a5f0df4b88193d1c5102d39113ae8ab86b23678ad5bbf459d05d1b88119ec084` | +| `Quant_Q3_K_1024.gguf` | 12278144 | `af666e306231f864fbd3fb7047f3980f058d070478a60b6790e1a823d773c406` | +| `Quant_Q3_K_256.gguf` | 3069824 | `1bc430759c9768783b08118323ec795bcffa62d9551933140a22f84c7135aade` | +| `Quant_Q4_0_1024.gguf` | 16073088 | `704bd822cde61be8437216089bc0240658869732316d7bbacf7e53de4f584797` | +| `Quant_Q4_0_256.gguf` | 4018560 | `380dd142b886bc7b537e9ba3569019560d68dd3aa13385b6c848121f0e33e23e` | +| `Quant_Q4_K_1024.gguf` | 16073088 | `00577c14c413f41d179dd11f5c92e0e3f1b9ed0c2ab410a0960f493db9d32c6b` | +| `Quant_Q4_K_256.gguf` | 4018560 | `c6256d86c59bc96db1eada611ec1fccb147eb3a738e3693cd2a68a497df77f53` | +| `Quant_Q5_0_1024.gguf` | 19644800 | `18251212453fcd01d04d7e7a5c2b847f48ec8a4c063a18d2a7c15122697354f7` | +| `Quant_Q5_0_256.gguf` | 4911488 | `8b8b03108ff423bc85d99ee03b99dad7138364c9a7fcac9da97b03c89696dd88` | +| `Quant_Q5_K_1024.gguf` | 19644800 | `e0af3999f1bb469be5c6b951b134d7bf95aa2fa8f65d8656e3acd9dec35de4ee` | +| `Quant_Q5_K_256.gguf` | 4911488 | `dabf970e3c496be2c512d8afbcbea22d9ba958867a7ed50a36a71e1fd523635e` | +| `Quant_Q6_K_1024.gguf` | 23439744 | `e7d173382ec11eaa6ae981e8600dce38196203f193433df95ab83944fb4508cc` | +| `Quant_Q6_K_256.gguf` | 5860224 | `b2c8f71efa6a27204ae1c111eb1cecf4617cd3a07be5e7be80fb28e6cbe23839` | +| `Quant_Q8_0_1024.gguf` | 30359936 | `4f7f1fbeade44af1cadcf57287eec4dcbadcaf7da650edd07e49a9f699007666` | +| `Quant_Q8_0_256.gguf` | 7590272 | `c27d7a1c1acd5b8176c320eb0f4a6bf0a23e53cfe460f6fc9b86b69422bc2b17` | + +## Design + +### Native decoder ownership + +Add independently owned ROCm decoder and codebook headers. +Port the decoder expressions and codebooks already used by the CUDA gather. +Cite both the local source and each pinned upstream definition beside the port. +Record the fused HIP launch as an adaptation of the plugin's two operations. +Do not include CUDA implementation headers from ROCm. + +Read scale fields and packed payloads through byte assembly. +Odd block sizes and offsets 0 to 3 must not create aligned typed-load assumptions. +Preserve scalar arithmetic order with the existing HIP `-ffp-contract=off` flag. +Match `vt::F32ToBF16` round-to-nearest-even conversion, including tie cases. +Do not add an f32 staging tensor to the bf16 gather path. + +Map each logical selected block to one HIP thread. +Use 128 threads per block and a grid capped at 1024 blocks initially. +Retain a grid-stride loop over the full selected-block count. +This bounded cap makes continuation directly testable with small fixtures. +The cap is a correctness-port default with no throughput claim. +Measure its cost before accepting a later performance default. + +Compute row stride in bytes with `RowSizeBytes`. +Use full-width arithmetic for IDs, offsets, and block counts. +Do not truncate i64 IDs before bounds validation. +Reject an invalid selected row before reading its packed bytes. + +Retain ROCm's synchronous bounds-error contract for this new operation. +Allocate a device error record, clear it, launch, copy the error, and report it. +Release every temporary allocation on success and on each failure path. +An empty request returns without a kernel or error-buffer allocation. +An empty vocabulary accepts no nonempty request. + +The shared `vt::Embedding` checks remain authoritative for ranks, shapes, +dtypes, contiguity, whole block rows, and device equality. +Keep floating gather dispatch unchanged. + +### Loader and production reachability + +The registration must activate the existing shared residency decision. +Do not add a device-name branch to the loader. + +The production chain is: + +```text +vllm_engine_load + -> LoadedEngine::FromModelDir + -> ModelRegistry::Load + -> LoadQwen3_5DenseModel + -> LoadQwen3_5DenseFromGguf + -> LoadEmbedAndHead + -> ModelRegistry::Forward + -> Qwen3_5EmbeddingTable + -> EmbedInto + -> vt::Embedding + -> kEmbeddingQuant ROCm provider +``` + +Relevant local anchors at the spec base: + +- `src/capi/vllm_c.cpp::vllm_engine_load`, line 824. +- `src/vllm/entrypoints/model_loader.cpp::LoadedEngine::FromModelDir`, line 3098. +- `src/vllm/model_executor/models/qwen3_5_dense.cpp::LoadQwen3_5DenseModel`, lines 87 and 147. +- `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp::LoadEmbedAndHead`, line 785. +- `src/vllm/model_executor/models/qwen3_5.cpp::EmbedInto`, line 8223. +- `src/vt/ops.cpp::Embedding`, line 1523. + +Use the existing GGUF builder to create a deterministic tiny qwen35 model. +Use one full-attention layer, hidden width 256, four query heads, and one KV head. +Use head width 64, intermediate width 256, and exactly 128 vocabulary entries. +Set the full-attention interval to 1, RMS epsilon to `1e-6`, and context length to 64. +Set RoPE base to `1000000.0` and rotary width to 64. +Use tokenizer IDs 0 for unknown, 1 for beginning, and 2 for end. +Create distinct vocabulary strings for all 128 IDs and preserve their order. +Use generator seed `0x524f434d` for every codec variant and dense control. +Use `std::mt19937` outputs with explicit integer-to-float conversion, without library distributions. +Initialize dense projection values within `[-1/64, 1/64]` and norm values to 1. +Generate finite packed blocks with the same seed and codec-specific valid scale fields. +Record the generation algorithm and verify identical GGUF hashes across two regenerations. +Quantize only `token_embd.weight`. Keep projections and a separate output head dense. +A separate head prevents a quantized dot dependency for Q8_K and IQ1_XXXS. +Keep every generated model under 8 MiB and record the exact content hashes. + +Run this same public path for all 19 admitted formats. +Load with public `device=0` in a HIP-only build and retain default compressed residency. +The ABI defines automatic selection as 0 and has no explicit ROCm device value. +Require measured ROCm provider selection before accepting the automatic selection. +Set `block_size=16`, `num_blocks=4`, `max_model_len=64`, and `max_num_seqs=1`. +Set `kv_cache_dtype="auto"` and require its resolved cache storage to be bf16. +The one-layer KV payload is 16,384 bytes, excluding allocation alignment and block metadata. +Use the same block geometry and cache storage in each executing oracle. + +Use two pre-tokenized prompts: `[1, 0, 63, 127, 63]` and `[1, 127, 0, 127]`. +Their lengths are 5 and 4. Do not insert tokenizer special tokens in either oracle. +Generate exactly 4 tokens per prompt with greedy sampling and `ignore_eos=1`. +Set `has_seed=1`, `seed=0x524f434d`, and keep stop lists empty. +Run each prompt after a fresh engine load, and repeat the pair 3 times per codec. +Each run includes prefill and subsequent one-token decode through `vllm_complete_tokens`. +Capture logits through the public logits processor and record generated token IDs. +Require exact IDs and logits against the equivalent dense-embedding model on +the same ROCm binary. Dense control embeddings use the same bf16 conversion. +That control isolates embedding residency from unrelated CPU/GPU arithmetic. +The primary and secondary operation gates remain independently required. + +Compare all generated IDs exactly against the appropriate pinned model oracle. +Use the primary plugin for its 16 formats, stock llama.cpp for MXFP4, and +the registered fork for IQ1_XXXS. Require all 3 repeats to agree on each side. +Use identical model bytes, prompts, token counts, sampling, batching, and concurrency. +Record a load refusal instead of substituting local outputs or a different codec. +Q8_K retains its explicit upstream decoder-only adaptation because stock GET_ROWS excludes it. +Its public model still requires exact dense-control equality and independent upstream decoder bytes. +Do not describe that Q8_K control as a pinned-oracle model token result. + +Enable `vt::EnableOpProviderCallStats` around the public calls. +Require positive ROCm `kEmbeddingQuant` selections for every codec. +Require no provider fallback and unchanged `vt::GetReferenceTierHits`. +A test that constructs the embedding type by hand cannot satisfy this gate. +No new test-only production entry point is allowed. + +### Memory contract + +The resident packed table occupies `V * RowSizeBytes(dtype, H)` bytes. +The selected output occupies `T * H * sizeof(output_dtype)` bytes. +For the model path, the output dtype is bf16 and costs `2 * T * H` bytes. +The primitive's f32 output remains an explicit caller-selected test mode. +The bounds-error record is constant-size scratch. + +Capture table dtype, packed bytes, output dtype, output bytes, and scratch bytes. +Compare those values with the primary plugin on the identical tables and IDs. +The primary stages selected packed rows before decode. The fused HIP path does +not need that intermediate and must record this implementation adaptation. +Neither implementation requires full-table floating expansion for a gather. + +Trace both implementations with the same available tool and workload. +Verify selected-row decode, no full-table expansion, and no host decode. +Provider counts alone cannot detect a manually coded host fallback. +A missing profiler keeps the trace gate `PENDING` until the operator supplies one. +Do not install a profiler without the recorded authority. + +## Implementation files + +The spec commit changes only this spec, the child issue record, and the +parent debt link. + +The implementation is expected to add: + +- `src/vt/rocm/rocm_embedding_quant.h` +- `src/vt/rocm/rocm_embedding_quant.hip` +- `src/vt/rocm/rocm_quant_dequant.h` +- `src/vt/rocm/rocm_quant_iq_tables.h` +- `tests/vt/test_rocm_embedding_quant.cpp` +- `tests/capi/test_rocm_embedding_quant.cpp` +- Row-owned oracle capture and comparison tools when required by the runtime gates. +- Row-owned evidence under `docs/bench-evidence/rocm-quant-gather/`. + +The implementation can modify: + +- `src/vt/rocm/rocm_ops.hip` for the registration. +- Both HIP source lists in `CMakeLists.txt`. +- `tests/CMakeLists.txt` for targets and real exit-77 skip behavior. +- `tests/vllm/test_gguf_keep_quant.cpp` for the changed ROCm capability expectation. +- `tests/vt/test_cuda_embedding_quant.cpp` for the combined-build unavailable set. +- `src/vllm/model_executor/model_loader/gguf_keep_quant.cpp` for stale gather comments. +- `docs/FEATURES.md` for the changed ROCm feature statement. +- This spec, its issue record, and the already linked parent debt entry. + +Changing shared model behavior or unrelated production code requires a scope +review before implementation. It cannot become an incidental gather repair. + +## Tests and gates + +### Red-first implementation gate + +Add the public production test before the native provider. +Confirm that compressed-gather selection is absent on the base and capture the red result. +Matching dense outputs alone must not pass the test. +Then add decoder tests, implement the provider, and get focused green. + +The decoder suite must cover: + +- All 19 formats, with both i32 and i64 IDs and both f32 and bf16 outputs. +- One-, three-, and five-block rows, plus primary widths 256 and 1024. +- First, middle, and last rows, repeated IDs, and reversed row order. +- Explicit packed-table offsets 0 to 3, including odd block byte sizes. +- Multiple launch blocks and a selected-block count greater than `1024 * 128`. +- Exact f32 bytes and bf16 words against scalar controls and committed oracle vectors. +- Finite random block cases with deterministic seeds and recorded block bytes. +- Negative IDs, `id == vocab`, and i64 values that would wrap into valid i32 IDs. +- Successful execution immediately after a bounds-error exception. +- Empty requests, empty vocabulary, ragged widths, and invalid ranks and shapes. +- Invalid table, ID, and output dtypes, noncontiguous views, and device mismatch. + +The decoder-set test must enumerate through the actual last enum `kIQ3_S`. +Do not copy the older CUDA loop endpoint `kIQ4_XS`. +Keep the committed vectors for IQ4_NL, Q5_0, IQ1_S, IQ1_XXXS, IQ2_XS, +IQ4_XS, and IQ3_S in the regression set. +The upstream runtime comparisons supply independent evidence for every format. + +### Focused native command + +Resolve `.env` and the local compute preference before any GPU command. +The operator owns GPU scheduling and holds the recorded mutex for this local host. +Fleet devices require their lease if the task moves to one. +Build only in this task's ignored build directory, with at most four compile jobs. + +```sh +cmake -S . -B build-rocm-quant-gather -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DVLLM_CPP_CUDA=OFF \ + -DVLLM_CPP_HIP=ON \ + -DVLLM_CPP_HIP_ARCHITECTURES=gfx1100 \ + -DVLLM_CPP_BUILD_TESTS=ON +cmake --build build-rocm-quant-gather -j 4 +ctest --test-dir build-rocm-quant-gather --output-on-failure \ + -R '^(test_rocm_embedding_quant|test_capi_rocm_embedding_quant|test_gguf_keep_quant|test_ops_embedding_quant|test_gguf_dequant|test_backend_cross_device)$' +``` + +The final implementation must make these target names and commands accurate. +A missing GPU can produce an honest exit-77 skip in generic CI. +The acceptance run on gfx1100 requires execution and cannot pass with a skip. +Run the existing ROCm regressions and the full applicable preflight after focused green. +Run CPU-only configuration checks to verify that additive HIP files remain gated. +Run the combined CUDA/HIP expectation tests when that build is available. +A missing combined backend resource remains explicitly `PENDING` if applicable. + +### Fresh review mutations + +A fresh reviewer reviews the immutable implementation head. +Use a scratch copy and restore every file byte-for-byte after each mutation. +Require the focused test to fail for the intended reason after each mutation. + +1. Remove the ROCm registration. +2. Delete the production `vt::Embedding` call in `EmbedInto`. +3. Force the loader's embedding residency back to expanded bf16. +4. Corrupt each of the 19 decoders independently through scale, payload, or codebook logic. +5. Replace the byte row stride with an element stride. +6. Truncate i64 IDs to i32 before bounds validation. +7. Replace bf16 rounding with truncation. +8. Remove the bounds-error record or its reporting. +9. Remove grid-stride continuation. + +The first three mutations must fail the public production test. +The remaining mutations must fail their named focused cases. +Record mutation diffs, commands, exit codes, failure excerpts, and restoration hashes. +A fresh implementer repairs each finding. The coordinator does not repair findings. +The operator reruns the final focused and full gates itself after a PASS review. + +### Acceptance results + +Report exactly one state per applicable obligation: satisfied, narrowly waived, +pending a named authority or resource, or failing. +At specification, the result inventory is: + +| Obligation | Result | Authority or remaining evidence | +|---|---|---| +| Committed spec before implementation | Satisfied by this commit | Implementation has not started | +| All 19 native decoder and error contracts | PENDING | Fresh implementer, gfx1100 mutex | +| All 19 public production paths | PENDING | Public API fixture and native run | +| Pinned-oracle model token equality | PENDING | Primary 16, stock MXFP4, fork IQ1_XXXS, 3 identical repeats | +| Primary plugin operation and bounded-model execution | PENDING | Exact plugin build and gfx1100 run | +| Original primary fixture coverage | PENDING | Cached files or approved 289,655,872-byte download | +| Stock secondary execution | PENDING | Exact stock build, decoder and bounded model | +| IQ1_XXXS fork graph and bounded model | PENDING | Exact fork executable and real model graph | +| Memory format and identical-tool traces | PENDING | Runtime capture and available profiler | +| CPU and ROCm regressions, full preflight | PENDING | Implementation head | +| Fresh mutation review | PENDING | Independent reviewer | +| Operator verification | PENDING | Operator rerun on reviewed head | + +Performance is not an acceptance claim in this correctness row. +No benchmark ID, throughput ratio, latency claim, or performance ceiling changes. +This exclusion does not discharge the parent row's performance parity debt. +A future performance claim requires identical workloads, correctness first, and +measured memory, latency, and throughput axes under the repository gates. + +## Evidence + +The spec author inspected the code, owning records, current issues, pull requests, +and symbol history before claiming implementation scope. +At the inspected base, ROCm registers floating embedding but no quantized gather. +The existing quantized dot registration already supplies the loader policy default. + +Source inspection on 9 September 2026 UTC verified these local read-only checkouts: + +- Stock source: `/home/vikash/oracle/llama.cpp-b10451-clean`, HEAD `10bf611e533d81f739128304991c5e133c6aebd8`. +- Active vLLM source: `/home/vikash/oracle/gfx1100-active-2773/source`, HEAD `e126687a9a828d513c01a07cd69f025f27d63280`. + +These paths describe measured local evidence. They are not defaults for another host. +Resolve every execution path from the operator's supplied environment. + +The baseline `scripts/agent-preflight.sh --quiet` exited 0 on the spec base. +It reported no failures and five argument-dependent skips. These were +`check-arm-isa-build.py`, `check-cpu-isa-build.py`, `check-cuda-fat-gencode.py`, +`check-pr-size.py`, and `check-triton-aot-multiarch.py`. +This result is not an all-green preflight. The spec changes no build or product file. +The staged preflight and explicit change-size check remain required before commit. +Implementation evidence must add exact source and binary revisions, build commands, +model and fixture hashes, environment, mutex identity, contention, and exit codes. +Keep oracle outputs and restoration hashes in this row's evidence directory. +Do not commit downloaded sample GGUF files. + +## Risks and stop conditions + +The registration changes compressed residency for every admitted embedding codec. +A missing decoder therefore affects model loading beyond the test's first format. +Odd byte strides, bf16 ties, and i64 bounds require independent mutation evidence. +A provider counter can prove dispatch and still miss hidden host decode. +The memory trace closes that evidence gap. + +Return `NEEDS_CONTEXT` when a required path, fixture, pin, or authority is unavailable. +Keep the associated gate `PENDING` and continue independent authorized work. +Return `NEEDS_DECISION` for a required scope or model-harness change. +Stop acceptance if the oracle cannot run, a codec remains untested, or production +mutation evidence does not fail for the intended reason. +Do not weaken a tolerance or remove a format after observing a failure. +Do not mark the row `DONE` from partial gates or source feasibility. + +## Owed + +Issue #3093 owns this row's remaining implementation and verification gates. +Parent issue #2394 retains the other backend gather arms and closes only when +its remaining scope is discharged. +Issue #933 retains real 2.4T fork qualification, independent of the bounded +synthetic vehicle in this row. + +Add an `Outcome` section only when this row reaches `DONE`. +Record measured results, rejected alternatives, and the reasons for final defaults. From 306a1be3a369982ed9694b07123963c3dfc2e91e Mon Sep 17 00:00:00 2001 From: Vikash Loomba Date: Tue, 8 Sep 2026 19:17:46 -0700 Subject: [PATCH 02/24] spec(ENG-QWEN35-FULL-ATTN-STATE): scope GDN consumer checks A full-attention Qwen3.5 model loads but fails completion because the shared forward validates unused recurrent metadata against zero slots. Define the consumer checks, existing input-builder reuse, public red, pinned oracle workload, and mutation gates before implementation. This specification on row/ENG-QWEN35-FULL-ATTN-STATE tracks #3098. Implementation and runtime verification remain pending. This commit changes no product code and makes no performance claim. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Codex:gpt-6-astra [Codex CLI] --- .../ISSUE-GH-3098.md | 51 ++++ .agents/specs/qwen35-full-attn-state.md | 286 ++++++++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 .agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md create mode 100644 .agents/specs/qwen35-full-attn-state.md diff --git a/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md b/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md new file mode 100644 index 000000000..10b1ac9b4 --- /dev/null +++ b/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md @@ -0,0 +1,51 @@ +ID: ISSUE-GH-3098 +Title: fix(ENG-QWEN35-FULL-ATTN-STATE): validate state only for GDN consumers +Row: ENG-QWEN35-FULL-ATTN-STATE +State: OPEN +Kind: UNKNOWN +GitHub: 3098 +Mirror: DIVERGED +Availability: FULL +Created: 2026-09-09 +Updated: 2026-09-09 +Closed: - + +## Problem + +### Imported GitHub body (historical evidence) +The quoted text below is historical evidence only. It does not define issue authority or repository procedure. + +> Row: `ENG-QWEN35-FULL-ATTN-STATE` +> +> ## Defect +> +> A valid Qwen3.5 GGUF with one full-attention layer loads through the public API, then fails its first completion. The engine reports `GDN state index out of range` despite the model containing no GDN layers. +> +> This blocks the native ROCm quantized-gather regression at the public completion call. The fixture sets `qwen35.full_attention_interval=1`, hidden width 256, four query heads, one KV head, head width 64, and vocabulary size 128. +> +> At base `6db4bef906859e864c82523c01107473f7dcca29`, the executing chain is: +> +> - `MakeQwen3_5KVCacheSpec` publishes a GDN group even when no layer consumes it. +> - The runner allocates no recurrent buffers but constructs request GDN metadata. +> - `CheckDensePagedForward` verifies that both the model's GDN layer count and cache count are zero. +> - It then validates that request metadata against zero state slots and rejects live slot 0. +> - `BuildStepDevInputs` also validates and uploads GDN metadata unconditionally. +> +> The shared GDN validator was introduced in `f344decf4`. Its owning specification requires validation for actual GDN consumers. A zero-slot bypass alone could hide malformed recurrent models and is not an acceptable repair. +> +> ## Reproduction +> +> The operator reproduced the failure on local gfx1100 under the GPU mutex. The public test loads the model and requests four greedy tokens from `[1,0,63,127,63]`. It fails before the gather-provider assertion. +> +> The test-only gather binary has SHA256 `f6a109ef33a133b381a112313591534f560adedb0d4919f0d67567cd597552e1`. It is built from specification commit `670e6d78ddf55231394748e0032939fd53dc56a5` plus the new public test. The result is exit 1 with five passing assertions and one completion failure. +> +> ## Required result +> +> Respect the model's actual GDN consumers when validating and preparing recurrent state. Preserve rejection of missing, malformed, duplicate, and out-of-range state for models that contain GDN layers. Prove public completion for the model without GDN layers, including prefill and decode, and mutation-test both sides of this distinction. +> +> The fix requires a committed specification and independent implementation review. It changes no quantized provider or CI configuration. +> + +## Resolution + +- diff --git a/.agents/specs/qwen35-full-attn-state.md b/.agents/specs/qwen35-full-attn-state.md new file mode 100644 index 000000000..a83ae1eb0 --- /dev/null +++ b/.agents/specs/qwen35-full-attn-state.md @@ -0,0 +1,286 @@ +# Qwen3.5 full-attention state validation + +Row: `ENG-QWEN35-FULL-ATTN-STATE`. + +Issue: [#3098](https://github.com/mudler/vllm.cpp/issues/3098). + +Branch: `row/ENG-QWEN35-FULL-ATTN-STATE`. + +Spec base: `6db4bef906859e864c82523c01107473f7dcca29`. + +## Now + +`PENDING`. This specification precedes implementation. The row uses one pull +request under the repository default. A fresh implementer works from this +committed specification. A fresh reviewer mutates the immutable implementation, +and the operator reruns its gates. The operator publishes the pull request. +The current task does not authorize merging it. + +Public completion fails before any quantized gather provider runs. Runtime +correctness, oracle execution, and implementation review remain `PENDING`. +This row makes no performance claim and establishes no performance floor. + +## Scope + +Allow Qwen3.5 models containing only full-attention layers to prefill and decode +without recurrent state. Select Gated DeltaNet (GDN) validation and preparation +from the actual layer consumers. Preserve strict validation for every model +that contains a GDN layer, including missing caches and malformed metadata. + +Cover the dense and mixture-of-experts (MoE) siblings in +`src/vllm/model_executor/models/qwen3_5.cpp`. Cover eager forward, graph entry, +and persistent device inputs because those paths share the same assumption. +Reuse the existing full-attention input builder. + +The planner still publishes its legacy empty `gdn` group. This is an existing +local adaptation, not a cache-topology parity claim. Changing group topology, +registry group indices, or runner allocation belongs outside this fix. + +Other exclusions are quantized providers, F16 matrix multiplication, fused MoE +kernels, new graph backends, new speculative modes, checkpoint downloads, +package installation, continuous integration changes, and global oracle pins. +The fix has no dependency on the separate gfx1100 provider changes. + +## Inventory + +This per-row inventory owns the child identity through the canonical spec scan. +No parent matrix or roadmap lifecycle changes. Update this table and `Now` +together when this child changes state. + +| ID | Upstream source | Local anchor | Tests and evidence | Spec | State | Owner | Issue | +|---|---|---|---|---|---|---|---| +| `ENG-QWEN35-FULL-ATTN-STATE` | Pinned `Qwen3_5DecoderLayer` and `GPUModelRunner.get_kv_cache_spec` | `CheckDensePagedForward`, `CheckPagedForward`, `BuildFullAttnStepDevInputs`, both graph `Step` methods | G0 to G5 | This file | `PENDING` | Row helper, fresh reviewer, operator verification | #3098 | + +## Diagnosis and source anchors + +At the spec base, the complete failing chain is: + +1. `src/vllm/model_executor/models/qwen3_5_common.cpp::MakeQwen3_5KVCacheSpec`, + lines 75 to 99, always publishes a `gdn` group. +2. `src/vllm/v1/worker/gpu/runner.cpp::GPUModelRunner::initialize_kv_cache` + allocates recurrent buffers only for `linear_attention` layers at lines + 1511 to 1513. This model has none. +3. `src/vllm/v1/worker/gpu/runner.cpp::GPUModelRunner::execute_model`, lines + 2779 to 2805, builds and remaps GDN metadata when that group exists. +4. `src/vllm/model_executor/models/qwen3_5.cpp::CheckDensePagedForward`, lines + 9240 to 9249, accepts zero GDN layers and zero caches. It then validates + live slot 0 against zero slots and throws at `ValidateGdnStateIndices`. +5. `BuildStepDevInputs`, lines 4659 to 4682, independently validates and + prepares the same unused metadata. Repairing the first check alone fails. + +The sibling `CheckPagedForward` repeats this assumption at lines 8526 to 8536. +`ForwardLayers` and `DenseForwardLayers` call the GDN builder at lines 8380 and +9323. Both graph `Step` methods validate GDN state before their eager fallback, +at lines 10763 and 11391. Persistent inputs repeat the builder at lines 11036 +and 11774. The graph staging functions already test the GDN presence flags. + +`git log -S'ValidateGdnAttentionMetadata'` identifies `f344decf4` and +`3ae5cfe06`. The original [packed-decode specification](gdn-packed-decode.md) +records why shared validation protects real consumers. Preserve that guarantee. + +The existing `BuildFullAttnStepDevInputs`, line 7845, uploads full-attention +metadata and leaves GDN fields inert. Its current consumer is the multi-token prediction (MTP) draft +head. Reusing it avoids a second full-attention preparation implementation. + +## Pinned reference and adaptations + +The [primary pin](../upstream-sync.md) is +`e126687a9a828d513c01a07cd69f025f27d63280`, runtime +`0.28.1rc1.dev132+ge126687a9`. Read these executing upstream anchors: + +- `vllm/model_executor/models/qwen3_5.py::Qwen3_5DecoderLayer.__init__`, + lines 144 to 160, constructs GDN only for `linear_attention`. +- `vllm/model_executor/models/qwen3_5.py::Qwen3_5Model.__init__`, lines 249 + to 259, selects every decoder from `config.layer_types`. +- `vllm/v1/worker/gpu/model_runner.py::GPUModelRunner.get_kv_cache_spec`, + lines 530 to 531, delegates to + `vllm/v1/worker/gpu/attn_utils.py::get_kv_cache_spec`, lines 52 to 65. + This V2 runner chain enumerates modules that actually require caches. +- `vllm/model_executor/layers/mamba/abstract.py::MambaBase.get_kv_cache_spec`, + lines 67 to 87, obtains recurrent shapes from a recurrent consumer. + +The exact no-GDN completion case is a local regression. The inspected upstream +`tests/models/language/generation/test_common.py`, `test_hybrid.py`, +`tests/models/test_qwen3_5_mtp_config.py`, and +`tests/v1/worker/test_gpu_model_runner.py` do not contain that case. +Preserve the existing ported GDN cases and their upstream anchors. Do not turn +unrelated KV-sharing allocation tests into a new topology obligation. + +The operator's pinned runtime reports `Using V2 Model Runner`. The V2 chain +is the primary execution anchor for qualification. + +Run the primary oracle on the identical generated dense GGUF before accepting +the fix. The [GGUF plugin pin](../oracles/vllm-gguf-plugin.md) is +`d4c1f0d082fc7cd4350da56689109a01c1f29d6c`. Its +`vllm_gguf_plugin/config_parser.py::GGUFConfigParser.parse` reads a local +configuration beside the artifact. Supplying that configuration and explicit +token IDs is an allowed harness adaptation. Preserve all model tensors and +geometry. A successful import or config construction is not an oracle result. + +Use the existing pinned runtime, plugin artifact, and dependencies supplied by +the operator. Record their source revisions and binary hashes. Missing runtime +registration or unsupported full-attention execution leaves the oracle gate +`PENDING`. Do not install a package, substitute safetensors, change the model, +or use another oracle without an explicit scope decision. Do not force eager +execution on the oracle. Record its resolved production configuration. + +The operator observed a missing `mm_proj` refusal on the sibling F16 oracle +workload. The pinned plugin's +`vllm_gguf_plugin/weights_adapter/qwen3_5.py::QWEN35_ARCHITECTURES`, line 40, +maps `qwen3_5_text` to conditional generation. Its `Qwen35GGUFAdapter.patch_hf_config` +replaces the architecture at line 225. Upstream +`vllm/model_executor/models/qwen3_5.py::Qwen3_5ForConditionalGeneration.__init__`, +lines 503 to 517, dereferences the vision configuration and constructs a tower. +A text configuration alone does not establish a runnable text-only GGUF path. +This known risk leaves G4 pending on an oracle refusal. + +## Design + +1. Derive the presence of GDN consumers from `weights.layers` and + `is_linear_attention`. Reuse one internal predicate where practical. +2. Keep layer-count, attention-cache-count, GDN-cache-count, and cache-layout + checks unconditional. A hybrid model with no caches must still fail. +3. Run GDN token-count, metadata, and graph-state validation only when a GDN + consumer exists. Keep the validators themselves strict, including direct + `BuildGdnStepInputs` consumers outside this model. +4. Select `BuildFullAttnStepDevInputs` for a model with no GDN consumers. + Apply the selection to both eager builders and both persistent graph builders. + Keep GDN upload and staging flags false on that path. +5. Pass inert empty GDN metadata into graph padding when no consumer exists. + `BuildPaddedDecode` must not copy unvalidated, arbitrary-length GDN indices + into its S-entry storage. Retain the bounds enforced for actual consumers. +6. Keep generic attention and graph shape checks effective for both model + topologies. Preserve real-GDN decode, prefill, mixed, speculative, and padded + state validation. Do not use GDN metadata as the only generic shape check. + +Never infer the absence of consumers from `state_slots == 0` or an empty cache +vector. Never add dummy recurrent state, a fake layer, a validation bypass flag, +or a fixture geometry change. Keep model activations and key-value (KV) storage at their +resolved bf16 dtype. Retain existing annotated f32 exceptions and integer +metadata layouts. This change adds no wider model buffers or recurrent tensors. + +## Regression fixture + +Use only the dense control from the frozen gather experiment. Extract its +minimal deterministic generator into this row's own fixture file. Preserve the +bytes of `Q4_0-dense.gguf`, even though its embedding and projections are dense. +Do not copy the 19-format provider campaign into this regression. + +The artifact has 991296 bytes and SHA256 +`0e6554ba521edfde00d4d025a3058eabaaacdce6b24344f959e83d8dde35df7f`. +Its geometry is hidden width 256, intermediate width 256, vocabulary 128, +four query heads, one KV head, head width 64, one full-attention layer, and +`full_attention_interval=1`. Rotary width is 64, base is 1000000, and MRoPE +sections are `[16,8,8,0]`. Norm epsilon is `1e-6`, seed is `0x524f434d`. +Inactive state-space model (SSM) loader keys retain convolution width 4, inner width 64, state width +64, time-step rank 1, and group count 1. + +Prompts are `[1,0,63,127,63]` and `[1,127,0,127]`. Request exactly four greedy +tokens with `ignore_eos=1` and seed `0x524f434d`. Use block size 16, four blocks, +maximum length 64, and one sequence. Public device 0 selects AUTO in the HIP-only +build. Assert the actual ROCm dense embedding provider executes. + +For both local and oracle runs, execute each prompt three times with a fresh +engine and fresh model state. Keep batch size and concurrency at one. Submit +prompts sequentially and record the actual scheduling and token budgets. + +## Gates and evidence + +| Gate | Required result | Current result | +|---|---|---| +| G0: independent red | New public regression on pristine product base fails at GDN validation after load | `PENDING`: operator reproduction exists, row-owned test is owed | +| G1: public completion | Both prompts produce four tokens in three fresh-engine repeats, native ROCm provider executes | `PENDING`: operator GPU run | +| G2: consumer distinction | Dense and MoE production routes accept no-GDN state and reject damaged real-GDN state | `PENDING`: fresh implementer | +| G3: graph preparation | Both drivers cover cold, capture, persistent staging, and replay routing with no GDN consumers | `PENDING`: fresh implementer and operator | +| G4: pinned oracle | Same dense artifact and all six fresh-engine runs, exact token IDs, finite logits, preserved dtypes | `PENDING`: operator runtime execution | +| G5: review and full gate | Focused gates, mutations, full preflight, fresh review, and operator rerun | `PENDING`: implementation | + +G0 starts at `vllm_engine_load` and `vllm_complete_tokens` from `include/vllm.h`. +The test must assert successful load before its expected pre-fix completion +failure. Reproduce with the row's fresh build from unchanged base product code. +The preserved gather red establishes the diagnosis, not this independent gate. + +For G2, enter `ModelRegistry::Forward` for both dense and MoE variants. Cover +prefill and decode without GDN consumers, with default-empty and unused +runner-style GDN metadata. For real GDN consumers, reject missing all caches, +wrong cache count, invalid ranks, inconsistent slots, missing metadata, +duplicate indices, and out-of-range indices. Keep valid hybrid completion green. +A validator-only unit test does not prove these production call sites execute. + +For G3, extend the existing graph harness for both drivers. Exercise their +production `Step` methods, graph fallback, persistent inputs, and staging flags. +Include no-GDN metadata with an oversized unused index vector. The padding path +must ignore that vector safely. Mutate the inert-metadata selection and require +this regression to fail. Use a memory-sanitized run if needed to expose an +out-of-bounds copy reliably. +Trace the registry dispatch to each driver and mutate each changed call site. +A CPU fake replay proves routing only. Record that limitation and obtain an +operator GPU replay result for any claimed replay numerics. Do not enable a +new backend or claim a GPU graph executed from the CPU harness. + +Register a dedicated public test such as `test_capi_qwen35_full_attn_state`. +Run it with `test_qwen27_paged_forward`, `test_qwen35_paged_forward`, +`test_qwen3_5_decode_graph_seam`, and `test_model_registry`. Retain existing +GDN state, speculative metadata, and graph-padding cases in those suites. +Build in a row-owned ignored `build-*` directory with at most `-j 4`. +The implementer records exact configure, build, and focused test commands +before handing GPU commands to the operator. No shared build directory is valid. + +For every result, record the immutable source SHA, binary SHA256, fixture hashes, +command, environment, exit status, and evidence path. G4 additionally records +source anchors, runtime and plugin identity, output tokens, resolved dtype, +attention backend, and graph mode. No config-only or local self-comparison +substitutes for G4. A token mismatch remains failing until explained and fixed. + +Fresh review uses scratch copies and restores every modified file byte-for-byte. +Restore unconditional GDN validation at each newly conditional entry. Restore +the GDN builder at each full-attention selection. Delete the production call +sites into the changed preparation path. Each relevant positive gate must fail. +Then force the no-GDN branch for a hybrid model, or remove cache-count +validation, and prove the corresponding malformed-hybrid gate fails. Mutate duplicate, range, missing +metadata, and layout guarantees individually. Keep per-mutation failure logs. + +Run `scripts/agent-preflight.sh` before edits and the staged form before commit. +Run exact-range record, commit-style, trailer, and PR-size checks after commit. +Classify omitted hardware and build gates explicitly. The operator repeats the +applicable gates on the immutable implementation before publication. + +## Existing evidence + +On 8 September 2026 PDT, the operator ran the frozen gather public binary on local +gfx1100 under `/home/vikash/gpu.lock`. Completion threw +`qwen3_5: GDN state index out of range`. The process returned 1 with five +passing assertions and one failed completion assertion. + +The binary SHA256 is +`f6a109ef33a133b381a112313591534f560adedb0d4919f0d67567cd597552e1`. +Its source was spec commit `670e6d78ddf55231394748e0032939fd53dc56a5` plus +uncommitted test-only changes. The fixture header SHA256 is +`339414f93e59e6be9a4ca545d5e762bb2816714343f466e218dbc2b69483bdfd`. +The public test source SHA256 is +`add58ac23eef26588fb358d7679feeac961baee3a1da3d5ddd3adedaf9a1a825`. +The log is `/home/vikash/.cache/rdna3-gather-impl/evidence/public-red.log`, SHA256 +`fbd5d684566961d71f31c8b9e58daba8d5303636adb12ceccb164dbe3b220e1d`. +These are supplied local evidence paths, not environment defaults. + +## Risks and stop conditions + +- `NEEDS_CONTEXT`: the frozen fixture bytes, pinned runtime, or source cannot + be verified. The operator owns the missing artifact or runtime decision. +- `NEEDS_DECISION`: the oracle requires a different model artifact, new + dependency, or behavior outside the stated scope. +- `BLOCKED`: required GPU execution is unavailable. Only the operator runs + the GPU work under the recorded mutex or applicable fleet lease. +- `FAILING`: a no-GDN route still prepares device recurrent metadata, a real-GDN guard + weakens, or a mutation remains green. Repair through a fresh implementer. +- `FAILING`: graph coverage relies on fake replay numerics or a different + untested sibling. Keep the affected gate pending until valid evidence exists. +- `NEEDS_DECISION`: the minimal fix requires planner topology, unrelated + quantization, broader speculative behavior, or any excluded file change. + +## Owed + +Issue #3098 owns implementation, independent red evidence, pinned oracle +execution, review mutations, and the operator rerun. Record the measured +outcome and defaults here before changing the row to `DONE`. Keep the issue +open until the work lands. From 44e95b39f02cb101d3b0af90a842c9153f72066e Mon Sep 17 00:00:00 2001 From: Vikash Loomba Date: Tue, 8 Sep 2026 20:32:11 -0700 Subject: [PATCH 03/24] fix(ENG-QWEN35-FULL-ATTN-STATE): skip unused GDN state checks Full-attention Qwen3.5 models have no recurrent cache but receive legacy GDN metadata. Select validation and device preparation from the loaded layer consumers. Keep hybrid cache and metadata checks strict, and pass inert metadata into graph padding before copying indices. The operator reproduced the public red and verified twelve fresh-engine completions. Both registered siblings and graph drivers pass focused CPU gates. Thirty scratch mutations prove the tests detect removed guards and production calls. Pinned vLLM rejects the exact text-only GGUF configuration before an engine becomes usable. G4 stays pending in the row specification. This change makes no performance claim and tracks #3098 on row/ENG-QWEN35-FULL-ATTN-STATE under draft PR #3101. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Codex:gpt-6-astra [Codex CLI] --- .../ISSUE-GH-3098.md | 10 +- .agents/specs/qwen35-full-attn-state.md | 259 ++++++++++++++- src/vllm/model_executor/models/qwen3_5.cpp | 108 +++++-- tests/CMakeLists.txt | 1 + tests/capi/qwen35_full_attn_fixture.h | 133 ++++++++ tests/capi/test_qwen35_full_attn_state.cpp | 262 +++++++++++++++ .../vllm/models/test_qwen27_paged_forward.cpp | 199 ++++++++++++ .../vllm/models/test_qwen35_paged_forward.cpp | 199 ++++++++++++ .../models/test_qwen3_5_decode_graph_seam.cpp | 298 ++++++++++++++++++ 9 files changed, 1418 insertions(+), 51 deletions(-) create mode 100644 tests/capi/qwen35_full_attn_fixture.h create mode 100644 tests/capi/test_qwen35_full_attn_state.cpp diff --git a/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md b/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md index 10b1ac9b4..3a39e2f8b 100644 --- a/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md +++ b/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md @@ -48,4 +48,12 @@ The quoted text below is historical evidence only. It does not define issue auth ## Resolution -- +The scoped implementation passes public completion through both default and +callback sampling arms. The operator reproduced the independent red and reran +all public and focused CPU gates. The implementer completed 30 mutation checks. + +The exact GGUF attempt on pinned vLLM refuses the text-only engine configuration +before generating a token. The owning [specification](../../specs/qwen35-full-attn-state.md) +records the source hashes, commands, logs, and pending G4 obligation. Fresh +review and the final operator gate remain pending. Keep this issue open until +qualified work lands. diff --git a/.agents/specs/qwen35-full-attn-state.md b/.agents/specs/qwen35-full-attn-state.md index a83ae1eb0..863f0a4b8 100644 --- a/.agents/specs/qwen35-full-attn-state.md +++ b/.agents/specs/qwen35-full-attn-state.md @@ -10,15 +10,15 @@ Spec base: `6db4bef906859e864c82523c01107473f7dcca29`. ## Now -`PENDING`. This specification precedes implementation. The row uses one pull -request under the repository default. A fresh implementer works from this -committed specification. A fresh reviewer mutates the immutable implementation, -and the operator reruns its gates. The operator publishes the pull request. -The current task does not authorize merging it. +`ACTIVE`. The consumer-based implementation passes public completion and the +focused CPU suites. The operator independently reproduced the red result and +reran the public and CPU gates. The row uses one pull request under the +repository default. Specification commit `f62e4d7db0a2e1fb7d0e0a3cb5dad7072f182690` +precedes implementation. -Public completion fails before any quantized gather provider runs. Runtime -correctness, oracle execution, and implementation review remain `PENDING`. -This row makes no performance claim and establishes no performance floor. +Pinned oracle execution, the final gate, and fresh implementation review remain +`PENDING`. The current task does not authorize merging. This row makes no +performance claim and establishes no performance floor. ## Scope @@ -49,7 +49,7 @@ together when this child changes state. | ID | Upstream source | Local anchor | Tests and evidence | Spec | State | Owner | Issue | |---|---|---|---|---|---|---|---| -| `ENG-QWEN35-FULL-ATTN-STATE` | Pinned `Qwen3_5DecoderLayer` and `GPUModelRunner.get_kv_cache_spec` | `CheckDensePagedForward`, `CheckPagedForward`, `BuildFullAttnStepDevInputs`, both graph `Step` methods | G0 to G5 | This file | `PENDING` | Row helper, fresh reviewer, operator verification | #3098 | +| `ENG-QWEN35-FULL-ATTN-STATE` | Pinned `Qwen3_5DecoderLayer` and `GPUModelRunner.get_kv_cache_spec` | `CheckDensePagedForward`, `CheckPagedForward`, `BuildFullAttnStepDevInputs`, both graph `Step` methods | G0 to G5 | This file | `ACTIVE` | Row helper, fresh reviewer, operator verification | #3098 | ## Diagnosis and source anchors @@ -188,12 +188,12 @@ prompts sequentially and record the actual scheduling and token budgets. | Gate | Required result | Current result | |---|---|---| -| G0: independent red | New public regression on pristine product base fails at GDN validation after load | `PENDING`: operator reproduction exists, row-owned test is owed | -| G1: public completion | Both prompts produce four tokens in three fresh-engine repeats, native ROCm provider executes | `PENDING`: operator GPU run | -| G2: consumer distinction | Dense and MoE production routes accept no-GDN state and reject damaged real-GDN state | `PENDING`: fresh implementer | -| G3: graph preparation | Both drivers cover cold, capture, persistent staging, and replay routing with no GDN consumers | `PENDING`: fresh implementer and operator | -| G4: pinned oracle | Same dense artifact and all six fresh-engine runs, exact token IDs, finite logits, preserved dtypes | `PENDING`: operator runtime execution | -| G5: review and full gate | Focused gates, mutations, full preflight, fresh review, and operator rerun | `PENDING`: implementation | +| G0: independent red | New public regression on pristine product base fails at GDN validation after load | Satisfied: operator reproduced the row-owned failure after public load | +| G1: public completion | Both prompts produce four tokens in three fresh-engine repeats, native ROCm provider executes | Satisfied: 12 fresh engines, default and callback sampling arms | +| G2: consumer distinction | Dense and MoE production routes accept no-GDN state and reject damaged real-GDN state | Satisfied: focused suites and independent operator rerun | +| G3: graph preparation | Both drivers cover cold, capture, persistent staging, and replay routing with no GDN consumers | Satisfied for CPU routing and staging, no GPU replay numerical claim | +| G4: pinned oracle | Same dense artifact and all six fresh-engine runs, exact token IDs, finite logits, preserved dtypes | `PENDING`: pinned plugin rejects the actual text-only engine configuration | +| G5: review and full gate | Focused gates, mutations, full preflight, fresh review, and operator rerun | `PENDING`: fresh review and final operator gate | G0 starts at `vllm_engine_load` and `vllm_complete_tokens` from `include/vllm.h`. The test must assert successful load before its expected pre-fix completion @@ -263,6 +263,230 @@ The log is `/home/vikash/.cache/rdna3-gather-impl/evidence/public-red.log`, SHA2 `fbd5d684566961d71f31c8b9e58daba8d5303636adb12ceccb164dbe3b220e1d`. These are supplied local evidence paths, not environment defaults. +## Implementation evidence + +Measurements on 9 September 2026 UTC use the row-owned worktree +`/home/vikash/vllm.cpp-qwen35-full-attn-state-impl`. Evidence is under +`/home/vikash/.cache/qwen35-full-attn-state-impl/evidence`. These paths identify +measured artifacts. They are not environment defaults. + +The product source is `qwen3_5.cpp`, SHA256 +`899913b8aeff65a08eb5289f6f08777ee78638e37722f9d8138daff723f8f498`. +The red source is the unchanged product at specification commit +`f62e4d7db0a2e1fb7d0e0a3cb5dad7072f182690`. Green snapshots carry that base, +the exact implementation patch, and every test source hash. The implementation +commit containing this record makes those bytes reachable from Git. + +### Public red and completion + +The operator generated the row's fixture and confirmed its 991296-byte size +and the frozen SHA256. The row-owned red binary has SHA256 +`76c4e04bfb1b2715d4010e11a1d85cb076c7ada8e146094a1419fc0566d6efff`. +It returned 1 after `public load succeeded`, with 11 passing assertions and +one failed completion assertion. The error was `GDN state index out of range`. +`red-snapshot/public-red-operator.log` has SHA256 +`dbf8bb09eccc4d626d0c6cc4a9d97d93738563954dae0aeefa32b9ed5bfd8981`. + +The green binary has SHA256 +`14d2fee7f63df4c8ab7721923d429822488e7ac55a058268b9145bd4d5f371a7`. +The operator ran all 12 fresh engines and passed all 3364 assertions. +`green-v1-snapshot/public-green-operator.log` has SHA256 +`6318b014c368835a71fe2501444adaf61b3312df178c564d0a0d3fba820f9c4e`. +The two token sequences were `[47,19,4,20]` and `[11,28,104,78]`. +Each sequence was identical in three repetitions of both sampling arms. + +The callback-free arm retains default device sampling. The callback arm +observes 512 finite logits per completion. A custom processor stages logits +through the host at `src/vllm/v1/sample/logits_processor/builtin.cpp::apply_logits_processors`, +lines 75 to 159. Both arms reach `vt::GreedyArgmax` through the sampler. +Each run executes one native ROCm embedding prefill, three embedding decodes, +four cache writes, and four greedy operations. Verified named providers call +the original native functions. They check bf16 embedding activations and KV +storage, f32 sampler logits, and i64 sampled IDs. Reference-tier hits do not +increase. The f32 logits belong to the existing sampler ABI. + +Both public commands use the operator's local GPU 0 and mutex: + +```sh +env HIP_VISIBLE_DEVICES=0 ROCR_VISIBLE_DEVICES=0 \ + TMPDIR=/home/vikash/.cache/qwen35-full-attn-state-impl/tmp \ + GIT_CEILING_DIRECTORIES=/home/vikash/.cache/qwen35-full-attn-state-impl/tmp \ + GIT_CONFIG_GLOBAL=/dev/null \ + flock -n -F /home/vikash/gpu.lock \ + /home/vikash/.cache/qwen35-full-attn-state-impl/evidence/green-v1-snapshot/test_capi_qwen35_full_attn_state +``` + +Use `red-snapshot` in the executable path for the frozen red command. +Each snapshot's `manifest.json` contains exact argument arrays and source +hashes. The operator receipts record execution and restoration checks. + +### CPU consumers and graph routing + +The implementer and operator passed these complete suites: + +| Suite | Test cases passed | Assertions passed | +|---|---|---| +| `test_model_registry` | 24 | 993 | +| `test_qwen27_paged_forward` | 36 | 1406 | +| `test_qwen35_paged_forward` | 10 | 676 | +| `test_qwen3_5_decode_graph_seam` | 16 | 1550 | + +The registry suite retains one pre-existing skipped case. All new cases run. +`cpu-green-v1-snapshot/manifest.json` has SHA256 +`575e9695acc9600515050a6ba0ed509795df45f7a128b98c6c303eb87c005183`. +It freezes all four executables and their source files. The operator's +per-binary logs, receipts, and `operator-results.json` are beside the manifest. + +The no-GDN tests enter both registered forwards for prefill and decode. +Empty metadata, unused runner metadata, and stale configuration labels all +reach the loaded layer consumers. Separate negative cases preserve each +hybrid cache-count, rank, slot-layout, metadata, duplicate, and range guard. +Existing speculative, prefill, mixed, and padded-state tests remain green. + +Both graph drivers cover capture enabled and disabled, asynchronous staging +enabled and disabled, batches 1 and 3, and three unused metadata forms. +Six steps cover cold execution, capture, persistent input binding, and replay +routing. Batch 3 pads to 4. Oversized unused indices contain 4096 entries. +Each persistent slot binds exactly five generic inputs, with no GDN input. + +The dense registry reaches its actual graph driver under the existing CPU +harness. The MoE registry needs its FP4 capability predicate. Its test uses +valid small NVFP4 expert tensors and a scoped CPU platform answer. A control +without that answer stays eager. Both use the existing CPU arithmetic and fake +graph replay. These cases prove routing and staging, not GPU replay numerics. +No backend or quantized provider changes. + +The shared builder's existing consumers also pass: +`test_qwen3_5_gguf_mtp`, `test_qwen35_exl3`, and +`test_qwen3_dflash2_draft`. Their complete CPU run returned 0. + +### Build and focused commands + +Run from the row worktree. Set `TMPDIR` and `GIT_CEILING_DIRECTORIES` to +`/home/vikash/.cache/qwen35-full-attn-state-impl/tmp`, and set +`GIT_CONFIG_GLOBAL=/dev/null` for gate subprocesses. Configure commands were: + +```sh +cmake -S . -B build-full-attn-cpu -G Ninja \ + -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DVLLM_CPP_CUDA=OFF -DVLLM_CPP_HIP=OFF -DVLLM_CPP_VULKAN=OFF \ + -DVLLM_CPP_METAL=OFF -DVLLM_CPP_MLX=OFF -DVLLM_CPP_TENSTORRENT=OFF \ + -DVLLM_CPP_TRITON=OFF -DVLLM_CPP_BUILD_EXAMPLES=OFF -DVLLM_CPP_SERVER=OFF +cmake -S . -B build-full-attn-hip -G Ninja \ + -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DVLLM_CPP_CUDA=OFF -DVLLM_CPP_HIP=ON -DVLLM_CPP_HIP_ARCHITECTURES=gfx1100 \ + -DVLLM_CPP_VULKAN=OFF -DVLLM_CPP_METAL=OFF -DVLLM_CPP_MLX=OFF \ + -DVLLM_CPP_TENSTORRENT=OFF -DVLLM_CPP_TRITON=OFF \ + -DVLLM_CPP_BUILD_EXAMPLES=OFF -DVLLM_CPP_SERVER=OFF +cmake --build build-full-attn-cpu -j 4 --target test_model_registry \ + test_qwen27_paged_forward test_qwen35_paged_forward \ + test_qwen3_5_decode_graph_seam test_capi_qwen35_full_attn_state +cmake --build build-full-attn-hip -j 4 --target test_capi_qwen35_full_attn_state +ctest --test-dir build-full-attn-cpu --output-on-failure \ + -R '^(test_qwen27_paged_forward|test_qwen35_paged_forward|test_qwen3_5_decode_graph_seam|test_model_registry)$' +cmake --build build-full-attn-cpu -j 4 --target test_qwen3_5_gguf_mtp \ + test_qwen35_exl3 test_qwen3_dflash2_draft +ctest --test-dir build-full-attn-cpu --output-on-failure \ + -R '^(test_qwen3_5_gguf_mtp|test_qwen35_exl3|test_qwen3_dflash2_draft)$' +``` + +All configure, final build, and green focused commands returned 0. +The original CPU red returned 8 from CTest. It detected both intended GDN +errors. Two valid-hybrid test assertions initially assumed host logits. The +registered forward returns device logits, so the tests now download them for +finite-value checks. No product behavior changed for that test correction. +`cpu-red-snapshot` preserves the original tests, product source, and binaries. + +### Implementer mutations + +The three address-sanitized baselines pass. All 30 mutations fail their focused +gates. `mutations/manifest.json` has SHA256 +`9f2cb023ea64af396a2fccbbe83b0dd8fc67a591aed9403c399cfa13f7a515ff`. +The external recipe `run-mutations.py` has SHA256 +`a0855b588f8d2e7a7286ee9a56b2a0551f8111059537e264127a2f6c9787b3b2`. + +Each mutant compiles a separate source copy at `-O0 -g -fsanitize=address` +and links the row's own CPU archive. The archive starts fresh for each mutant. +The corresponding baseline uses the same compiler and linker flags. +`ASAN_OPTIONS=detect_leaks=0:abort_on_error=1` disables unrelated leak reporting. +No tracked source or normal build output changes. Each manifest entry records +its command, mutated source hash, binary hash, failed exit, and restoration. + +For each sibling, mutations restore unconditional entry validation, force the +entry's no-consumer branch, remove cache-count validation, and restore the GDN +eager builder. They independently restore graph validation, GDN padding-size +restrictions, unused spec classification, and persistent GDN preparation. +Removing each pre-padding shape check fails. Restoring the unused GDN index +copy causes an address-sanitizer heap-buffer-overflow in both drivers. + +Six shared mutations separately remove rank, paired-slot, cross-layer-slot, +duplicate, range, and missing-index guarantees. Both registry suites fail +for each removal. Four further mutations delete each registry's graph and +eager production call. Each relevant positive gate fails. Fresh independent +review must repeat the required mutations on the immutable implementation. + +### Full gate and build classification + +`preflight-start.log` records the full gate before edits. +`preflight-staged.log` records the staged run before the implementation commit. +The staged run uses the same temporary-directory and Git isolation as the +focused tests, plus the existing NumPy dependency path supplied by the operator. +An external argument wrapper adds `--jobs 4` only to the compile checker. +It preserves every gate and changes no tracked script. + +The generic preflight sweep does not supply every build checker's arguments. +The x86 CPU ISA audit runs explicitly against +`build-full-attn-cpu/compile_commands.json` and passes in `cpu-isa-build.log`. +The exact-range checks supply the recorded product base and implementation +head, with draft PR 3101 for path classification. Their results belong in +`range-gates.json` beside the other evidence. + +ARM ISA, CUDA fat-binary, and Triton AOT build audits are outside this row's +configured CPU and HIP builds. The change edits no architecture-specific +instruction unit, CUDA gencode setting, or Triton artifact. The normal public +test returns skip code 77 in a CPU-only build because public AUTO requires the +HIP-only configuration here. The operator's HIP run executes every assertion. +GPU graph replay numerics remain unclaimed. G4 and fresh review remain pending. + +### Pinned oracle refusal + +The operator ran the actual first engine against the unchanged dense GGUF. +The engine returned 1 before becoming usable and emitted no tokens. The +exception reports `Qwen3_5Config` required and `Qwen3_5TextConfig` received. +The executing rejection is in upstream +`vllm/multimodal/processing/context.py::InputProcessingContext.get_hf_config`, +line 140, called by `vllm/model_executor/models/qwen3_5.py::Qwen3_5ProcessingInfo.get_hf_config`, +line 108. +The complete traceback is preserved in the report and operator log. + +The runtime reports vLLM `0.28.1rc1.dev132+ge126687a9`, PyTorch +`2.12.0+git6bbd260`, HIP `7.2.53211`, and plugin +`0.0.5+d4c1f0d.gfx1100`. The script supplies only local HF text metadata and +explicit token IDs. Model geometry, tensor bytes, inactive SSM keys, and MRoPE +sections match the frozen fixture. Production graph mode remains requested +with `enforce_eager=False`. No registry, model, or plugin correction is applied. + +`oracle-exact-gguf-v1-command.json` records the exact Docker argument arrays, +image digest, read-only runtime and plugin mounts, nonroot user, private +2 GiB IPC allocation, offline settings, and GPU 0 mutex. Each of its six +commands starts a new process and engine. The operator stopped after the first +refusal, because the remaining five commands cannot supply missing runtime +capability. No token, finite-logit, resolved-dtype, or GPU graph result is claimed +for the oracle. + +The attempt report `oracle-exact-gguf-v1-p0-r0.json` has SHA256 +`46d714e5fe6577663b0cb266c8d88c9a4a629eb2727314775a5b5dbb605ac2c0`. +Its operator log has SHA256 +`5244fbca9f48db1bfc6d9817d823fcc4e1fe1a48a89f1c04c216ad1a5db4cdc6`. +The script SHA256 is +`504162e44ba828249a1a825bf2053f53e7902f168bad3ba515334ff8440a7f3e`. +The local HF configuration SHA256 is +`6c4b2c6f3d71b90818730bbfa900a5cbb0a96bd64ab656fd9db8e65111c05638`. + +G4 remains `PENDING` on the operator's pinned GGUF runtime capability. +The implementation does not substitute a model or oracle. Issue #3098 retains +ownership of this gate, independent review, and the final operator gate. + ## Risks and stop conditions - `NEEDS_CONTEXT`: the frozen fixture bytes, pinned runtime, or source cannot @@ -280,7 +504,8 @@ These are supplied local evidence paths, not environment defaults. ## Owed -Issue #3098 owns implementation, independent red evidence, pinned oracle -execution, review mutations, and the operator rerun. Record the measured +Issue #3098 owns the pending pinned oracle execution, fresh review mutations, +and the final operator gate. Public red, local completion, consumer validation, +and CPU graph routing have measured evidence above. Record the measured outcome and defaults here before changing the row to `DONE`. Keep the issue open until the work lands. diff --git a/src/vllm/model_executor/models/qwen3_5.cpp b/src/vllm/model_executor/models/qwen3_5.cpp index 83ea59640..29bc1e464 100644 --- a/src/vllm/model_executor/models/qwen3_5.cpp +++ b/src/vllm/model_executor/models/qwen3_5.cpp @@ -7835,6 +7835,32 @@ DBuf MtpHeadHidden(Dev device, const Qwen3_5MTPWeights& weights, return MatmulBf16D(device, concatenated.t(), weights.fc); } +template +bool HasGdnConsumers(const Weights& weights) { + // vLLM qwen3_5.py:144-160 @ e126687a9a constructs GDN only for these layers. + // Cache absence cannot establish this: a hybrid model can have missing caches. + return std::any_of(weights.layers.begin(), weights.layers.end(), + [](const auto& layer) { return layer.is_linear_attention; }); +} + +void ValidateFullAttnStepMetadata(int64_t tokens, const CommonAttentionMetadata& am) { + VT_CHECK(am.num_actual_tokens == tokens, + "qwen3_5 full-attn: attn metadata token count must match positions"); + VT_CHECK(static_cast(am.slot_mapping.size()) == tokens, + "qwen3_5 full-attn: slot_mapping must cover every token"); + VT_CHECK(am.num_reqs >= 0 && + static_cast(am.seq_lens.size()) == am.num_reqs && + static_cast(am.query_start_loc.size()) == am.num_reqs + 1, + "qwen3_5 full-attn: malformed full-attn metadata shapes"); + VT_CHECK(am.block_table_num_cols >= 0 && + static_cast(am.block_table_tensor.size()) == + static_cast(am.num_reqs) * am.block_table_num_cols, + "qwen3_5 full-attn: malformed block table"); + VT_CHECK(am.query_start_loc.front() == 0 && am.query_start_loc.back() == tokens && + std::is_sorted(am.query_start_loc.begin(), am.query_start_loc.end()), + "qwen3_5 full-attn: query offsets must span tokens in order"); +} + // ── Full-attention-only per-step device inputs (SPEC-MTP I5c). ────────────── // BuildStepDevInputs sibling for a step with NO GDN layers (the MTP draft head // is a single layer_type="full_attention" decoder — qwen3_5_mtp.py:105-112). It @@ -7846,13 +7872,7 @@ StepDevInputs BuildFullAttnStepDevInputs(Dev d, const std::vector& positions, const CommonAttentionMetadata& am) { const int64_t T = static_cast(positions.size()); - VT_CHECK(am.num_actual_tokens == T, - "qwen3_5 MTP paged: attn metadata token count must match positions"); - VT_CHECK(static_cast(am.slot_mapping.size()) == T, - "qwen3_5 MTP paged: slot_mapping must cover every token"); - VT_CHECK(static_cast(am.seq_lens.size()) == am.num_reqs && - static_cast(am.query_start_loc.size()) == am.num_reqs + 1, - "qwen3_5 MTP paged: malformed full-attn metadata shapes"); + ValidateFullAttnStepMetadata(T, am); return StepDevInputs{ DBuf(d, DType::kI32, {T}, positions.data()), DBuf(d, DType::kI64, {T}, am.slot_mapping.data()), @@ -8376,8 +8396,10 @@ static DBuf ForwardLayers(Dev d, const Tensor& hidden_in, }(); std::optional local_sdi; if (persistent_sdi == nullptr) - local_sdi.emplace( - BuildStepDevInputs(d, positions, attn_meta, gdn_meta, gdn_state_slots)); + local_sdi.emplace(HasGdnConsumers(weights) + ? BuildStepDevInputs(d, positions, attn_meta, gdn_meta, + gdn_state_slots) + : BuildFullAttnStepDevInputs(d, positions, attn_meta)); StepDevInputs& sdi = persistent_sdi != nullptr ? *persistent_sdi : *local_sdi; // Build the fused-preamble cos|sin cache ONCE; fp4_attn keys the per-arch // default (fp8/bf16 attn — the 35B — stays OFF; VT_FUSE_ATTN_PREAMBLE overrides). @@ -8521,8 +8543,6 @@ static void CheckPagedForward(const std::vector& token_ids, "qwen3_5 paged forward: weights.layers size must equal num_hidden_layers"); VT_CHECK(attn_meta.num_actual_tokens == T, "qwen3_5 paged forward: attn_meta.num_actual_tokens must equal T"); - VT_CHECK(gdn_meta.num_actual_tokens == T, - "qwen3_5 paged forward: gdn_meta.num_actual_tokens must equal T"); int64_t n_full = 0, n_gdn = 0; for (const auto& l : weights.layers) (l.is_linear_attention ? n_gdn : n_full) += 1; @@ -8532,8 +8552,12 @@ static void CheckPagedForward(const std::vector& token_ids, "qwen3_5 paged forward: gdn_state count must equal GDN layer count"); const int64_t state_slots = detail::ValidateGdnStateCacheLayout(gdn_state); - detail::ValidateGdnAttentionMetadata( - gdn_meta, state_slots, /*allow_inert_padding=*/false); + if (n_gdn > 0) { + VT_CHECK(gdn_meta.num_actual_tokens == T, + "qwen3_5 paged forward: gdn_meta.num_actual_tokens must equal T"); + detail::ValidateGdnAttentionMetadata( + gdn_meta, state_slots, /*allow_inert_padding=*/false); + } } // Transfer a freshly-produced [rows, vocab] device logits DBuf into an OWNING @@ -9235,8 +9259,6 @@ static void CheckDensePagedForward(const std::vector& token_ids, "num_hidden_layers"); VT_CHECK(attn_meta.num_actual_tokens == T, "qwen3_5 dense paged forward: attn_meta.num_actual_tokens must equal T"); - VT_CHECK(gdn_meta.num_actual_tokens == T, - "qwen3_5 dense paged forward: gdn_meta.num_actual_tokens must equal T"); int64_t n_full = 0, n_gdn = 0; for (const auto& l : weights.layers) (l.is_linear_attention ? n_gdn : n_full) += 1; VT_CHECK(static_cast(attn_kv.size()) == n_full, @@ -9245,8 +9267,12 @@ static void CheckDensePagedForward(const std::vector& token_ids, "qwen3_5 dense paged forward: gdn_state count must equal GDN layers"); const int64_t state_slots = detail::ValidateGdnStateCacheLayout(gdn_state); - detail::ValidateGdnAttentionMetadata( - gdn_meta, state_slots, /*allow_inert_padding=*/false); + if (n_gdn > 0) { + VT_CHECK(gdn_meta.num_actual_tokens == T, + "qwen3_5 dense paged forward: gdn_meta.num_actual_tokens must equal T"); + detail::ValidateGdnAttentionMetadata( + gdn_meta, state_slots, /*allow_inert_padding=*/false); + } } // Dense embed (27B): hidden[T,H] bf16 = embed_tokens[token_ids] (device-resident @@ -9319,8 +9345,10 @@ static DBuf DenseForwardLayers(Dev d, const Tensor& hidden_in, gdn_state.empty() ? 0 : gdn_state.front().ssm_state.shape[0]; std::optional local_sdi; if (persistent_sdi == nullptr) - local_sdi.emplace( - BuildStepDevInputs(d, positions, attn_meta, gdn_meta, gdn_state_slots)); + local_sdi.emplace(HasGdnConsumers(weights) + ? BuildStepDevInputs(d, positions, attn_meta, gdn_meta, + gdn_state_slots) + : BuildFullAttnStepDevInputs(d, positions, attn_meta)); StepDevInputs& sdi = persistent_sdi != nullptr ? *persistent_sdi : *local_sdi; // Build the fused-preamble cos|sin cache ONCE; fp4_attn keys the per-arch // default (the real 27B W4A4 => ON; bf16/GGUF dense => OFF; env overrides). @@ -10760,7 +10788,9 @@ ForwardLogits Qwen3_5DecodeGraph::Step( CheckPagedForward(token_ids, positions, attn_meta, gdn_meta, attn_kv, gdn_state, impl_->weights, impl_->config); const int64_t B = static_cast(token_ids.size()); - detail::ValidateGdnDecodeGraphState(gdn_meta, gdn_state, B); + const bool has_gdn = HasGdnConsumers(impl_->weights); + if (has_gdn) detail::ValidateGdnDecodeGraphState(gdn_meta, gdn_state, B); + else ValidateFullAttnStepMetadata(B, attn_meta); Backend& b = vt::GetBackend(impl_->queue.device.type); Dev d{b, impl_->queue}; // #1380: open a fresh demand measurement for this step. `PreGrowForCapture` @@ -10784,7 +10814,7 @@ ForwardLogits Qwen3_5DecodeGraph::Step( // exact shape trivially satisfies that while keeping the padded-row inertness // question out of the spec path. The shape count stays bounded by max_num_seqs // because num_reqs is. - const bool spec_step = gdn_meta.num_spec_decodes > 0; + const bool spec_step = has_gdn && gdn_meta.num_spec_decodes > 0; const int64_t S = spec_step ? B : PadToCaptureSize(B, impl_->max_num_reqs); // ENG-CUDAGRAPH-BREAK W6 (#1374): this step's uniform query length, and the // ring key built from it. `Q == 0` means the batch does not divide evenly into @@ -10803,8 +10833,8 @@ ForwardLogits Qwen3_5DecodeGraph::Step( const bool qlen_capped = DecodeGraphQueryLenCapped(impl_->slots, key); if (qlen_capped) v1::NoteDecodeGraphQueryLenDecline(); if (!impl_->enabled || S < 0 || !servable_shape || qlen_capped || - !detail::CanUseGdnDecodeGraphSize( - B, S, IndexedGdnStateIoEnabled(impl_->queue.device))) { + (has_gdn && !detail::CanUseGdnDecodeGraphSize( + B, S, IndexedGdnStateIoEnabled(impl_->queue.device)))) { if (aux_out != nullptr && !aux_out->layer_ids.empty()) { // The graph cannot serve this batch (disabled / unsupported size), so fall // back to the EAGER multi-tap forward, which fills aux_out itself. Without @@ -10906,7 +10936,10 @@ ForwardLogits Qwen3_5DecodeGraph::Step( pam = attn_meta; pgm = gdn_meta; } else { - BuildPaddedDecode(S, token_ids, positions, attn_meta, gdn_meta, ptok, ppos, + // The padding helper copies GDN indices into S entries. Without consumers, + // the caller's unused metadata has no validated bound and must stay inert. + BuildPaddedDecode(S, token_ids, positions, attn_meta, + has_gdn ? gdn_meta : GDNAttentionMetadata{}, ptok, ppos, pam, pgm); } @@ -11033,8 +11066,10 @@ ForwardLogits Qwen3_5DecodeGraph::Step( s.pin.Free(); { ActivePoolScope persistent_scope(&PersistentDecodeInputPool(d.b)); - s.dev = std::make_unique(BuildStepDevInputs( - d, s.positions, s.attn_meta, s.gdn_meta, gdn_state_slots)); + s.dev = std::make_unique( + has_gdn ? BuildStepDevInputs(d, s.positions, s.attn_meta, s.gdn_meta, + gdn_state_slots) + : BuildFullAttnStepDevInputs(d, s.positions, s.attn_meta)); MaybeBuildAttnCosSin(d, *s.dev, impl_->config, S, fp4_attn); } const bool has_idx = s.dev->has_gdn_idx && @@ -11388,7 +11423,9 @@ ForwardLogits Qwen3_5DenseDecodeGraph::Step( CheckDensePagedForward(token_ids, positions, attn_meta, gdn_meta, attn_kv, gdn_state, impl_->weights, impl_->config); const int64_t B = static_cast(token_ids.size()); - detail::ValidateGdnDecodeGraphState(gdn_meta, gdn_state, B); + const bool has_gdn = HasGdnConsumers(impl_->weights); + if (has_gdn) detail::ValidateGdnDecodeGraphState(gdn_meta, gdn_state, B); + else ValidateFullAttnStepMetadata(B, attn_meta); Backend& b = vt::GetBackend(impl_->queue.device.type); Dev d{b, impl_->queue}; // #1380: open a fresh demand measurement for this step. `PreGrowForCapture` @@ -11410,7 +11447,7 @@ ForwardLogits Qwen3_5DenseDecodeGraph::Step( // exact shape trivially satisfies that while keeping the padded-row inertness // question out of the spec path. The shape count stays bounded by max_num_seqs // because num_reqs is. - const bool spec_step = gdn_meta.num_spec_decodes > 0; + const bool spec_step = has_gdn && gdn_meta.num_spec_decodes > 0; const int64_t S = spec_step ? B : PadToCaptureSize(B, impl_->max_num_reqs); // ENG-CUDAGRAPH-BREAK W6 (#1374): this step's uniform query length, and the // ring key built from it. `Q == 0` means the batch does not divide evenly into @@ -11429,8 +11466,8 @@ ForwardLogits Qwen3_5DenseDecodeGraph::Step( const bool qlen_capped = DecodeGraphQueryLenCapped(impl_->slots, key); if (qlen_capped) v1::NoteDecodeGraphQueryLenDecline(); if (!impl_->enabled || S < 0 || !servable_shape || qlen_capped || - !detail::CanUseGdnDecodeGraphSize( - B, S, IndexedGdnStateIoEnabled(impl_->queue.device))) { + (has_gdn && !detail::CanUseGdnDecodeGraphSize( + B, S, IndexedGdnStateIoEnabled(impl_->queue.device)))) { if (aux_out != nullptr && !aux_out->layer_ids.empty()) { // The graph cannot serve this batch (disabled / unsupported size), so fall // back to the EAGER multi-tap forward, which fills aux_out itself. Without @@ -11530,7 +11567,10 @@ ForwardLogits Qwen3_5DenseDecodeGraph::Step( pam = attn_meta; pgm = gdn_meta; } else { - BuildPaddedDecode(S, token_ids, positions, attn_meta, gdn_meta, ptok, ppos, + // The padding helper copies GDN indices into S entries. Without consumers, + // the caller's unused metadata has no validated bound and must stay inert. + BuildPaddedDecode(S, token_ids, positions, attn_meta, + has_gdn ? gdn_meta : GDNAttentionMetadata{}, ptok, ppos, pam, pgm); } @@ -11771,8 +11811,10 @@ ForwardLogits Qwen3_5DenseDecodeGraph::Step( s.pin.Free(); { ActivePoolScope persistent_scope(&PersistentDecodeInputPool(d.b)); - s.dev = std::make_unique(BuildStepDevInputs( - d, s.positions, s.attn_meta, s.gdn_meta, gdn_state_slots)); + s.dev = std::make_unique( + has_gdn ? BuildStepDevInputs(d, s.positions, s.attn_meta, s.gdn_meta, + gdn_state_slots) + : BuildFullAttnStepDevInputs(d, s.positions, s.attn_meta)); MaybeBuildAttnCosSin(d, *s.dev, impl_->config, S, fp4_attn); } const bool has_idx = s.dev->has_gdn_idx && diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a3117cc61..2811d051c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2562,6 +2562,7 @@ endif() # C ABI (M3.5 Task 1): the C++ test drives the public C API over a synthetic # engine via the internal MakeEngineHandle hook (reached under src/). vllm_cpp_add_test(test_capi capi/test_capi.cpp) +vllm_cpp_add_test(test_capi_qwen35_full_attn_state capi/test_qwen35_full_attn_state.cpp) target_include_directories(test_capi PRIVATE ${CMAKE_SOURCE_DIR}/src) target_compile_definitions(test_capi PRIVATE PARAKEET_E2E_FIXTURE_DIR="${CMAKE_SOURCE_DIR}/tests/vllm/models/fixtures/parakeet_e2e" diff --git a/tests/capi/qwen35_full_attn_fixture.h b/tests/capi/qwen35_full_attn_fixture.h new file mode 100644 index 000000000..4af83032d --- /dev/null +++ b/tests/capi/qwen35_full_attn_fixture.h @@ -0,0 +1,133 @@ +// ENG-QWEN35-FULL-ATTN-STATE (#3098): one deterministic, all-dense GGUF. +// Extracted from rocm_quant_gather_fixture.h, SHA256 +// 339414f93e59e6be9a4ca545d5e762bb2816714343f466e218dbc2b69483bdfd. +// Keep the dense Q4_0 control byte-identical to that experiment. Its name and +// inactive SSM loader keys are part of the frozen artifact, not active layers. +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "vllm/gguf_builder.h" +#include "vt/dtype.h" +#include "vt/quant.h" + +namespace qwen35_full_attn_test { + +inline constexpr uint32_t kSeed = 0x524f434d; +inline constexpr int64_t kHidden = 256; +inline constexpr int64_t kVocab = 128; +inline constexpr size_t kArtifactBytes = 991296; +inline constexpr const char* kArtifactSha256 = + "0e6554ba521edfde00d4d025a3058eabaaacdce6b24344f959e83d8dde35df7f"; + +inline std::string DenseEmbedding() { + // Q4_0 is only the deterministic source of these BF16 values. The resulting + // GGUF contains a dense embedding and no quantized projection. + constexpr int64_t kBlockBytes = 18; + constexpr int64_t kBlockElems = 32; + constexpr int64_t kBlocks = kVocab * kHidden / kBlockElems; + std::string packed(static_cast(kBlocks * kBlockBytes), '\0'); + std::mt19937 rng(kSeed); + for (int64_t block = 0; block < kBlocks; ++block) { + const size_t base = static_cast(block * kBlockBytes); + for (int64_t byte = 0; byte < kBlockBytes; ++byte) + packed[base + static_cast(byte)] = static_cast(rng() & 255); + packed[base] = 0; + packed[base + 1] = 0x20; // Half d = 1/128, exactly as the frozen control. + } + std::vector decoded(static_cast(kVocab * kHidden)); + const auto decode = vt::cpu::BlockToFloat(vt::DType::kQ4_0); + if (decode == nullptr) throw std::runtime_error("fixture Q4_0 decoder absent"); + decode(packed.data(), decoded.data(), kVocab * kHidden); + std::string dense; + dense.reserve(decoded.size() * 2); + for (float value : decoded) { + if (!std::isfinite(value)) throw std::runtime_error("nonfinite fixture block"); + const uint16_t word = vt::F32ToBF16(value); + dense.push_back(static_cast(word & 255)); + dense.push_back(static_cast(word >> 8)); + } + return dense; +} + +inline std::string BuildModel() { + using namespace gguf_test; + GgufModelBuilder builder; + builder.AddKv(StrKv("general.architecture", "qwen35")); + builder.AddKv(StrKv("general.name", "rocm-quant-gather-synthetic")); + builder.AddKv(U32Kv("general.quantization_version", 2)); + builder.AddKv(U32Kv("qwen35.embedding_length", 256)); + builder.AddKv(U32Kv("qwen35.block_count", 1)); + builder.AddKv(U32Kv("qwen35.attention.head_count", 4)); + builder.AddKv(U32Kv("qwen35.attention.head_count_kv", 1)); + builder.AddKv(U32Kv("qwen35.attention.key_length", 64)); + builder.AddKv(U32Kv("qwen35.attention.value_length", 64)); + builder.AddKv(U32Kv("qwen35.feed_forward_length", 256)); + builder.AddKv(U32Kv("qwen35.full_attention_interval", 1)); + builder.AddKv(U32Kv("qwen35.context_length", 64)); + builder.AddKv(U32Kv("qwen35.vocab_size", 128)); + builder.AddKv(F32Kv("qwen35.attention.layer_norm_rms_epsilon", 1e-6F)); + builder.AddKv(F32Kv("qwen35.rope.freq_base", 1000000.0F)); + builder.AddKv(U32Kv("qwen35.rope.dimension_count", 64)); + builder.AddKv(I32ArrayKv("qwen35.rope.dimension_sections", {16, 8, 8, 0})); + builder.AddKv(U32Kv("qwen35.ssm.conv_kernel", 4)); + builder.AddKv(U32Kv("qwen35.ssm.inner_size", 64)); + builder.AddKv(U32Kv("qwen35.ssm.state_size", 64)); + builder.AddKv(U32Kv("qwen35.ssm.time_step_rank", 1)); + builder.AddKv(U32Kv("qwen35.ssm.group_count", 1)); + builder.AddKv(StrKv("tokenizer.ggml.model", "gpt2")); + builder.AddKv(StrKv("tokenizer.ggml.pre", "qwen2")); + builder.AddKv(U32Kv("tokenizer.ggml.unknown_token_id", 0)); + builder.AddKv(U32Kv("tokenizer.ggml.bos_token_id", 1)); + builder.AddKv(U32Kv("tokenizer.ggml.eos_token_id", 2)); + builder.AddKv(BoolKv("tokenizer.ggml.add_bos_token", false)); + std::vector vocabulary = {"", "", ""}; + for (int id = 3; id < kVocab; ++id) vocabulary.push_back("token" + std::to_string(id)); + builder.AddKv(StrArrayKv("tokenizer.ggml.tokens", vocabulary)); + builder.AddKv(StrArrayKv("tokenizer.ggml.merges", {})); + std::vector types(128, 1); + types[0] = 2; + types[1] = types[2] = 3; + builder.AddKv(I32ArrayKv("tokenizer.ggml.token_type", types)); + builder.AddTensor("token_embd.weight", {256, 128}, 30, DenseEmbedding()); + + std::mt19937 rng(kSeed); + const auto projection = [&](const char* name, uint64_t input, uint64_t output) { + std::string bytes; + bytes.reserve(static_cast(input * output * 2)); + for (uint64_t i = 0; i < input * output; ++i) { + const int32_t integer = static_cast(rng() & 65535) - 32768; + const float value = static_cast(integer) / 2097152.0F; + const uint16_t word = vt::F32ToBF16(value); + bytes.push_back(static_cast(word & 255)); + bytes.push_back(static_cast(word >> 8)); + } + builder.AddTensor(name, {input, output}, 30, bytes); + }; + const auto norm = [&](const char* name, uint64_t width) { + std::string bytes; + for (uint64_t i = 0; i < width; ++i) bytes += U32Le(0x3f800000); + builder.AddTensor(name, {width}, 0, bytes); + }; + projection("output.weight", 256, 128); + projection("blk.0.attn_q.weight", 256, 512); + projection("blk.0.attn_k.weight", 256, 64); + projection("blk.0.attn_v.weight", 256, 64); + projection("blk.0.attn_output.weight", 256, 256); + projection("blk.0.ffn_gate.weight", 256, 256); + projection("blk.0.ffn_up.weight", 256, 256); + projection("blk.0.ffn_down.weight", 256, 256); + norm("output_norm.weight", 256); + norm("blk.0.attn_norm.weight", 256); + norm("blk.0.post_attention_norm.weight", 256); + norm("blk.0.attn_q_norm.weight", 64); + norm("blk.0.attn_k_norm.weight", 64); + return builder.Build(); +} + +} // namespace qwen35_full_attn_test diff --git a/tests/capi/test_qwen35_full_attn_state.cpp b/tests/capi/test_qwen35_full_attn_state.cpp new file mode 100644 index 000000000..388c558b5 --- /dev/null +++ b/tests/capi/test_qwen35_full_attn_state.cpp @@ -0,0 +1,262 @@ +// Public regression for ENG-QWEN35-FULL-ATTN-STATE (#3098). +// Pinned vLLM e126687a9a: qwen3_5.py:144-160 constructs recurrent state +// consumers only for linear_attention layers. This no-GDN case is local. +#define DOCTEST_CONFIG_IMPLEMENT +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "capi/qwen35_full_attn_fixture.h" +#include "vllm.h" +#include "vt/backend.h" +#include "vt/op_provider.h" +#include "vt/ops.h" + +#if defined(VLLM_CPP_HIP) && !defined(VLLM_CPP_CUDA) +namespace vt::rocm { +void EmbeddingKernelRocm(Queue&, Tensor&, const Tensor&, const Tensor&); +void ReshapeAndCacheKernelRocm(Queue&, const Tensor&, const Tensor&, Tensor&, + Tensor&, const Tensor&); +void GreedyArgmaxKernelRocm(Queue&, Tensor&, const Tensor&); +} // namespace vt::rocm +#endif + +namespace { + +std::atomic native_prefills{0}, native_decodes{0}, native_cache_writes{0}; +std::atomic native_samples{0}; +std::atomic wrong_model_dtype{false}; +constexpr const char* kObserver = "qwen35-full-attn-state-observer"; + +#if defined(VLLM_CPP_HIP) && !defined(VLLM_CPP_CUDA) +void ObserveEmbedding(vt::Queue& queue, vt::Tensor& out, + const vt::Tensor& table, const vt::Tensor& ids) { + if (queue.device.type != vt::DeviceType::kROCM || + out.dtype != vt::DType::kBF16 || table.dtype != vt::DType::kBF16) + wrong_model_dtype = true; + // Call the verified native function, then count the completed native call. + // RegisterOp cannot replace vt-native: duplicate provider names are ignored. + vt::rocm::EmbeddingKernelRocm(queue, out, table, ids); + if (ids.Numel() > 1) ++native_prefills; + else ++native_decodes; +} + +void ObserveCache(vt::Queue& queue, const vt::Tensor& key, + const vt::Tensor& value, vt::Tensor& key_cache, + vt::Tensor& value_cache, const vt::Tensor& slots) { + if (key.dtype != vt::DType::kBF16 || value.dtype != vt::DType::kBF16 || + key_cache.dtype != vt::DType::kBF16 || value_cache.dtype != vt::DType::kBF16) + wrong_model_dtype = true; + vt::rocm::ReshapeAndCacheKernelRocm(queue, key, value, key_cache, value_cache, slots); + ++native_cache_writes; +} + +void ObserveGreedy(vt::Queue& queue, vt::Tensor& ids, const vt::Tensor& logits) { + // The existing sampler ABI consumes f32 logits and produces i64 token IDs. + if (queue.device.type != vt::DeviceType::kROCM || + logits.device.type != vt::DeviceType::kROCM || + ids.device.type != vt::DeviceType::kROCM || + logits.dtype != vt::DType::kF32 || ids.dtype != vt::DType::kI64) + wrong_model_dtype = true; + vt::rocm::GreedyArgmaxKernelRocm(queue, ids, logits); + ++native_samples; +} +#endif + +void InstallNativeObservers() { +#if defined(VLLM_CPP_HIP) && !defined(VLLM_CPP_CUDA) + const auto install = [](vt::OpId op, void* native, void* observer) { + REQUIRE(vt::GetOp(op, vt::DeviceType::kROCM) == native); + const auto before = vt::GetOpProviderStats(op, vt::DeviceType::kROCM); + REQUIRE(before.last_selected != nullptr); + REQUIRE(std::string(before.last_selected) == vt::kNativeProviderName); + vt::OpProvider provider; + provider.name = kObserver; + provider.priority = 1; + provider.fn = observer; + vt::RegisterOpProvider(op, vt::DeviceType::kROCM, provider); + REQUIRE(vt::GetOp(op, vt::DeviceType::kROCM) == observer); + }; + install(vt::OpId::kEmbedding, + reinterpret_cast(&vt::rocm::EmbeddingKernelRocm), + reinterpret_cast(&ObserveEmbedding)); + install(vt::OpId::kReshapeAndCache, + reinterpret_cast(&vt::rocm::ReshapeAndCacheKernelRocm), + reinterpret_cast(&ObserveCache)); + install(vt::OpId::kGreedyArgmax, + reinterpret_cast(&vt::rocm::GreedyArgmaxKernelRocm), + reinterpret_cast(&ObserveGreedy)); +#else + throw std::runtime_error("native observers require a HIP-only build"); +#endif +} + +struct Completion { + std::vector ids; + // The public logits-processor ABI supplies f32 logits. This is host evidence, + // not an activation or KV buffer in the model. + std::vector logits; + bool capture_overflow = false; + int callbacks = 0; +}; + +// Reserve the full callback output before entering the C ABI. This callback +// cannot throw or change the logits that the greedy sampler reads. +void Capture(const int32_t*, int32_t, float* logits, int32_t vocab, void* data) { + auto& result = *static_cast(data); + if (vocab != 128 || result.callbacks >= 4) { + result.capture_overflow = true; + return; + } + for (int32_t i = 0; i < vocab; ++i) result.logits.push_back(logits[i]); + ++result.callbacks; +} + +Completion Run(const std::string& path, const std::vector& prompt, + int repeat, size_t prompt_index, bool capture_logits) { + auto model = vllm_model_params_default(); + model.model_path = path.c_str(); + model.device = 0; // Public AUTO in the required HIP-only build. + model.block_size = 16; + model.num_blocks = 4; + model.max_model_len = 64; + model.max_num_seqs = 1; + model.kv_cache_dtype = "auto"; + vllm_engine* raw = nullptr; + const vllm_status loaded = vllm_engine_load(&model, &raw); + INFO("public load: " << vllm_last_error()); + REQUIRE(loaded == VLLM_OK); + std::unique_ptr engine(raw, &vllm_engine_free); + std::printf("FULL_ATTN public load succeeded repeat=%d prompt=%zu\n", repeat, prompt_index); + std::fflush(stdout); + + Completion result; + result.ids.resize(4); + result.logits.reserve(4 * 128); + auto sampling = vllm_sampling_params_default(); + sampling.temperature = 0.0F; + sampling.max_tokens = 4; + sampling.ignore_eos = 1; + sampling.has_seed = 1; + sampling.seed = qwen35_full_attn_test::kSeed; + if (capture_logits) { + sampling.logits_processor = Capture; + sampling.logits_processor_user_data = &result; + } + native_prefills = 0; + native_decodes = 0; + native_cache_writes = 0; + native_samples = 0; + wrong_model_dtype = false; + const auto hits_before = vt::GetReferenceTierHits(); + vt::ResetOpProviderStats(vt::OpId::kEmbedding, vt::DeviceType::kROCM); + vt::EnableOpProviderCallStats(true); + int32_t count = 0; + const vllm_status completed = vllm_complete_tokens( + engine.get(), prompt.data(), static_cast(prompt.size()), &sampling, + result.ids.data(), 4, &count, nullptr); + vt::EnableOpProviderCallStats(false); + INFO("public completion: " << vllm_last_error()); + REQUIRE(completed == VLLM_OK); + REQUIRE(count == 4); + REQUIRE_FALSE(result.capture_overflow); + REQUIRE(result.callbacks == (capture_logits ? 4 : 0)); + REQUIRE(result.logits.size() == (capture_logits ? 512 : 0)); + for (float value : result.logits) CHECK(std::isfinite(value)); + for (int32_t id : result.ids) CHECK((id >= 0 && id < 128)); + CHECK(native_prefills.load() == 1); + CHECK(native_decodes.load() == 3); + CHECK(native_cache_writes.load() == 4); + CHECK(native_samples.load() == 4); + CHECK_FALSE(wrong_model_dtype.load()); + CHECK(vt::GetReferenceTierHits() == hits_before); + const auto stats = vt::GetOpProviderStats(vt::OpId::kEmbedding, vt::DeviceType::kROCM); + CHECK(stats.selections >= 4); + CHECK(stats.declines == 0); + CHECK(stats.fallbacks == 0); + REQUIRE(stats.last_selected != nullptr); + CHECK(std::string(stats.last_selected) == kObserver); + std::printf("FULL_ATTN repeat=%d prompt=%zu capture_logits=%d fresh_engine=1 concurrency=1 " + "prompt_tokens=%zu native_prefills=%d native_decodes=%d " + "native_cache_writes=%d native_samples=%d activation=bf16 kv=bf16 " + "finite_logits=%zu tokens=", + repeat, prompt_index, capture_logits, prompt.size(), native_prefills.load(), + native_decodes.load(), native_cache_writes.load(), native_samples.load(), + result.logits.size()); + for (int32_t id : result.ids) std::printf(" %d", id); + std::printf("\n"); + return result; +} + +void WriteFixture(const std::filesystem::path& path) { + const auto bytes = qwen35_full_attn_test::BuildModel(); + if (bytes.size() != qwen35_full_attn_test::kArtifactBytes) + throw std::runtime_error("full-attention fixture size changed"); + if (!path.parent_path().empty()) std::filesystem::create_directories(path.parent_path()); + std::ofstream file(path, std::ios::binary); + file.write(bytes.data(), static_cast(bytes.size())); + if (!file) throw std::runtime_error("cannot write full-attention fixture"); +} + +} // namespace + +TEST_CASE("Qwen3.5 full-attention state enters public load and completion") { + const auto bytes = qwen35_full_attn_test::BuildModel(); + REQUIRE(bytes.size() == qwen35_full_attn_test::kArtifactBytes); + CHECK(bytes == qwen35_full_attn_test::BuildModel()); + gguf_test::TempFile fixture(bytes); + InstallNativeObservers(); + const std::vector> prompts = {{1, 0, 63, 127, 63}, {1, 127, 0, 127}}; + std::vector first(2 * prompts.size()); + // builtin.cpp::apply_logits_processors stages logits through the host when a + // callback exists. Both modes still execute the native device argmax, but + // the callback-free arm proves the default public route without that staging. + for (bool capture_logits : {false, true}) { + CAPTURE(capture_logits); + for (int repeat = 0; repeat < 3; ++repeat) { + CAPTURE(repeat); + for (size_t p = 0; p < prompts.size(); ++p) { + CAPTURE(p); + const Completion result = Run(fixture.path(), prompts[p], repeat, p, capture_logits); + Completion& baseline = first[static_cast(capture_logits) * prompts.size() + p]; + if (repeat == 0) baseline = result; + else { + CHECK(result.ids == baseline.ids); + REQUIRE(result.logits.size() == baseline.logits.size()); + if (capture_logits) + CHECK(std::memcmp(result.logits.data(), baseline.logits.data(), + result.logits.size() * sizeof(float)) == 0); + } + if (capture_logits) CHECK(result.ids == first[p].ids); + } + } + } +} + +int main(int argc, char** argv) { + if (argc == 3 && std::string(argv[1]) == "--write-fixture") { + WriteFixture(argv[2]); + return 0; + } +#if defined(VLLM_CPP_HIP) && !defined(VLLM_CPP_CUDA) + try { + vt::GetBackend(vt::DeviceType::kROCM); + } catch (const std::runtime_error& error) { + std::printf("SKIPPED: ROCm device unavailable: %s\n", error.what()); + return 77; + } + doctest::Context context(argc, argv); + return context.run(); +#else + std::puts("SKIPPED: public AUTO regression requires a HIP-only build"); + return 77; +#endif +} diff --git a/tests/vllm/models/test_qwen27_paged_forward.cpp b/tests/vllm/models/test_qwen27_paged_forward.cpp index 9c88ec94d..2ea5d878e 100644 --- a/tests/vllm/models/test_qwen27_paged_forward.cpp +++ b/tests/vllm/models/test_qwen27_paged_forward.cpp @@ -1348,6 +1348,205 @@ TEST_CASE("qwen27 packed QKV uses maximum CT logical-shard divisors") { std::runtime_error); } + +namespace { + +// ENG-QWEN35-FULL-ATTN-STATE (#3098). Enter the registered forward, with the +// existing CPU fixture's f32 cache representation and unchanged tolerances. +TEST_CASE("qwen27 full-attention registry accepts unused GDN metadata") { + HfConfig c = MakeConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + const Qwen3_5DenseWeights w = MakeWeights(c); + CachePool pool(c, 4, 8); + REQUIRE(pool.gdn_state.empty()); + bool runner_metadata = false; + SUBCASE("default-empty GDN metadata") {} + SUBCASE("unused runner GDN metadata") { runner_metadata = true; } + SUBCASE("the loaded layers determine consumers") { + // The loaded consumer wins over a stale configuration label. + c.layer_types = {"linear_attention"}; + runner_metadata = true; + } + auto model = vllm::BorrowQwen3_5DenseLoadedModel(w); + vt::Queue q = Q(); + const std::vector indices; + const auto host = [&](const vllm::ForwardLogits& logits) { + std::vector out; + if (logits.on_device()) { + out.resize(static_cast(logits.rows * logits.vocab)); + auto& backend = vt::GetBackend(q.device.type); + backend.Copy(q, out.data(), logits.device_tensor.data, out.size() * sizeof(float)); + backend.Synchronize(q); + } else { + out = logits.host; + } + for (float value : out) CHECK(std::isfinite(value)); + return out; + }; + + const std::vector ids = {5, 9, 2}; + const std::vector positions = {0, 1, 2}; + const auto am = PrefillAttnMeta(3, {0}, 8, 0); + const auto gm = runner_metadata ? PrefillGdnMeta(3, 0) : GDNAttentionMetadata{}; + ModelForwardInput prefill{ids, positions, am, gm, pool.attn_kv, pool.gdn_state, + c, q, indices}; + prefill.num_reqs = 1; + const auto prefill_logits = host(ModelRegistry::Forward(*model, prefill)); + REQUIRE(prefill_logits.size() == static_cast(3 * c.vocab_size)); + const auto dense_prefill = Qwen3_5DenseModel::ForwardDense(ids, positions, w, c, q); + CHECK(MaxAbsDiff(prefill_logits, dense_prefill, prefill_logits.size()) < 1e-2); + + const std::vector next = {8}, next_positions = {3}; + auto decode_am = PrefillAttnMeta(1, {0}, 8, 3); + decode_am.seq_lens = decode_am.seq_lens_cpu = {4}; + decode_am.max_seq_len = 4; + GDNAttentionMetadata decode_gm; + if (runner_metadata) { + decode_gm.num_decodes = decode_gm.num_decode_tokens = 1; + decode_gm.num_actual_tokens = 1; + decode_gm.non_spec_state_indices_tensor = std::vector{0}; + decode_gm.non_spec_query_start_loc = std::vector{0, 1}; + } + ModelForwardInput decode{next, next_positions, decode_am, decode_gm, pool.attn_kv, + pool.gdn_state, c, q, indices}; + decode.num_reqs = 1; + decode.pure_decode = true; + const auto decode_logits = host(ModelRegistry::Forward(*model, decode)); + REQUIRE(decode_logits.size() == static_cast(c.vocab_size)); + const auto dense_full = Qwen3_5DenseModel::ForwardDense({5, 9, 2, 8}, {0, 1, 2, 3}, w, c, q); + const std::vector last(dense_full.end() - c.vocab_size, dense_full.end()); + CHECK(MaxAbsDiff(decode_logits, last, decode_logits.size()) < 2e-2); +} + +TEST_CASE("qwen27 full-attention registry keeps generic counts") { + HfConfig c = MakeConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + Qwen3_5DenseWeights w = MakeWeights(c); + CachePool pool(c, 4, 8); + const std::vector ids = {5}, indices; + std::vector positions = {0}; + auto am = PrefillAttnMeta(1, {0}, 8, 0); + const GDNAttentionMetadata gm; + const char* expected = nullptr; + SUBCASE("positions") { positions.clear(); expected = "positions length"; } + SUBCASE("attention token count") { + am.num_actual_tokens = 2; + expected = "attn_meta.num_actual_tokens"; + } + SUBCASE("layer count") { w.layers.clear(); expected = "weights.layers size"; } + SUBCASE("attention cache count") { pool.attn_kv.clear(); expected = "attn_kv count"; } + SUBCASE("unexpected recurrent cache") { + pool.gdn_state.emplace_back(); + expected = "gdn_state count"; + } + REQUIRE(expected != nullptr); + auto model = vllm::BorrowQwen3_5DenseLoadedModel(w); + vt::Queue q = Q(); + ModelForwardInput input{ids, positions, am, gm, pool.attn_kv, pool.gdn_state, c, q, indices}; + input.num_reqs = 1; + CHECK_THROWS_WITH_AS(ModelRegistry::Forward(*model, input), + doctest::Contains(expected), std::runtime_error); +} + +TEST_CASE("qwen27 registry preserves each hybrid GDN guard") { + const HfConfig c = MakeConfig(); + const Qwen3_5DenseWeights w = MakeWeights(c); + CachePool pool(c, 3, 8); + REQUIRE(pool.gdn_state.size() == 3); + std::vector ids = {5, 9}, positions = {0, 0}; + const std::vector indices; + auto am = PrefillAttnMeta(2, {0, 1}, 8, 0); + am.num_reqs = 2; + am.max_query_len = am.max_seq_len = 1; + am.query_start_loc = am.query_start_loc_cpu = {0, 1, 2}; + am.seq_lens = am.seq_lens_cpu = {1, 1}; + am.block_table_num_cols = 1; + am.slot_mapping = {0, 8}; + GDNAttentionMetadata gm; + gm.num_actual_tokens = gm.num_decodes = gm.num_decode_tokens = 2; + gm.non_spec_state_indices_tensor = std::vector{0, 1}; + gm.non_spec_query_start_loc = std::vector{0, 1, 2}; + const char* expected = nullptr; + SUBCASE("valid hybrid") {} + SUBCASE("all GDN caches missing") { + pool.gdn_state.clear(); + expected = "gdn_state count"; + } + SUBCASE("wrong GDN cache count") { + pool.gdn_state.pop_back(); + expected = "gdn_state count"; + } + SUBCASE("invalid SSM rank") { + pool.gdn_state.back().ssm_state.rank = 3; + expected = "GDN SSM/conv state ranks"; + } + SUBCASE("invalid convolution rank") { + pool.gdn_state.back().conv_state.rank = 4; + expected = "GDN SSM/conv state ranks"; + } + SUBCASE("mismatched SSM and convolution slots") { + pool.gdn_state.back().conv_state.shape[0] = 2; + expected = "GDN conv/SSM state slot counts"; + } + SUBCASE("inconsistent layer slots") { + pool.gdn_state.back().ssm_state.shape[0] = 2; + pool.gdn_state.back().conv_state.shape[0] = 2; + expected = "all GDN layers must use the same state slot count"; + } + SUBCASE("missing metadata") { + gm = GDNAttentionMetadata{}; + expected = "gdn_meta.num_actual_tokens"; + } + SUBCASE("wrong GDN token count") { + gm.num_actual_tokens = 1; + expected = "gdn_meta.num_actual_tokens"; + } + SUBCASE("missing indices") { + gm.non_spec_state_indices_tensor.reset(); + expected = "missing non-spec GDN state indices"; + } + SUBCASE("duplicate indices") { + gm.non_spec_state_indices_tensor = std::vector{0, 0}; + expected = "duplicate live GDN state index"; + } + SUBCASE("out-of-range indices") { + gm.non_spec_state_indices_tensor = std::vector{0, 3}; + expected = "GDN state index out of range"; + } + SUBCASE("incomplete prefill metadata") { + am = PrefillAttnMeta(2, {0}, 8, 0); + positions = {0, 1}; + gm = PrefillGdnMeta(2, 0); + gm.prefill_has_initial_state.reset(); + expected = "incomplete GDN prefill metadata"; + } + auto model = vllm::BorrowQwen3_5DenseLoadedModel(w); + vt::Queue q = Q(); + ModelForwardInput input{ids, positions, am, gm, pool.attn_kv, pool.gdn_state, c, q, indices}; + input.num_reqs = am.num_reqs; + if (expected != nullptr) { + CHECK_THROWS_WITH_AS(ModelRegistry::Forward(*model, input), + doctest::Contains(expected), std::runtime_error); + } else { + const auto logits = ModelRegistry::Forward(*model, input); + REQUIRE(logits.rows == 2); + REQUIRE(logits.vocab == c.vocab_size); + std::vector host = logits.host; + if (logits.on_device()) { + host.resize(static_cast(2 * c.vocab_size)); + auto& backend = vt::GetBackend(q.device.type); + backend.Copy(q, host.data(), logits.device_tensor.data, host.size() * sizeof(float)); + backend.Synchronize(q); + } + REQUIRE(host.size() == static_cast(2 * c.vocab_size)); + for (float value : host) CHECK(std::isfinite(value)); + } +} + +} // namespace + TEST_CASE("qwen27 dense paged: full-prefill batch-of-1 equals dense forward") { const HfConfig c = MakeConfig(); const Qwen3_5DenseWeights w = MakeWeights(c); diff --git a/tests/vllm/models/test_qwen35_paged_forward.cpp b/tests/vllm/models/test_qwen35_paged_forward.cpp index 9c5b05a15..62cc52da2 100644 --- a/tests/vllm/models/test_qwen35_paged_forward.cpp +++ b/tests/vllm/models/test_qwen35_paged_forward.cpp @@ -301,6 +301,205 @@ double MaxAbsDiff(const std::vector& a, const std::vector& b, size } // namespace + +namespace { + +// ENG-QWEN35-FULL-ATTN-STATE (#3098). Enter the registered forward, with the +// existing CPU fixture's f32 cache representation and unchanged tolerances. +TEST_CASE("qwen35 full-attention registry accepts unused GDN metadata") { + HfConfig c = MakeConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + const Qwen3_5MoeWeights w = MakeWeights(c); + CachePool pool(c, 4, 8); + REQUIRE(pool.gdn_state.empty()); + bool runner_metadata = false; + SUBCASE("default-empty GDN metadata") {} + SUBCASE("unused runner GDN metadata") { runner_metadata = true; } + SUBCASE("the loaded layers determine consumers") { + // The loaded consumer wins over a stale configuration label. + c.layer_types = {"linear_attention"}; + runner_metadata = true; + } + auto model = vllm::BorrowQwen3_5MoeLoadedModel(w); + vt::Queue q = Q(); + const std::vector indices; + const auto host = [&](const vllm::ForwardLogits& logits) { + std::vector out; + if (logits.on_device()) { + out.resize(static_cast(logits.rows * logits.vocab)); + auto& backend = vt::GetBackend(q.device.type); + backend.Copy(q, out.data(), logits.device_tensor.data, out.size() * sizeof(float)); + backend.Synchronize(q); + } else { + out = logits.host; + } + for (float value : out) CHECK(std::isfinite(value)); + return out; + }; + + const std::vector ids = {5, 9, 2}; + const std::vector positions = {0, 1, 2}; + const auto am = PrefillAttnMeta(3, {0}, 8, 0); + const auto gm = runner_metadata ? PrefillGdnMeta(3, 0) : GDNAttentionMetadata{}; + ModelForwardInput prefill{ids, positions, am, gm, pool.attn_kv, pool.gdn_state, + c, q, indices}; + prefill.num_reqs = 1; + const auto prefill_logits = host(ModelRegistry::Forward(*model, prefill)); + REQUIRE(prefill_logits.size() == static_cast(3 * c.vocab_size)); + const auto dense_prefill = Qwen3_5Model::ForwardDense(ids, positions, w, c, q); + CHECK(MaxAbsDiff(prefill_logits, dense_prefill, prefill_logits.size()) < 1e-2); + + const std::vector next = {8}, next_positions = {3}; + auto decode_am = PrefillAttnMeta(1, {0}, 8, 3); + decode_am.seq_lens = decode_am.seq_lens_cpu = {4}; + decode_am.max_seq_len = 4; + GDNAttentionMetadata decode_gm; + if (runner_metadata) { + decode_gm.num_decodes = decode_gm.num_decode_tokens = 1; + decode_gm.num_actual_tokens = 1; + decode_gm.non_spec_state_indices_tensor = std::vector{0}; + decode_gm.non_spec_query_start_loc = std::vector{0, 1}; + } + ModelForwardInput decode{next, next_positions, decode_am, decode_gm, pool.attn_kv, + pool.gdn_state, c, q, indices}; + decode.num_reqs = 1; + decode.pure_decode = true; + const auto decode_logits = host(ModelRegistry::Forward(*model, decode)); + REQUIRE(decode_logits.size() == static_cast(c.vocab_size)); + const auto dense_full = Qwen3_5Model::ForwardDense({5, 9, 2, 8}, {0, 1, 2, 3}, w, c, q); + const std::vector last(dense_full.end() - c.vocab_size, dense_full.end()); + CHECK(MaxAbsDiff(decode_logits, last, decode_logits.size()) < 2e-2); +} + +TEST_CASE("qwen35 full-attention registry keeps generic counts") { + HfConfig c = MakeConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + Qwen3_5MoeWeights w = MakeWeights(c); + CachePool pool(c, 4, 8); + const std::vector ids = {5}, indices; + std::vector positions = {0}; + auto am = PrefillAttnMeta(1, {0}, 8, 0); + const GDNAttentionMetadata gm; + const char* expected = nullptr; + SUBCASE("positions") { positions.clear(); expected = "positions length"; } + SUBCASE("attention token count") { + am.num_actual_tokens = 2; + expected = "attn_meta.num_actual_tokens"; + } + SUBCASE("layer count") { w.layers.clear(); expected = "weights.layers size"; } + SUBCASE("attention cache count") { pool.attn_kv.clear(); expected = "attn_kv count"; } + SUBCASE("unexpected recurrent cache") { + pool.gdn_state.emplace_back(); + expected = "gdn_state count"; + } + REQUIRE(expected != nullptr); + auto model = vllm::BorrowQwen3_5MoeLoadedModel(w); + vt::Queue q = Q(); + ModelForwardInput input{ids, positions, am, gm, pool.attn_kv, pool.gdn_state, c, q, indices}; + input.num_reqs = 1; + CHECK_THROWS_WITH_AS(ModelRegistry::Forward(*model, input), + doctest::Contains(expected), std::runtime_error); +} + +TEST_CASE("qwen35 registry preserves each hybrid GDN guard") { + const HfConfig c = MakeConfig(); + const Qwen3_5MoeWeights w = MakeWeights(c); + CachePool pool(c, 3, 8); + REQUIRE(pool.gdn_state.size() == 3); + std::vector ids = {5, 9}, positions = {0, 0}; + const std::vector indices; + auto am = PrefillAttnMeta(2, {0, 1}, 8, 0); + am.num_reqs = 2; + am.max_query_len = am.max_seq_len = 1; + am.query_start_loc = am.query_start_loc_cpu = {0, 1, 2}; + am.seq_lens = am.seq_lens_cpu = {1, 1}; + am.block_table_num_cols = 1; + am.slot_mapping = {0, 8}; + GDNAttentionMetadata gm; + gm.num_actual_tokens = gm.num_decodes = gm.num_decode_tokens = 2; + gm.non_spec_state_indices_tensor = std::vector{0, 1}; + gm.non_spec_query_start_loc = std::vector{0, 1, 2}; + const char* expected = nullptr; + SUBCASE("valid hybrid") {} + SUBCASE("all GDN caches missing") { + pool.gdn_state.clear(); + expected = "gdn_state count"; + } + SUBCASE("wrong GDN cache count") { + pool.gdn_state.pop_back(); + expected = "gdn_state count"; + } + SUBCASE("invalid SSM rank") { + pool.gdn_state.back().ssm_state.rank = 3; + expected = "GDN SSM/conv state ranks"; + } + SUBCASE("invalid convolution rank") { + pool.gdn_state.back().conv_state.rank = 4; + expected = "GDN SSM/conv state ranks"; + } + SUBCASE("mismatched SSM and convolution slots") { + pool.gdn_state.back().conv_state.shape[0] = 2; + expected = "GDN conv/SSM state slot counts"; + } + SUBCASE("inconsistent layer slots") { + pool.gdn_state.back().ssm_state.shape[0] = 2; + pool.gdn_state.back().conv_state.shape[0] = 2; + expected = "all GDN layers must use the same state slot count"; + } + SUBCASE("missing metadata") { + gm = GDNAttentionMetadata{}; + expected = "gdn_meta.num_actual_tokens"; + } + SUBCASE("wrong GDN token count") { + gm.num_actual_tokens = 1; + expected = "gdn_meta.num_actual_tokens"; + } + SUBCASE("missing indices") { + gm.non_spec_state_indices_tensor.reset(); + expected = "missing non-spec GDN state indices"; + } + SUBCASE("duplicate indices") { + gm.non_spec_state_indices_tensor = std::vector{0, 0}; + expected = "duplicate live GDN state index"; + } + SUBCASE("out-of-range indices") { + gm.non_spec_state_indices_tensor = std::vector{0, 3}; + expected = "GDN state index out of range"; + } + SUBCASE("incomplete prefill metadata") { + am = PrefillAttnMeta(2, {0}, 8, 0); + positions = {0, 1}; + gm = PrefillGdnMeta(2, 0); + gm.prefill_has_initial_state.reset(); + expected = "incomplete GDN prefill metadata"; + } + auto model = vllm::BorrowQwen3_5MoeLoadedModel(w); + vt::Queue q = Q(); + ModelForwardInput input{ids, positions, am, gm, pool.attn_kv, pool.gdn_state, c, q, indices}; + input.num_reqs = am.num_reqs; + if (expected != nullptr) { + CHECK_THROWS_WITH_AS(ModelRegistry::Forward(*model, input), + doctest::Contains(expected), std::runtime_error); + } else { + const auto logits = ModelRegistry::Forward(*model, input); + REQUIRE(logits.rows == 2); + REQUIRE(logits.vocab == c.vocab_size); + std::vector host = logits.host; + if (logits.on_device()) { + host.resize(static_cast(2 * c.vocab_size)); + auto& backend = vt::GetBackend(q.device.type); + backend.Copy(q, host.data(), logits.device_tensor.data, host.size() * sizeof(float)); + backend.Synchronize(q); + } + REQUIRE(host.size() == static_cast(2 * c.vocab_size)); + for (float value : host) CHECK(std::isfinite(value)); + } +} + +} // namespace + TEST_CASE("qwen35 paged: full-prefill batch-of-1 equals dense forward") { const HfConfig c = MakeConfig(); const Qwen3_5MoeWeights w = MakeWeights(c); diff --git a/tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp b/tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp index e613831f6..c23223ae1 100644 --- a/tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp +++ b/tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp @@ -42,6 +42,7 @@ #include "decode_graph_seam_harness.h" #include "vllm/model_executor/models/device_pool.h" +#include "vllm/model_executor/models/model_registry.h" #include "vllm/model_executor/models/qwen3_5.h" #include "vllm/model_executor/models/qwen3_5_dense.h" #include "vllm/transformers_utils/hf_config.h" @@ -974,6 +975,303 @@ bool PoolBypassLane() { } // namespace + +namespace { + +CommonAttentionMetadata FullAttnDecodeMeta(int32_t batch, int32_t position) { + auto am = DecodeAttnMeta(position); + am.num_reqs = am.num_actual_tokens = batch; + am.query_start_loc.clear(); + am.seq_lens.assign(static_cast(batch), position + 1); + am.block_table_tensor.clear(); + am.slot_mapping.clear(); + for (int32_t r = 0; r < batch; ++r) { + am.query_start_loc.push_back(r); + am.block_table_tensor.push_back(r); + am.slot_mapping.push_back(static_cast(r) * 16 + position); + } + am.query_start_loc.push_back(batch); + am.query_start_loc_cpu = am.query_start_loc; + am.seq_lens_cpu = am.seq_lens; + return am; +} + +GDNAttentionMetadata UnusedGdnMeta(int32_t batch, int mode) { + GDNAttentionMetadata gm; + if (mode == 0) return gm; + gm.num_decodes = gm.num_decode_tokens = gm.num_actual_tokens = batch; + gm.non_spec_state_indices_tensor = std::vector(static_cast(batch)); + for (int32_t r = 0; r < batch; ++r) + (*gm.non_spec_state_indices_tensor)[static_cast(r)] = r; + if (mode == 2) { + // No GDN consumer can read any of this metadata. In particular, graph + // padding must not copy this vector into an S-entry destination. + gm.non_spec_state_indices_tensor->assign(4096, 777); + gm.num_actual_tokens = -7; + gm.num_spec_decodes = 999; + } + return gm; +} + +template +void FullAttnGraphRouting(const HfConfig& c, const Weights& w) { + for (bool capture : {false, true}) { + CAPTURE(capture); + for (bool async : {false, true}) { + CAPTURE(async); + for (int mode : {0, 1, 2}) { + CAPTURE(mode); + for (int32_t batch : {1, 3}) { + CAPTURE(batch); + StaticGraphCpu harness(capture); + const ScopedEnv async_mode("VT_ASYNC_EXECUTOR", async ? "1" : "0"); + // Padding from three requests to four needs no GDN state I/O. + const ScopedEnv no_indexed_state("VT_GDN_INDEXED_STATE_IO", "0"); + CachePool pool(c, 4, 16); + REQUIRE(pool.gdn_state.empty()); + vt::Queue q = Q(); + vt::ResetGraphBreakStats(); + vt::ResetStepInputStats(); + Graph graph(w, c, q, 4); + for (int32_t step = 0; step < 6; ++step) { + const std::vector ids(static_cast(batch), 11 + step); + const std::vector positions(static_cast(batch), step); + const auto logits = graph.Step(ids, positions, FullAttnDecodeMeta(batch, step), + UnusedGdnMeta(batch, mode), pool.attn_kv, + pool.gdn_state); + REQUIRE(logits.rows == batch); + REQUIRE(logits.vocab == c.vocab_size); + REQUIRE(logits.on_device()); + if (step == 0) { + CHECK_FALSE(graph.captured()); + CHECK(vt::GetGraphBreakStats().segments_captured == 0); + } + } + const auto graphs = vt::GetGraphBreakStats(); + const auto inputs = vt::GetStepInputStats(); + if (capture) { + CHECK(graph.captured()); + CHECK(graphs.segments_captured == (async ? 2 : 1)); + CHECK(graphs.replays == (async ? 4 : 5)); + CHECK(graph.replay_count() == (async ? 4 : 5)); + // Exactly five generic inputs per slot. A sixth input means the + // no-consumer path still binds recurrent state indices. + CHECK(inputs.binds == (async ? 10 : 0)); + CHECK(inputs.host_refreshes == (async ? 10 : 0)); + } else { + CHECK_FALSE(graph.captured()); + CHECK(graphs.segments_captured == 0); + CHECK(graphs.replays == 0); + CHECK(inputs.binds == 0); + CHECK(inputs.host_refreshes == 0); + } + CHECK(inputs.device_refreshes == 0); + } + } + } + } + MESSAGE("CPU fake graph: cold, capture, staging, replay, and fallback routing only; " + "no GPU replay numerics"); +} + +template +void FullAttnGraphShapeGuards(const HfConfig& c, const Weights& w) { + StaticGraphCpu harness; + CachePool pool(c, 4, 16); + vt::Queue q = Q(); + Graph graph(w, c, q, 4); + auto am = DecodeAttnMeta(0); + const char* expected = nullptr; + SUBCASE("oversized slot mapping") { + am.slot_mapping.push_back(0); + expected = "slot_mapping"; + } + SUBCASE("oversized sequence lengths") { + am.seq_lens.push_back(1); + expected = "full-attn metadata shapes"; + } + SUBCASE("oversized query offsets") { + am.query_start_loc.push_back(1); + expected = "full-attn metadata shapes"; + } + SUBCASE("oversized block table") { + am.block_table_tensor.push_back(0); + expected = "block table"; + } + SUBCASE("query offsets do not cover the batch") { + am.query_start_loc.back() = 2; + expected = "query offsets"; + } + REQUIRE(expected != nullptr); + CHECK_THROWS_WITH_AS(graph.Step({11}, {0}, am, {}, pool.attn_kv, pool.gdn_state), + doctest::Contains(expected), std::runtime_error); +} + +// A scoped routing witness, not a new backend. The real CPU backend and all +// native CPU arithmetic remain in use. Only the MoE registry's existing FP4 +// capability predicate receives a test answer. The fake graph replays no math. +class ScopedFp4GraphCapability final : public vllm::platforms::Platform { + public: + ScopedFp4GraphCapability() + : previous_(vllm::platforms::GetPlatform(vt::DeviceType::kCPU)) { + vllm::platforms::RegisterPlatform(vt::DeviceType::kCPU, this); + } + ~ScopedFp4GraphCapability() override { + vllm::platforms::RegisterPlatform(vt::DeviceType::kCPU, &previous_); + } + vt::DeviceType device_type() const override { return previous_.device_type(); } + vt::Backend& backend() const override { return previous_.backend(); } + vllm::platforms::DeviceCapability get_device_capability() const override { + return previous_.get_device_capability(); + } + std::vector supported_dtypes() const override { + return previous_.supported_dtypes(); + } + vllm::platforms::ResidencyPolicy residency_policy() const override { + return previous_.residency_policy(); + } + bool support_static_graph_mode() const override { return true; } + bool cutlass_fp4_supported() const override { return true; } + + private: + vllm::platforms::Platform& previous_; +}; + +// The existing MakeNvfp4W4A16 test pattern, with finite nonzero E2M1 values and +// E4M3 scales. K and N are the CPU model's real expert projection dimensions. +vllm::Nvfp4Weight RoutingFp4(int64_t n, int64_t k) { + vllm::Nvfp4Weight w; + w.n = n; + w.k = k; + w.scale2 = 1.0F; + w.packed.dtype = w.scale.dtype = DType::kI8; + w.packed.rank = w.scale.rank = 2; + w.packed.shape[0] = w.scale.shape[0] = n; + w.packed.shape[1] = k / 2; + w.scale.shape[1] = k / 16; + w.packed.bytes.assign(static_cast(n * k / 2), 0x21); + w.scale.bytes.assign(static_cast(n * k / 16), 0x20); + return w; +} + +void AddRoutingFp4(Qwen3_5MoeWeights& w, const HfConfig& c) { + for (auto& layer : w.layers) { + auto& moe = layer.moe; + moe.expert_gate.clear(); + moe.expert_up.clear(); + moe.expert_down.clear(); + for (int64_t expert = 0; expert < c.num_experts; ++expert) { + moe.expert_gate_fp4.push_back(RoutingFp4(c.moe_intermediate_size, c.hidden_size)); + moe.expert_up_fp4.push_back(RoutingFp4(c.moe_intermediate_size, c.hidden_size)); + moe.expert_down_fp4.push_back(RoutingFp4(c.hidden_size, c.moe_intermediate_size)); + } + moe.shared_gate_proj = OwnedTensor{}; + moe.shared_up_proj = OwnedTensor{}; + moe.shared_down_proj = OwnedTensor{}; + moe.shared_gate_proj_fp4 = RoutingFp4(c.shared_expert_intermediate_size, c.hidden_size); + moe.shared_up_proj_fp4 = RoutingFp4(c.shared_expert_intermediate_size, c.hidden_size); + moe.shared_down_proj_fp4 = RoutingFp4(c.hidden_size, c.shared_expert_intermediate_size); + } +} + +void RegistryFullAttnGraph(vllm::LoadedModel& model, const HfConfig& c, bool expect_graph) { + CachePool pool(c, 4, 16); + vt::Queue q = Q(); + const std::vector indices; + CHECK(model.registration().architecture == c.architectures.front()); + CHECK(model.registration().factory == vllm::RegistrationFor(c.architectures.front()).factory); + vt::ResetGraphBreakStats(); + vt::ResetStepInputStats(); + for (int32_t step = 0; step < 6; ++step) { + const std::vector ids = {11 + step}, positions = {step}; + const auto am = DecodeAttnMeta(step); + const auto gm = UnusedGdnMeta(1, 2); + vllm::ModelForwardInput input{ids, positions, am, gm, pool.attn_kv, + pool.gdn_state, c, q, indices}; + input.num_reqs = 1; + input.pure_decode = true; + input.uniform_query_len = 1; + // The legacy planner group carries capacity even without a state consumer. + input.gdn_state_slots = 4; + const auto logits = vllm::ModelRegistry::Forward(model, input); + REQUIRE(logits.rows == 1); + REQUIRE(logits.vocab == c.vocab_size); + } + const auto graphs = vt::GetGraphBreakStats(); + CHECK(graphs.segments_captured == (expect_graph ? 2 : 0)); + CHECK(graphs.replays == (expect_graph ? 4 : 0)); + CHECK(vt::GetStepInputStats().binds == (expect_graph ? 10 : 0)); + CHECK(vt::GetStepInputStats().host_refreshes == (expect_graph ? 10 : 0)); +} + +} // namespace + +TEST_CASE("full-attention dense graph ignores unused GDN state") { + HfConfig c = dense::TinyConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + const auto w = dense::MakeWeights(c); + FullAttnGraphRouting(c, w); +} + +TEST_CASE("full-attention MoE graph ignores unused GDN state") { + HfConfig c = TinyConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + const auto w = MakeWeights(c); + FullAttnGraphRouting(c, w); +} + +TEST_CASE("full-attention dense graph keeps attention shape guards") { + HfConfig c = dense::TinyConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + const auto w = dense::MakeWeights(c); + FullAttnGraphShapeGuards(c, w); +} + +TEST_CASE("full-attention MoE graph keeps attention shape guards") { + HfConfig c = TinyConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + const auto w = MakeWeights(c); + FullAttnGraphShapeGuards(c, w); +} + +TEST_CASE("full-attention registry reaches the dense graph Step") { + StaticGraphCpu harness; + const ScopedEnv async("VT_ASYNC_EXECUTOR", "1"); + HfConfig c = dense::TinyConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + const auto w = dense::MakeWeights(c); + auto model = vllm::BorrowQwen3_5DenseLoadedModel(w); + RegistryFullAttnGraph(*model, c, true); +} + +TEST_CASE("full-attention registry reaches the MoE graph Step through its FP4 predicate") { + StaticGraphCpu harness; + const ScopedEnv async("VT_ASYNC_EXECUTOR", "1"); + HfConfig c = TinyConfig(); + c.num_hidden_layers = 1; + c.layer_types = {"full_attention"}; + auto w = MakeWeights(c); + AddRoutingFp4(w, c); + // Control: valid FP4 CPU arithmetic alone does not satisfy the registry's + // platform predicate, so the registered forward stays eager. + { + auto model = vllm::BorrowQwen3_5MoeLoadedModel(w); + RegistryFullAttnGraph(*model, c, false); + } + { + ScopedFp4GraphCapability fake_capability; + auto model = vllm::BorrowQwen3_5MoeLoadedModel(w); + RegistryFullAttnGraph(*model, c, true); + } + MESSAGE("MoE registry witness uses a fake CPU FP4 capability and fake graph replay; " + "no GPU replay numerics"); +} + TEST_CASE("#2029: a NON-speculative Qwen3_5DenseDecodeGraph capture allocates nothing" " [pooled lane only -- SKIPPED under VT_POOL_BYPASS, where the pool is" " disabled and the guarantee is false by design]" From 4fc300f93cfb075c0afddccdd476a552fa900cdb Mon Sep 17 00:00:00 2001 From: Vikash Loomba Date: Tue, 8 Sep 2026 21:27:09 -0700 Subject: [PATCH 04/24] test(ENG-QWEN35-FULL-ATTN-STATE): pin query offset guards The graph shape tests reject nonzero first offsets and descending internal offsets for both model siblings. Each case fails when its guard is deleted, so independent review can verify both offset guarantees. Production code remains unchanged. Record the repair evidence under issue #3098. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Codex:gpt-6-astra [Codex CLI] --- .../ISSUE-GH-3098.md | 6 +++ .agents/specs/qwen35-full-attn-state.md | 48 +++++++++++++++++++ .../models/test_qwen3_5_decode_graph_seam.cpp | 15 +++++- 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md b/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md index 3a39e2f8b..155fe15d7 100644 --- a/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md +++ b/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md @@ -52,6 +52,12 @@ The scoped implementation passes public completion through both default and callback sampling arms. The operator reproduced the independent red and reran all public and focused CPU gates. The implementer completed 30 mutation checks. +Fresh review found missing negative coverage for the first query offset and +internal offset ordering. The test repair covers both graph siblings. +Each independent guard deletion now fails its corresponding new subcase. +The unchanged control and four complete focused CPU suites pass. +The specification records this repair's hashes, commands, and evidence. + The exact GGUF attempt on pinned vLLM refuses the text-only engine configuration before generating a token. The owning [specification](../../specs/qwen35-full-attn-state.md) records the source hashes, commands, logs, and pending G4 obligation. Fresh diff --git a/.agents/specs/qwen35-full-attn-state.md b/.agents/specs/qwen35-full-attn-state.md index 863f0a4b8..3fe8f3a92 100644 --- a/.agents/specs/qwen35-full-attn-state.md +++ b/.agents/specs/qwen35-full-attn-state.md @@ -487,6 +487,54 @@ G4 remains `PENDING` on the operator's pinned GGUF runtime capability. The implementation does not substitute a model or oracle. Issue #3098 retains ownership of this gate, independent review, and the final operator gate. +### First-offset and ordering coverage repair + +Fresh review of `25bea3e67597f6700fc1f2e9cfb5269948338c6d` found two missing +negative cases in `FullAttnGraphShapeGuards`. Deleting the first-offset check +or the ordering check independently left the existing focused suites green. +The reviewer found no product defect for this finding. + +The repair adds distinct subcases for both dense and MoE graph `Step` methods. +The first-offset case uses `{1,1}` with one request. The ordering case uses +`{0,2,1,3}` with three requests and matching token, slot, sequence, and block +arrays. Both cases retain empty GDN metadata and the existing exception checks. +All production bytes remain unchanged from the reviewed implementation. + +Repair evidence on 9 September 2026 UTC is under +`/home/vikash/.cache/qwen35-full-attn-state-repair1/evidence`. +The linked worktree is `/home/vikash/vllm.cpp-qwen35-full-attn-state-repair1`. +The repaired test source has SHA256 +`b8f5d330fd2d6436e19e9573406adda85cb6fd1ce1736332536b1da5df403ba5`. +The normal graph executable has SHA256 +`0af438e83c0c15b66860e95dd6ea47660555387a5fc9d6716ee34a5b1d0c5d80`. + +Each deleted-guard mutant returns 1 for each sibling's corresponding new +subcase. Each failure reports that the expected exception did not occur. +An unchanged address-sanitized control passes both complete shape cases. +Every mutation uses a scratch source and a fresh copy of this worktree's +CPU archive. Production and test restoration hashes match after every run. +The mutation manifest has SHA256 +`5248b0efd6fc9e0cf465aed89a36c87933f8dca0e9cbec71e07bbb157d0d6607`. +It records exact compile, link, and run arguments, binary hashes, and logs. +The external recipe is +`/home/vikash/.cache/qwen35-full-attn-state-repair1/run-mutations.py`, SHA256 +`9bb055dbdcbc070ecd9ce06e21968d44328e14552ecd6759f44da4b61c2804cf`. + +The four complete CPU suites listed under G2 and G3 pass in `cpu-green.log`. +The complete graph suite passes 16 cases and 1558 assertions in `graph-green.log`. +Configure and build arguments match the earlier CPU recipe, with at most +`-j 4` and this repair worktree's paths. Temporary files stay outside the +worktree, and `GIT_CONFIG_GLOBAL=/dev/null` isolates Git fixtures. + +The full preflight before edits returns 0. The staged preflight uses the same +NumPy path and external compile-scheduler wrapper as the implementation gate. +The repair handoff records the staged result and exact-range checks. +The explicit CPU instruction-set audit passes against this worktree's +`build-full-attn-cpu/compile_commands.json`. +Fresh scoped review and the final operator gate remain pending. +G4 retains the pinned engine refusal. This test repair adds no oracle waiver, +GPU replay numerical claim, or performance claim. + ## Risks and stop conditions - `NEEDS_CONTEXT`: the frozen fixture bytes, pinned runtime, or source cannot diff --git a/tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp b/tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp index c23223ae1..5efb5ad90 100644 --- a/tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp +++ b/tests/vllm/models/test_qwen3_5_decode_graph_seam.cpp @@ -1102,8 +1102,21 @@ void FullAttnGraphShapeGuards(const HfConfig& c, const Weights& w) { am.query_start_loc.back() = 2; expected = "query offsets"; } + SUBCASE("query offsets start after zero") { + am.query_start_loc = {1, 1}; + am.query_start_loc_cpu = am.query_start_loc; + expected = "query offsets"; + } + SUBCASE("query offsets descend inside the batch") { + am = FullAttnDecodeMeta(3, 0); + am.query_start_loc = {0, 2, 1, 3}; + am.query_start_loc_cpu = am.query_start_loc; + expected = "query offsets"; + } REQUIRE(expected != nullptr); - CHECK_THROWS_WITH_AS(graph.Step({11}, {0}, am, {}, pool.attn_kv, pool.gdn_state), + const std::vector ids(static_cast(am.num_actual_tokens), 11); + const std::vector positions(static_cast(am.num_actual_tokens), 0); + CHECK_THROWS_WITH_AS(graph.Step(ids, positions, am, {}, pool.attn_kv, pool.gdn_state), doctest::Contains(expected), std::runtime_error); } From 376223f000f85683f2881136e38ee52892d8d3a8 Mon Sep 17 00:00:00 2001 From: Vikash Loomba Date: Tue, 8 Sep 2026 22:16:43 -0700 Subject: [PATCH 05/24] spec(BACKEND-ROCM-QUANT-GATHER): admit decoder-only embedding storage The public Q8_K case reaches a materializer that still requires a dot kernel. Define an explicit embedding role and preserve the matrix default before changing that shared loader. Issue #3093 owns the correction and its loader, public API, and mutation gates. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:gpt-6-astra [Codex] --- .agents/specs/rocm-quant-gather.md | 52 ++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/.agents/specs/rocm-quant-gather.md b/.agents/specs/rocm-quant-gather.md index 092abc0da..ab8ed3e7f 100644 --- a/.agents/specs/rocm-quant-gather.md +++ b/.agents/specs/rocm-quant-gather.md @@ -397,8 +397,56 @@ The implementation can modify: - `docs/FEATURES.md` for the changed ROCm feature statement. - This spec, its issue record, and the already linked parent debt entry. -Changing shared model behavior or unrelated production code requires a scope -review before implementation. It cannot become an incidental gather repair. +The scoped materializer amendment below authorizes two shared loader files. +Other shared model behavior and unrelated production code require a scope +review before implementation. + +### Q8_K materializer amendment + +The operator approved this amendment on 9 September 2026 UTC under issue #3093. +Commit this amendment before changing either newly scoped product file: + +- `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp` +- `include/vllm/model_executor/models/qwen3_5_gguf_weights.h` + +The first native focused run passed 4 of 6 targets. The public test reached +Q8_K after the first 8 formats matched their dense controls. Its first Q8_K +load returned status 2. The native decoder suite separately passed all 11,698 +value assertions, but its empty-shape fixture failed during tensor construction. +That malformed test fixture requires a metadata view with zero dimensions. + +`LoadEmbedAndHead` already selects `KeepQuantGatherDType` through the shared +residency policy. It then calls `OwnGgufQuantBlocks`, whose guard at line 89 +requires `KeepQuantDType`. The latter requires a dot kernel and refuses Q8_K. +This mismatch prevents the row's declared decoder-only format from loading. +`git log -S 'VT_CHECK(KeepQuantDType(tensor.ggml_type'` identifies commit +`429e19d6a` as the guard's introduction. + +Add an explicit tensor role to `OwnGgufQuantBlocks`. Default the role to +`kMatmulWeight`, preserving the dot requirement for every existing caller. +The embedding materializer explicitly selects `kEmbeddingTable`, which checks +`KeepQuantGatherDType` instead. Preserve packed bytes, orientation, borrowing, +copying, prefaulting, and every existing matrix repack default. A gather must +not opt into a matrix repack. Do not change either shared dtype set, add a +dot kernel, or change any backend capability outside this row. + +Add a smallest loader test in `tests/vllm/test_gguf_keep_quant.cpp` using the +same generated Q8_K model. Require the ordinary loader to retain the original +packed embedding bytes and `nk=false`. Require the default materializer to +refuse that decoder-only format and the matrix residency route to expand it. +Keep the public Q8_K load and completion test as the production gate. +Fresh review removes the embedding role argument and weakens the default dot +guard separately. Each mutation must fail its corresponding gate. + +The operator's first native run used the manifest +`native-focused-v1.json`, SHA256 +`496a12c417b9cb95036896da418d74fd8383fc6d1497f0ed94f4e457791bf479`. +Its log is `native-focused-v1.log`, SHA256 +`2f21277ec55c85cf6cd4abbb669a688bdfab415de13c9bcd0588e6a7854787ac`. +Both files reside under the row's external evidence directory +`/home/vikash/.cache/rdna3-gather-impl/evidence/`. +The operator verified unchanged source, archive, and executable hashes around +the run. The Q8_K public load had 1,108 passing assertions before its failure. ## Tests and gates From 2e5adfb85a255528bffa5d3cdb016efb2bab70d8 Mon Sep 17 00:00:00 2001 From: Vikash Loomba Date: Tue, 8 Sep 2026 22:26:09 -0700 Subject: [PATCH 06/24] spec(BACKEND-ROCM-QUANT-GATHER): admit Q8_K file geometry The loader regression identifies an unknown-type refusal before the materializer. Define the existing Q8_K byte geometry and its reader gate before adding that trait. Preserve matrix refusals and correct the earlier cause attribution under issue #3093. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:gpt-6-astra [Codex] --- .agents/specs/rocm-quant-gather.md | 36 ++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/.agents/specs/rocm-quant-gather.md b/.agents/specs/rocm-quant-gather.md index ab8ed3e7f..656926934 100644 --- a/.agents/specs/rocm-quant-gather.md +++ b/.agents/specs/rocm-quant-gather.md @@ -267,6 +267,11 @@ An empty vocabulary accepts no nonempty request. The shared `vt::Embedding` checks remain authoritative for ranks, shapes, dtypes, contiguity, whole block rows, and device equality. Keep floating gather dispatch unchanged. +Bind the native gather to `queue.device.index` before allocating its error +record or launching work. A different ambient HIP device must not redirect +the allocation, launch, or cleanup. The two-device regression keeps the queue +and tensors on device 0, selects ambient device 1, and checks rows, bounds, +and recovery. Fresh review removes this binding and requires that gate to fail. ### Loader and production reachability @@ -411,14 +416,15 @@ Commit this amendment before changing either newly scoped product file: The first native focused run passed 4 of 6 targets. The public test reached Q8_K after the first 8 formats matched their dense controls. Its first Q8_K -load returned status 2. The native decoder suite separately passed all 11,698 +load returned status 2, without a readable error capture. The native decoder suite separately passed all 11,698 value assertions, but its empty-shape fixture failed during tensor construction. That malformed test fixture requires a metadata view with zero dimensions. `LoadEmbedAndHead` already selects `KeepQuantGatherDType` through the shared residency policy. It then calls `OwnGgufQuantBlocks`, whose guard at line 89 requires `KeepQuantDType`. The latter requires a dot kernel and refuses Q8_K. -This mismatch prevents the row's declared decoder-only format from loading. +This downstream guard would refuse the decoder-only format after the reader +accepts it. That materializer failure was a source hypothesis at this amendment. `git log -S 'VT_CHECK(KeepQuantDType(tensor.ggml_type'` identifies commit `429e19d6a` as the guard's introduction. @@ -448,6 +454,32 @@ Both files reside under the row's external evidence directory The operator verified unchanged source, archive, and executable hashes around the run. The Q8_K public load had 1,108 passing assertions before its failure. +### Q8_K reader amendment + +The new loader-focused red identifies the first executing refusal: +`GgufFile::OpenOne` rejects GGML type 15 at `gguf_reader.cpp:506`, because +`FindGgmlTraits` has no entry for it. The result is exit 1 after one passing +fixture assertion. The log is `materializer-loader-red.log` in the same +external evidence directory. The materializer guard remains a separate +downstream hypothesis until the reader accepts the file. + +The operator approved this additional scope on 9 September 2026 UTC: +`src/vllm/model_executor/model_loader/gguf_reader.cpp`. Commit this amendment +before changing that file. Add exactly the existing Q8_K geometry for GGML +type 15: 256 elements and 292 bytes per block. Stock llama.cpp pin +`10bf611e533d81f739128304991c5e133c6aebd8`, `ggml/src/ggml-common.h:370-376`, +defines `block_q8_K` as a float delta, 256 signed bytes, and 16 signed 16-bit +sums. This is already the geometry in `vt::DType::kQ8_K`. + +Keep all other traits byte-for-byte equal. Preserve unknown-type refusals, +overflow checks, span checks, and whole-block divisibility. This amendment +does not add a shared dtype or change a matrix dtype set. Add the reader +regression in `tests/vllm/test_gguf_keep_quant.cpp`, checking geometry and +original packed bytes through `GgufFile::Open`. Fresh review deletes the +type-15 entry and mis-sizes its geometry independently. Both mutations must +fail a meaningful gate. After adding the trait, rerun the loader-focused red +to identify the materializer failure before changing that guard. + ## Tests and gates ### Red-first implementation gate From 8c9101fa41892bcbd3a97764a7f179a0ef1321f2 Mon Sep 17 00:00:00 2001 From: Vikash Loomba Date: Tue, 8 Sep 2026 23:04:41 -0700 Subject: [PATCH 07/24] spec(ENG-QWEN35-FULL-ATTN-STATE): require the runner completion regression The full-attention-only runner test still expects the former forward-side GDN refusal. Specify its successful execution and state checks before correcting the test. Keep fixture geometry and runner topology unchanged. Refs #3098 FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:gpt-6-astra [Codex] --- .agents/specs/qwen35-full-attn-state.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.agents/specs/qwen35-full-attn-state.md b/.agents/specs/qwen35-full-attn-state.md index 3fe8f3a92..6283c1015 100644 --- a/.agents/specs/qwen35-full-attn-state.md +++ b/.agents/specs/qwen35-full-attn-state.md @@ -41,6 +41,25 @@ kernels, new graph backends, new speculative modes, checkpoint downloads, package installation, continuous integration changes, and global oracle pins. The fix has no dependency on the separate gfx1100 provider changes. +### Runner regression amendment + +On 9 September 2026 UTC, integration testing found an obsolete expectation in +`tests/vllm/v1/worker/test_runner.cpp`. Its full-attention-only step case still +expects the forward's former GDN refusal. The reviewed consumer checks now +allow that same unchanged fixture to execute successfully. + +The operator authorizes a test-only correction under #3098. Require successful +execution, a valid sampled token with request feedback, and populated attention +state while recurrent state remains absent. Preserve the fixture's geometry, +weights, prompt, empty layer types, and single full-attention cache group. +This amendment changes no runner allocation, group topology, or product code. + +Capture the current assertion failure before editing. Run the corrected focused +case and the complete runner suite. In a scratch build, restore the dense +forward's unconditional GDN metadata requirement. The corrected case must fail +at that original refusal. Restore all source and archive bytes after the +mutation. Fresh review and operator verification remain required. + ## Inventory This per-row inventory owns the child identity through the canonical spec scan. From b46852d13f7c8776557dab170e02ebea50cdfdec Mon Sep 17 00:00:00 2001 From: Vikash Loomba Date: Tue, 8 Sep 2026 23:10:11 -0700 Subject: [PATCH 08/24] test(ENG-QWEN35-FULL-ATTN-STATE): require runner completion without GDN The reviewed consumer checks make the full-attention runner fixture succeed, so its old exception expectation now fails. Require completed execution, changed attention state, a valid sampled token, and request feedback. Preserve the existing fixture and keep GDN state absent. The focused case passes 18 assertions. All 41 CPU runner cases pass with 1914 assertions. Restoring unconditional dense GDN validation fails the corrected case at the original refusal. Product bytes remain unchanged. Refs #3098 FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:gpt-6-astra [Codex] --- .../ISSUE-GH-3098.md | 8 +++ .agents/specs/qwen35-full-attn-state.md | 31 +++++++++++ tests/vllm/v1/worker/test_runner.cpp | 53 +++++++++++++------ 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md b/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md index 155fe15d7..f6ece4b6d 100644 --- a/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md +++ b/.agents/issues/ENG-QWEN35-FULL-ATTN-STATE/ISSUE-GH-3098.md @@ -63,3 +63,11 @@ before generating a token. The owning [specification](../../specs/qwen35-full-at records the source hashes, commands, logs, and pending G4 obligation. Fresh review and the final operator gate remain pending. Keep this issue open until qualified work lands. + +The full-attention runner regression now requires successful execution and +sampled-token feedback instead of the former GDN refusal. Its focused case +passes 18 assertions and the complete CPU runner suite passes 41 cases and +1914 assertions. Restoring unconditional dense GDN validation fails the new +case at the original refusal. The scoped spec amendment precedes this test-only +repair; runner allocation, group topology, fixtures, and product code stay +unchanged. The specification records the exact red, green, and mutation evidence. diff --git a/.agents/specs/qwen35-full-attn-state.md b/.agents/specs/qwen35-full-attn-state.md index 6283c1015..9d8f07cac 100644 --- a/.agents/specs/qwen35-full-attn-state.md +++ b/.agents/specs/qwen35-full-attn-state.md @@ -554,6 +554,37 @@ Fresh scoped review and the final operator gate remain pending. G4 retains the pinned engine refusal. This test repair adds no oracle waiver, GPU replay numerical claim, or performance claim. +### Runner completion expectation repair + +The committed amendment `78c7441bd26db62904c18f6c105dd64dac265e77` precedes +this test edit. The unchanged pre-repair case returns one because it expects +an exception from a successful forward. The focused red log SHA256 is +`0750d5cb6e1cedda4e690e8340d3331790193604c04fb99ceffbfeca4c865641`. + +The repaired case passes 18 assertions. It checks the actual prompt, produced +logit row and request counts, changed attention-cache bytes in both layers, +an in-range sampled token, and token feedback into the admitted request. +The GDN group, caches, and metadata remain absent. The fixture bytes and +all production source remain unchanged by this repair. +The complete CPU runner suite passes 41 cases and 1914 assertions. + +Evidence is under `/home/vikash/.cache/rdna3-f16-repair1/runner-repair`. +`obsolete-expectation-red.json`, `build-receipt.json`, `focused-green.json`, +and `full-green.json` pin the source, private CPU and HIP binaries, exact +commands, and logs. The corrected test source SHA256 is +`8b70d78678245776737965cd461123b62716ed1d2cf130d604234e67519f09b2`. + +The separate scratch mutation restores only the dense entry's unconditional +GDN validation. The repaired runner case returns one at the original +`gdn_meta.num_actual_tokens must equal T` refusal. Its two assertions contain +one setup pass and one intended failure. The mutation log SHA256 is +`dd4585b2a527b262ba3447444a48566144f56c30ffc99419719eb69ea4e68d83`. +`../mutations/runner-gdn-consumer/recipe.json` records the fresh archive copy, +compile and link arguments, mutant binary, and byte-exact scratch restoration. +The original production source and archive hashes remain unchanged. +Fresh scoped review and the final operator gate remain required. The pinned +GGUF primary refusal retains its existing G4 disposition. + ## Risks and stop conditions - `NEEDS_CONTEXT`: the frozen fixture bytes, pinned runtime, or source cannot diff --git a/tests/vllm/v1/worker/test_runner.cpp b/tests/vllm/v1/worker/test_runner.cpp index ceeb54f06..597a3c551 100644 --- a/tests/vllm/v1/worker/test_runner.cpp +++ b/tests/vllm/v1/worker/test_runner.cpp @@ -1920,21 +1920,44 @@ TEST_CASE("runner: full-attention-only step skips GDN metadata build (no OOB)") SchedulerOutput s1 = NewStep({MakeFaNewReq("A", prompt, 0, {0, 1}, Greedy())}, {{"A", P}}); - // Pre-generalization, execute_model called gather_block_table(gdn_group_id_ == - // -1) → input_batch_.block_table[-1] (out-of-bounds → crash) BEFORE reaching - // the model forward. Post-generalization the whole GDN metadata build is gated - // on gdn_group_id_ >= 0, so a full-attention-only step builds a default-empty - // gdn_meta and reaches the model forward WITHOUT any out-of-bounds. - // - // The forward it reaches here is the BORROWED 27B *dense* forward, which - // carries its OWN hybrid assumption (gdn_meta must describe every token — - // qwen3_5.cpp:5463). That is a FORWARD-side seam gap, NOT a runner one: - // Qwen3ForCausalLM's own dense forward (W3) will not assume a GDN group. So we - // assert only that control reached the forward via a clean, CATCHABLE throw - // (not an uncatchable OOB), which proves the runner's GDN path was skipped. - CHECK_THROWS_WITH_AS(runner.execute_model(s1), - doctest::Contains("qwen3_5 dense paged forward"), - std::runtime_error); + REQUIRE(runner.attn_kv().size() == static_cast(c.num_hidden_layers)); + std::vector> kv_before; + for (const PagedKvCache& kv : runner.attn_kv()) { + const size_t block_bytes = static_cast( + 2 * kv.block_size * kv.num_kv_heads * kv.head_size) * vt::SizeOf(kv.dtype); + const auto* bytes = static_cast(kv.data); + kv_before.emplace_back(bytes, bytes + block_bytes); + } + + // #3098 removes the borrowed dense forward's former GDN requirement. The + // unchanged full-attention fixture must now finish with real attention state + // and sampled-token feedback, while the runner leaves GDN metadata empty. + REQUIRE_FALSE(runner.execute_model(s1).has_value()); + CHECK(runner.gdn_group_id() == -1); + CHECK(runner.gdn_state().empty()); + CHECK(runner.last_gdn_meta().num_actual_tokens == 0); + CHECK(runner.last_step().input_token_ids == prompt); + CHECK(runner.last_forward_rows() == 1); + CHECK(runner.last_forward_num_actual_tokens() == P); + CHECK(runner.last_forward_num_reqs() == 1); + for (size_t layer = 0; layer < runner.attn_kv().size(); ++layer) { + CAPTURE(layer); + const auto* bytes = static_cast(runner.attn_kv()[layer].data); + const std::vector kv_after(bytes, bytes + kv_before[layer].size()); + CHECK(kv_after != kv_before[layer]); + } + + const ModelRunnerOutput output = runner.sample_tokens(std::nullopt); + REQUIRE(output.req_ids == std::vector{"A"}); + REQUIRE(output.sampled_token_ids.size() == 1); + REQUIRE(output.sampled_token_ids[0].size() == 1); + const int32_t token = output.sampled_token_ids[0][0]; + CHECK(token >= 0); + CHECK(token < c.vocab_size); + const auto& batch = runner.input_batch(); + const int row = batch.req_id_to_index.at("A"); + CHECK(batch.num_tokens_no_spec[static_cast(row)] == P + 1); + CHECK(batch.token_id(row, P) == token); } // ─── M3: THE BLOCK-SIZE CONTRACT AT ITS PRODUCTION CALL SITE ───────────────── From c5bb0f1f71f1db2bac5f436189a6a018fb62cbc3 Mon Sep 17 00:00:00 2001 From: Vikash Loomba Date: Tue, 8 Sep 2026 23:54:06 -0700 Subject: [PATCH 09/24] feat(BACKEND-ROCM-QUANT-GATHER): decode packed embedding rows ROCm expands quantized embeddings because its operation table lacks a compressed gather. Register all 19 admitted codecs and decode selected rows directly into the caller's F32 or BF16 output. Keep the error record fixed at 16 bytes and validate full-width IDs before reading a packed row. Admit the existing Q8_K file geometry and distinguish embedding storage from matrix storage. The embedding role preserves packed decoder-only formats; the default materializer still requires a dot kernel and refuses embedding repacks. Bind allocation and launch to the queue's device. The gfx1100 operator passed all 15 final CTests and the required two-device witness. All 76 operation outputs meet the pinned oracle gates, including 68 byte-identical outputs. Matching traces preserve untraced outputs and show native selected-row decode with requested output and BF16 KV storage. The full staged preflight reports no failures and five argument-dependent skips. The separate CPU ISA audit passes. The row evidence names each skip and preserves the complete raw gate output. Keep the row ACTIVE. Original upstream fixtures await download authority. The pinned primary renderer refuses the exact bounded model, and both secondary models abort before tokens. Model token equality, matched oracle cache geometry, fresh mutation review, and reviewed-head operator gates remain pending. This change makes no performance claim. Refs #3093. The branch retains the separately reviewed #3101 prerequisite. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:gpt-6-astra [Codex] --- .agents/engine-matrix.md | 4 +- .agents/specs/rocm-quant-gather.md | 70 +- CMakeLists.txt | 2 + docs/FEATURES.md | 2 +- .../rocm-quant-gather/README.md | 187 + .../ambient-device-witness-v1.json | 54 + ...nt-device-witness-v2.operator-receipt.json | 29 + .../materializer-second-red.json | 44 + .../native-final-v4-commands.json | 191 + ...ative-final-v4-operator-capture-audit.json | 470 +++ .../native-final-v4-operator-results.json | 53 + .../rocm-quant-gather/native-focused-v1.json | 101 + .../native-focused-v2-operator-results.json | 88 + .../rocm-quant-gather/native-focused-v2.json | 464 +++ .../native-operation-captures.tar.gz | Bin 0 -> 162780 bytes .../native-v2-oracle-comparison-operator.json | 1843 ++++++++++ .../oracle-audit-arithmetic-explanation.json | 235 ++ .../oracle-audit-artifact-manifest.json | 101 + ...acle-audit-executing-source-artifacts.json | 48 + .../oracle-audit-independent-audit.json | 52 + .../rocm-quant-gather/oracle-audit-report.md | 59 + .../plugin-artifact-sha256.json | 140 + .../plugin-build-command.json | 54 + .../preflight-final-staged-result.json | 48 + .../preflight-python-environment.json | 9 + .../primary-model-config.json | 44 + .../primary-model-v1-command.json | 101 + .../primary-model-v1-operator-receipt.json | 72 + .../primary-model-v1-report-p0-r0.json | 49 + .../primary-model-v2-command.json | 116 + .../primary-model-v2-operator-receipt.json | 86 + .../primary-model-v2-report-p0-r0.json | 49 + .../primary-operation-captures.tar.gz | Bin 0 -> 146575 bytes .../primary-synthetic-v1.json | 378 ++ ...primary-synthetic-v1.operator-receipt.json | 64 + .../public-model-trace-captures.tar.gz | Bin 0 -> 3245815 bytes .../public-model-trace-v1-command.json | 557 +++ ...ublic-model-trace-v1-operator-receipt.json | 33 + ...c-model-trace-v1-operator-trace-audit.json | 492 +++ .../public-model-trace-v1-public-audit.json | 3223 +++++++++++++++++ .../public-red-after-prerequisite-v1.json | 58 + ...d-after-prerequisite.operator-receipt.json | 8 + .../rocm-quant-gather/q8k-reader-red.json | 36 + .../rocm-quant-gather/raw-logs.tar.gz | Bin 0 -> 36818 bytes .../record-anchor-repair.json | 12 + .../secondary-frozen-v1.json | 399 ++ .../secondary-operation-captures.tar.gz | Bin 0 -> 11761 bytes .../stock-shapes-v1-commands.json | 108 + .../stock-shapes-v1-operator-results.json | 118 + .../synthetic-parity-v2.json | 1835 ++++++++++ .../table-whitespace-only.json | 6 + .../rocm-quant-gather/trace-v2-commands.json | 1495 ++++++++ .../trace-v2-operator-input-audit.json | 40 + .../trace-v2-operator-results.json | 122 + .../trace-v2-operator-trace-audit.json | 529 +++ .../trace-v2-profiler-captures.tar.gz | Bin 0 -> 1941304 bytes .../trace-v2-trace-audit.json | 654 ++++ .../two-regeneration-model-hashes.json | 347 ++ .../models/qwen3_5_gguf_weights.h | 5 +- .../model_loader/gguf_keep_quant.cpp | 2 +- .../model_loader/gguf_reader.cpp | 6 + .../models/qwen3_5_gguf_weights.cpp | 11 +- src/vt/rocm/rocm_embedding_quant.h | 22 + src/vt/rocm/rocm_embedding_quant.hip | 179 + src/vt/rocm/rocm_ops.hip | 3 + src/vt/rocm/rocm_quant_dequant.h | 671 ++++ src/vt/rocm/rocm_quant_iq_tables.h | 1208 ++++++ tests/CMakeLists.txt | 13 + tests/capi/rocm_quant_gather_fixture.h | 202 ++ tests/capi/test_rocm_embedding_quant.cpp | 193 + tests/vllm/test_gguf_keep_quant.cpp | 56 +- tests/vt/test_cuda_embedding_quant.cpp | 9 +- tests/vt/test_rocm_embedding_quant.cpp | 388 ++ tools/rocm_quant_gather/CMakeLists.txt | 26 + tools/rocm_quant_gather/audit_trace.py | 125 + tools/rocm_quant_gather/capture.cpp | 185 + tools/rocm_quant_gather/compare.py | 113 + tools/rocm_quant_gather/primary.py | 136 + tools/rocm_quant_gather/primary_model.py | 80 + tools/rocm_quant_gather/primary_trace.py | 79 + tools/rocm_quant_gather/secondary.cpp | 138 + tools/rocm_quant_gather/stock_shapes.py | 47 + 82 files changed, 19241 insertions(+), 35 deletions(-) create mode 100644 docs/bench-evidence/rocm-quant-gather/README.md create mode 100644 docs/bench-evidence/rocm-quant-gather/ambient-device-witness-v1.json create mode 100644 docs/bench-evidence/rocm-quant-gather/ambient-device-witness-v2.operator-receipt.json create mode 100644 docs/bench-evidence/rocm-quant-gather/materializer-second-red.json create mode 100644 docs/bench-evidence/rocm-quant-gather/native-final-v4-commands.json create mode 100644 docs/bench-evidence/rocm-quant-gather/native-final-v4-operator-capture-audit.json create mode 100644 docs/bench-evidence/rocm-quant-gather/native-final-v4-operator-results.json create mode 100644 docs/bench-evidence/rocm-quant-gather/native-focused-v1.json create mode 100644 docs/bench-evidence/rocm-quant-gather/native-focused-v2-operator-results.json create mode 100644 docs/bench-evidence/rocm-quant-gather/native-focused-v2.json create mode 100644 docs/bench-evidence/rocm-quant-gather/native-operation-captures.tar.gz create mode 100644 docs/bench-evidence/rocm-quant-gather/native-v2-oracle-comparison-operator.json create mode 100644 docs/bench-evidence/rocm-quant-gather/oracle-audit-arithmetic-explanation.json create mode 100644 docs/bench-evidence/rocm-quant-gather/oracle-audit-artifact-manifest.json create mode 100644 docs/bench-evidence/rocm-quant-gather/oracle-audit-executing-source-artifacts.json create mode 100644 docs/bench-evidence/rocm-quant-gather/oracle-audit-independent-audit.json create mode 100644 docs/bench-evidence/rocm-quant-gather/oracle-audit-report.md create mode 100644 docs/bench-evidence/rocm-quant-gather/plugin-artifact-sha256.json create mode 100644 docs/bench-evidence/rocm-quant-gather/plugin-build-command.json create mode 100644 docs/bench-evidence/rocm-quant-gather/preflight-final-staged-result.json create mode 100644 docs/bench-evidence/rocm-quant-gather/preflight-python-environment.json create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-model-config.json create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-model-v1-command.json create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-model-v1-operator-receipt.json create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-model-v1-report-p0-r0.json create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-model-v2-command.json create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-model-v2-operator-receipt.json create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-model-v2-report-p0-r0.json create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-operation-captures.tar.gz create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-synthetic-v1.json create mode 100644 docs/bench-evidence/rocm-quant-gather/primary-synthetic-v1.operator-receipt.json create mode 100644 docs/bench-evidence/rocm-quant-gather/public-model-trace-captures.tar.gz create mode 100644 docs/bench-evidence/rocm-quant-gather/public-model-trace-v1-command.json create mode 100644 docs/bench-evidence/rocm-quant-gather/public-model-trace-v1-operator-receipt.json create mode 100644 docs/bench-evidence/rocm-quant-gather/public-model-trace-v1-operator-trace-audit.json create mode 100644 docs/bench-evidence/rocm-quant-gather/public-model-trace-v1-public-audit.json create mode 100644 docs/bench-evidence/rocm-quant-gather/public-red-after-prerequisite-v1.json create mode 100644 docs/bench-evidence/rocm-quant-gather/public-red-after-prerequisite.operator-receipt.json create mode 100644 docs/bench-evidence/rocm-quant-gather/q8k-reader-red.json create mode 100644 docs/bench-evidence/rocm-quant-gather/raw-logs.tar.gz create mode 100644 docs/bench-evidence/rocm-quant-gather/record-anchor-repair.json create mode 100644 docs/bench-evidence/rocm-quant-gather/secondary-frozen-v1.json create mode 100644 docs/bench-evidence/rocm-quant-gather/secondary-operation-captures.tar.gz create mode 100644 docs/bench-evidence/rocm-quant-gather/stock-shapes-v1-commands.json create mode 100644 docs/bench-evidence/rocm-quant-gather/stock-shapes-v1-operator-results.json create mode 100644 docs/bench-evidence/rocm-quant-gather/synthetic-parity-v2.json create mode 100644 docs/bench-evidence/rocm-quant-gather/table-whitespace-only.json create mode 100644 docs/bench-evidence/rocm-quant-gather/trace-v2-commands.json create mode 100644 docs/bench-evidence/rocm-quant-gather/trace-v2-operator-input-audit.json create mode 100644 docs/bench-evidence/rocm-quant-gather/trace-v2-operator-results.json create mode 100644 docs/bench-evidence/rocm-quant-gather/trace-v2-operator-trace-audit.json create mode 100644 docs/bench-evidence/rocm-quant-gather/trace-v2-profiler-captures.tar.gz create mode 100644 docs/bench-evidence/rocm-quant-gather/trace-v2-trace-audit.json create mode 100644 docs/bench-evidence/rocm-quant-gather/two-regeneration-model-hashes.json create mode 100644 src/vt/rocm/rocm_embedding_quant.h create mode 100644 src/vt/rocm/rocm_embedding_quant.hip create mode 100644 src/vt/rocm/rocm_quant_dequant.h create mode 100644 src/vt/rocm/rocm_quant_iq_tables.h create mode 100644 tests/capi/rocm_quant_gather_fixture.h create mode 100644 tests/capi/test_rocm_embedding_quant.cpp create mode 100644 tests/vt/test_rocm_embedding_quant.cpp create mode 100644 tools/rocm_quant_gather/CMakeLists.txt create mode 100644 tools/rocm_quant_gather/audit_trace.py create mode 100644 tools/rocm_quant_gather/capture.cpp create mode 100644 tools/rocm_quant_gather/compare.py create mode 100644 tools/rocm_quant_gather/primary.py create mode 100644 tools/rocm_quant_gather/primary_model.py create mode 100644 tools/rocm_quant_gather/primary_trace.py create mode 100644 tools/rocm_quant_gather/secondary.cpp create mode 100644 tools/rocm_quant_gather/stock_shapes.py diff --git a/.agents/engine-matrix.md b/.agents/engine-matrix.md index 080ea6e7c..2b7e02bc0 100644 --- a/.agents/engine-matrix.md +++ b/.agents/engine-matrix.md @@ -172,8 +172,8 @@ lifecycle are unchanged. |---|---|---|---|---|---|---|---|---| | `SPEC-MTP` | Qwen3.6 MTP heads, k=1 first. **M-mtp-0 CLOSED 2026-07-24: the standalone draft head is oracle-parity-proven on BOTH checkpoints** (27B dense + 35B MoE, k=1, vLLM 0.25.0 executable @ pin `e24d1b24`) - argmax exact on 26/26 unambiguous rows each; the one remaining row per checkpoint is an EXACT oracle top1==top2 tie where vLLM's own `argmax` and `topk` disagree and our pick is a tied maximum; logits within the whole-model bound (atol 0.05 + rtol 0.05), 0/216 out-of-tol on both; shared lm_head isolated is bit-exact on the 35B NVFP4 head. **I2 scheduler-half LANDED (2026-07-24)**: host-side spec plumbing + the FROZEN spec-metadata ABI (spec §2.7) - `SpeculativeConfig`, `DraftTokenIds`, `Request::spec_token_ids`/`NumTokensWithSpec`, populated `scheduled_spec_decode_tokens`, `Scheduler::update_draft_token_ids`, `take_draft_token_ids` seam, `EngineCore::post_step`, `InputBatch::num_accepted_tokens`/`update_req_spec_token_ids`; DEFAULT-OFF and INERT (no `SpeculativeConfig` => `num_lookahead_tokens == 0`). **I3 verify-half LANDED (2026-07-24)**: greedy rejection sampler + per-request logits expansion (see `SPEC-REJECTION`, now `ACTIVE`). **I4 GDN-half LANDED (2026-07-24)**: the GDN speculative slot path + bit-exact state rollback, the piece BOTH GDN-hybrid gate checkpoints need (see `SPEC-GDN-SEGMENTS`, now `ACTIVE`). **I5a GDN LAYER ROUTING + runner spec-metadata upload LANDED (2026-07-24, `CLAIM-SPEC-MTP-I5A`)**: `GdnBlockPaged` now routes a pure-spec batch through `vt::GdnSpecDecode`/`vt::CausalConv1dSpecUpdate` and the runner uploads I4's six spec device tensors — first sub-increment of the scoped M-mtp-1 (I5a GDN wiring → I5b prepare_prefill → I5c MTP paged propose → I5d config+runner-loop+the 27B token gate, spec §5). DEFAULT-OFF INERT, bit-exact vs the I4 ops, no e2e loop yet. **I5b `prepare_prefill_inputs` LANDED (2026-07-24, `CLAIM-SPEC-MTP-I5B`, recorded under `SPEC-REJECTION`)**: the drafter prefill input-prep host routine (shift-splice + `query_len -= num_rejected` + last-token index / metadata) — second scoped M-mtp-1 sub-increment, DEFAULT-OFF INERT, unit-gated RED-first, additive. **I5d CONFIG + RUNNER LOOP LANDED, PARTIAL (2026-07-25, `CLAIM-SPEC-MTP-I5D`)**: `--speculative-config` JSON parse -> `EngineParams::speculative_config`; `LoadedEngine` resolution (`ResolveSpecConfig`/`ResolveMtp`, widened KV `MakeQwen3_5KVCacheSpec(num_spec>0)`, `BuildMtpDraft`, forced sync scheduling, `MakeScheduler(spec)`, `EngineCore(check_for_draft=true)`); the full runner verify/propose loop (draft splice, hidden-tap capture, GDN builder spec-overload feed, k+1 GDN state-slot remap + widened conv cache + draft-KV alloc, `MtpProposePrefill` post-sampling, `take_draft_token_ids`, acceptance telemetry). CUDA `-Werror` 0 warnings, cutlass-ON banner. SPEC-OFF BYTE-IDENTICAL (all gated on `spec_on()`): SACRED 27B 235/235, 35B 315/315, Coder 138/138 + unit test_runner 257 / test_mtp_speculator 169 / test_gdn_metadata_builder 483 / test_ops_gdn 3630 ALL PASS. **The three-way 27B token gate is NOT yet passing** (`tests/parity/test_qwen27_spec_decode.cpp` RUNS the loop + MEASURES the blocker): the spec-ON engine throws on the FIRST prefill step at `gdn_state_gather: working/cache row shapes must match` (`src/vt/ops.cpp:1773`) — I4's spec conv rollback needs the conv row widened to `(K-1)+num_spec` but the non-spec GDN conv ops assume `(K-1)`. Closing needs widened-cache-aware non-spec GDN conv ops + the MIXED `GdnBlockPaged` split/merge. Row LEFT `GATING` at I5e. **I5e LANDED 2026-07-25 (`CLAIM-SPEC-MTP-I5E`) — `SPEC-MTP` LEAVES `GATING`.** Made the non-spec GDN conv ops widened-cache-aware (mirror vLLM `state_len=KERNEL_WIDTH-1` + physical `stride_conv_state_tok`; leading `(K-1)` sub-window; byte-identical at `num_spec==0`, contiguous fast path kept) AND RCA'd the resulting 0-acceptance dead-drafter to the async input-combine overwriting the verify batch's draft position with the committed token (forced off under spec, nullopt-guarded). **THREE-WAY 27B GATE PASSES** (single-request greedy): our-ON == vLLM `--speculative-config mtp` greedy == our-OFF token-for-token; **acceptance 16/16 drafts accepted**, ~16 target steps saved. Spec-OFF SACRED byte-identical (27B 235/235, 35B 315/315, Coder 138/138), `test_ops_gdn` 3678, compute-sanitizer 0 on the spec step. NOT `DONE`: MIXED `GdnBlockPaged` split/merge (concurrency) + throughput A/B are I6. **I6 LANDED 2026-07-25 (`CLAIM-SPEC-MTP-I6`), `benchmark_binding=true` — the §5 c1 THROUGHPUT GATE, first spec-decode speed number:** OURS spec-ON (`examples/vllm-bench` + an additive `--speculative-config` flag, production config) vs pinned vLLM 0.25.0 spec-ON (graphed `vllm serve --speculative-config mtp` + `vllm bench serve`, `enforce_eager=False`/`FULL_AND_PIECEWISE`/inductor; MTP confirmed `Resolved architecture: Qwen3_5MTP`), SAME `{"method":"mtp","num_speculative_tokens":1}`, 27B `~/bench/q36-27b-nvfp4-vllm`, c1, greedy, 8 real prompts x 256 out, prose + code, idle box one-engine-at-a-time under one `flock`, 3 reps (cold TTFT discarded), token-identity re-confirmed FIRST (`test_qwen27_spec_decode` PASS 16/16). RESULT — **ours AT/ABOVE vLLM on EVERY measured axis** (prose / code): TPOT 66.2/62.95 vs 69.1/65.3 ms (ours ~1.04x faster), output tput 15.10/15.72 vs 14.43/15.13 tok/s (+4.6%/+3.9%), ITL 121.6/121.1 vs 123.2 ms, TTFT(warm) 131/131 vs 151.5/181 ms, acceptance ours 0.85/0.92 vs vLLM 0.838 overall (within noise, live drafter both), peak RSS 28.4 GB ON / 24.8 GB OFF (both inside the 119 GiB pool). Spec helps both (ours 1.52x/1.59x, vLLM 1.51x/1.60x TPOT); ours already ~4% faster spec-OFF. STAYS `ACTIVE`: the c>1 mixed spec+non-spec `GdnBlockPaged` split/merge is still refused (needs a row `IndexSelect`/`IndexCopy` vt op) + owes a c>1 A/B, and no user-facing supported `--speculative-config` on the OpenAI server yet (bench flag example-only/additive). Raw logs dgx `~/work/mtp-bench-i6/{results,vresults}`. **I7 LANDED 2026-07-25 (`CLAIM-SPEC-MTP-I7`, `benchmark_binding=true`) — the MIXED spec+non-spec GDN batch (concurrency), the server/CLI `--speculative-config`, and the c>1 A/B — implementation COMPLETE + at vLLM parity; STAYS `ACTIVE` for one honest reason (below), NOT a lag.** New row op `vt::IndexSelect`/`vt::IndexCopy` (CUDA==CPU bit-exact at GDN widths, RED-first); `GdnBlockPagedMixedSpec` split/merge (mirror `qwen_gdn_linear_attn.py:1329-1576`) proven MODEL-INDEPENDENTLY bit-exact (mixed == pure spec + pure prefill, 27B/35B, `test_qwen3_5_gdn_spec_routing`, RED-first by a broken merge); compute-sanitizer 0 on the mixed step + op; server (I5d) + CLI (ABI v6) `--speculative-config`. **c>1 A/B (both spec-ON, same config):** ours ON-PAR-OR-ABOVE vLLM at c2/c4/c8 (output tput within ~+/-2%, ours +1.6%/+2.5% c2, +0.9%/+1.7% c4, +0.9%/-1.1% c8 within noise, prose/code; both ~1.5x spec speedup — does NOT go neutral; acceptance 0.84-0.92 vs vLLM 0.835). **Why STAYS `ACTIVE` (honest, not a lag):** the DONE criterion's strict `token-exact at c>1` clause is a proven MODEL impossibility — the 27B greedy is bf16-batch-nondeterministic (spec-OFF max_seqs 4-vs-1 differs 2/3 short prompts, NO spec involved), affecting vLLM identically, so exact c>1 token identity cannot be met by any correct implementation; c>1 correctness is instead established by the model-independent bit-exact split/merge proof + acceptance parity (near-tie-distributional-gate), with token-exact strict at c1 (I6). No missing work, no lever — the DONE final call is deferred to the user given this criterion ambiguity. SACRED spec-OFF byte-identical 27B 235/235, 35B 315/315, Coder 138/138; CUDA `-Werror` 0 warnings. Raw logs dgx `~/work/mixed-batch/{cN_results,cN_vresults}`. **I8 — `SPEC-MTP` → `DONE` 2026-07-26 (`CLAIM-SPEC-MTP-DONE`, records-only, ZERO code):** the user RATIFIED the deferred c>1 criterion — at concurrency > 1 the DONE bar is the near-tie-distributional form (ours ∈ vLLM's batch-nondeterministic set) + the SPEED delta, NOT strict token-exact (a proven bf16-batch-nondeterminism MODEL impossibility that affects vLLM identically). Both I6-owed DONE items are therefore CLOSED: (1) the MIXED spec+non-spec `GdnBlockPaged` split/merge (I7, model-independently bit-exact + compute-sanitizer 0) with the c2-c8 A/B on-par-or-above vLLM, and (2) the server + CLI + C-ABI(v6) `--speculative-config` flag (I5d/I7, `examples/server/main.cpp`+`examples/cli/main.cpp`+`src/capi/vllm_c.cpp`). MTP k=1 spec-decode is COMPLETE and gated: 27B three-way token-exact at c1 (I5e), c1 above vLLM on every axis (I6), c2-c8 on-par-or-above (I7), spec-OFF byte-identical SACRED (27B 235/235, 35B 315/315, Coder 138/138). This transition is byte-identical BY CONSTRUCTION (`git diff --stat` = records only; ZERO `src/`/`include/`/`examples/` touched, so the I5d/I6/I7 GPU gates stand on this exact code). Tracked follow-ons: the 35B `Qwen3_5MoeMTP` full e2e token gate (M-mtp-2) is now **CLOSED — `DONE` 2026-07-26 (`CLAIM-SPEC-MTP-M-MTP-2`)**: three-way token-exact 16/16 vs the live vLLM 0.25.0 oracle (spec-ON AND spec-OFF), acceptance 16/16 both sides, c1 spec-ON 1.19x TPOT / +16.3% output-tput vs spec-OFF (0.908) — `MODEL-SPEC-qwen3-5-mtp-qwen3-5-moe-mtp` `GATING`→`DONE`, so MTP is `DONE` on BOTH gate models. Remaining spec-decode follow-on: `SPEC-DFLASH` (oracle-BLOCKED, vllm#40898) | T1 | `vllm/v1/worker/gpu/spec_decode/mtp/speculator.py:12`; `vllm/model_executor/models/qwen3_5_mtp.py:63,129-165,192-301`; **I5d** `vllm/engine/arg_utils.py` (`--speculative-config`); `vllm/v1/worker/gpu/model_runner.py:1455-1489` | `include/vllm/config/speculative.h`; `include/vllm/v1/core/sched/scheduler.h`; `src/vllm/v1/core/sched/scheduler.cpp`; `include/vllm/v1/worker/gpu/input_batch.h`; `include/vllm/model_executor/models/qwen3_5_mtp.h:23,58`; `src/vllm/model_executor/models/qwen3_5_mtp.cpp:271`; `src/vllm/model_executor/models/qwen3_5.cpp:3336,3359`; **I5d** `src/vllm/config/speculative.cpp`; `src/vllm/entrypoints/model_loader.cpp` (`ResolveSpecConfig`/`MakeKVCacheMaybeSpec`/ctor wiring); `src/vllm/v1/worker/gpu/runner.cpp` (splice/tap/GDN spec feed/`propose_drafts`/`take_draft_token_ids`/spec-slot remap/draft-KV alloc); `examples/server/main.cpp` | `tests/vllm/v1/test_scheduler.cpp:1135,1238,1272,1316`; `tests/vllm/v1/worker/test_input_batch.cpp`; `tests/vllm/v1/spec_decode/test_mtp_speculator.cpp:201,225,263,299,331` (7/7 cases, 141 assertions); oracle runner `tests/parity/test_op_parity.cpp:1373` + focused case `:1914` (20/20 assertions, both checkpoints, `VLLM_MTP_REQUIRE_CHECKPOINTS=1`); goldens `tests/parity/goldens/qwen3_5_mtp_head_{27b,35b}/`; dump `tools/parity/dump_qwen3_5_mtp.py:144`; **I5d** `tests/parity/test_qwen27_spec_decode.cpp` (three-way gate, RUNS + measures the RCA blocker); **I6** `examples/bench/{main.cpp,bench_core.h}` (additive `--speculative-config` bench flag + acceptance telemetry); **I7** `tests/vllm/models/test_qwen3_5_gdn_spec_routing.cpp` (mixed == pure spec + prefill bit-exact), `tests/parity/test_qwen27_spec_decode_concurrent.cpp`, `tests/vt/test_ops_gdn.cpp` (IndexSelect/IndexCopy); DONE closure [ledger](parity-ledger.md#L714) | [mtp-spec-decode.md](specs/mtp-spec-decode.md) | `DONE` | `72f9fb1` | | `SPEC-MTP-K-GT-1` | **MTP speculation DEPTH (`num_speculative_tokens` > 1).** Ports the autoregressive multi-step propose the k=1 early exit sits in front of, so a configured depth is SERVED instead of silently degraded. Before it, `--num-speculative-tokens 3` reserved KV for 3, captured the verify shape at T=4 and stashed ONE draft per request, with no error and no log; a refusal by name landed first and this row removed it in the same flow. `MtpProposeDrafts` runs the prefill, the k=1 early exit, then `prepare_decode_inputs` and the k-1 single-token draft decode steps over the draft's own paged KV, with `update_draft_inputs` recording each step and feeding it forward. Greedy plus accept-if-equal makes the emitted sequence INDEPENDENT of k, so a token-identity gate cannot see a clamped drafter and every depth assertion needs a positive witness beside the identity. The per-depth counters were the FIRST witness and a fresh review proved them BLIND: they report the LENGTH of the emitted draft list, so a propose that runs one forward and pads all k columns satisfies them, and acceptance is zero at every depth on the CPU model, so no acceptance figure separates the arms either. TWO witnesses survive, because one does not cover both failures. `spec_mtp_draft_decode_forwards() == spec_mtp_propose_calls() * (k - 1)`, counted after each draft decode forward RETURNS and guarded by a non-zero call count, catches a propose that SHORT-CIRCUITS or CLAMPS. A third fresh review then proved it does NOT catch PADDING, since a loop that runs every forward and then discards what it sampled increments it honestly. `spec_mtp_proposals_with_varied_drafts()`, read at the CONSUMER on the array the propose delivered, catches exactly that. NEITHER shows per-column provenance, and neither does a non-zero acceptance count AT DEPTH, which a padded row earns whenever the target repeats a token. The owed DGX gate closes it with a per-depth acceptance RATE against a PADDED CONTROL. The CPU tier therefore proves k drafts are PROPOSED and VERIFIED, never ACCEPTED at depth. DEFAULT unchanged at k=1 (both checkpoints' `n_predict`). **NO speed number at any k>1**: the GPU was held by another session for the whole flow, so the DGX three-way at k=2..4 on the 27B and 35B and the matched-k throughput A/B are OWED, as is the bf16 GDN-state arm (the CPU gate runs the f32 arm because `vt::CausalConv1dSpecUpdate` rejects bf16 off CUDA). Also owed and filed: [#1020](https://github.com/mudler/vllm.cpp/issues/1020), a step whose ACTUAL draft count differs from the configured k leaves the captured verify graph silently. | T1 | `vllm/v1/worker/gpu/spec_decode/autoregressive/speculator.py:129-274,335-371,374-419,426-471,597-671,674-771` @ `555967922`; `vllm/config/speculative.py:967-991` | [`src/vllm/v1/worker/gpu/spec_decode/mtp/speculator.cpp`](../src/vllm/v1/worker/gpu/spec_decode/mtp/speculator.cpp) (`MtpProposeDrafts`); [`prepare_decode_inputs.cpp`](../src/vllm/v1/worker/gpu/spec_decode/autoregressive/prepare_decode_inputs.cpp); `Qwen3_5MTPModel::GatherHiddenRows` ([qwen3_5.cpp](../src/vllm/model_executor/models/qwen3_5.cpp)); `GPUModelRunner::propose_drafts` + the per-depth counters ([runner.cpp](../src/vllm/v1/worker/gpu/runner.cpp), [runner.h](../include/vllm/v1/worker/gpu/runner.h)); the in-memory `mtp_weights` seam ([model_loader.h](../include/vllm/entrypoints/model_loader.h)) | [`test_mtp_depth`](../tests/vllm/v1/spec_decode/test_mtp_depth.cpp) 5/5, 63 assertions (k=1,2,3,4 through `LoadedEngine`, greedy tokens identical to spec-OFF, each arm witnessed BOTH by the draft decode forwards the propose RAN and by whether the DELIVERED draft row varied with depth; neither witness shows per-column provenance, which is owed to the DGX gate); [`test_prepare_decode_inputs`](../tests/vllm/v1/spec_decode/test_prepare_decode_inputs.cpp) 8/8, 33 (both kernel ports + both `max_model_len` clamps, 5 mutations caught); [`test_speculative_mtp_depth`](../tests/vllm/config/test_speculative_mtp_depth.cpp) 4/4, 20; full CPU suite ctest 493 passed / 0 failed / 2 skipped of 495 (the two skips checkpoint-gated and unrelated) | [mtp-k-gt-1.md](specs/mtp-k-gt-1.md) | `ACTIVE` | `CLAIM-SPEC-MTP-K-GT-1` ([#81](https://github.com/mudler/vllm.cpp/issues/81)) | -| `SPEC-MTP-GGUF` | MTP speculative decoding from a GGUF TARGET. Today `FromModelDir` refuses `mtp`+GGUF outright (`src/vllm/entrypoints/model_loader.cpp:717-723`) on the original spike's assumption that GGUF exports carry no `mtp.*` ([mtp-spec-decode.md](specs/mtp-spec-decode.md):979-980, "until we re-export GGUFs with the head"). That is stale: llama.cpp's Qwen3.5 converter DOES emit the head, under layer-indexed `nextn` naming, and our own `HfConfigFromGguf` ALREADY reads `nextn_predict_layers` (it just discards the value into the trunk layer count). Gap is a `TensorResolver` over `GgufFile` mapping `mtp.*` onto `blk.{L+i}.nextn.*` with dequant-to-bf16, one config field, and narrowing the rejection to `dflash`. `ngram`+GGUF already works and is untouched. Qwen3.5/3.6 only (the widened spec KV path serves no other arch). NO ABI change | T2 | llama.cpp (the producer contract; vLLM has no GGUF MTP path) `conversion/qwen.py:535-604` `_Qwen35MtpMixin` (the authoritative `mtp.*`->`nextn` remapper + `add_nextn_predict_layers`); `gguf-py/gguf/constants.py:129,910-917,1494-1501`; `gguf-py/gguf/tensor_mapping.py` `NEXTN_*` | **G1-G3 LANDED 2026-07-28.** `HfConfigFromGguf` republishes the head depth `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:598` (`c.raw["mtp_num_hidden_layers"] = nextn`, previously read then discarded); the head loader `LoadQwen3_5MTPFromGguf` `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:1448` (+ decl `include/vllm/model_executor/models/qwen3_5_gguf_weights.h:143`) reusing the TRUNK helpers `OwnNormMinus1`/`OwnMatmulWeight`/`OwnBf16`/`LoadAttnGguf`/`LoadMoeGguf` so the head inherits the GGUF (w+1) norm storage, quantization/residency routing and torch [N,K] shapes; `NumMtpLayers`/`UsesDedicatedEmbeddings` exported out of the anon namespace `include/vllm/model_executor/models/qwen3_5_mtp.h`; rejection narrowed to dflash + a head-less-GGUF check `src/vllm/entrypoints/model_loader.cpp` and the head attached in the GGUF branch; **G4 GREEN + `CPU-SPEC-DIVERGENCE` FIXED 2026-07-28**: root cause `src/vllm/model_executor/models/qwen3_5.cpp:3616` sized the GDN state gather/scatter row by `(Kw-1)` while the speculative persistent row is `(Kw-1)+num_spec`, so `GatherRows`/`ScatterRows` mis-strode the slot AND every channel past the first, corrupting post-prefill recurrent state. Fix = `CopyStateRowsStrided` (same TU) used by `GatherStateF32`/`ScatterStateF32` when `cache.shape[2] != work.shape[2]`; the contiguous helpers are kept when the widths agree, so every non-spec path is byte-identical by construction. CPU-only in effect (the fp16/bf16 arm routes through the `GdnStateGather`/`Scatter` ops, so CUDA was never exposed; no GPU result affected) | `tests/vllm/models/test_qwen3_5_gguf_mtp.cpp:109,146,156,184` **4 cases, and the split is the 2026-08-21 repair** ([#1454](https://github.com/mudler/vllm.cpp/issues/1454)): the file used to be the env-gated pair ALONE, each opening on a bare `return`, so with `VLLM_MTP_GGUF_MODEL` unset it reported `test cases: 2 \| 2 passed`, **`assertions: 0`**, `Status: SUCCESS!`, exit 0 - which is every CI run of this repository, the variable being set nowhere in `.github/workflows/`. The `18 assertions` this cell used to record was the LIVE count and was never once reached in CI. Now `:109` and `:146` are **HERMETIC** (KV-only synthetic GGUFs, no weight bytes, 18 assertions on any machine) and pin the arithmetic the old file only NAMED in a comment above `CHECK(c.num_hidden_layers > 0)`: `num_hidden_layers + mtp_num_hidden_layers == block_count` over 65/1, 25/1 and 28/3 - the third arm separating `- nextn` from `- 1` - plus the head-less arm, where the key is NOT published and `NumMtpLayers` answering 1 for an absent key is exactly why the invariant cannot be written with that helper alone. `:156` and `:184` stay env-gated on `VLLM_MTP_GGUF_MODEL` (so CI stays asset-free) and now SKIP LOUDLY with a `MESSAGE` naming the variable, as `tests/vllm/entrypoints/test_gguf_mmproj_reach.cpp` does; `:156` re-derives the same invariant from the file's OWN `block_count` kv. Unset: **4 cases / 18 assertions / `Status: SUCCESS!` / rc 0**. Live on `Qwen3.8-27B-Q4_K_M.gguf` (`block_count` 65, `nextn_predict_layers` 1): **4 cases / 38 assertions / `Status: SUCCESS!` / rc 0**. Mutation-proved on the production line `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:889`, both compiling clean and both restored against a pre-taken sha256: `= block_count` (drop the subtraction) 3/4 cases, 9/18 red, exit 1; `= block_count - 1` (the wrong constant) 2/4 cases, 5/18 red, exit 1. The SAME mutations left the PREVIOUS file at 2/2 cases, 0 assertions, `SUCCESS!`, exit 0. Correctness of the production line is unchanged and was never in question (`1a4db5c3c`, `493327b4e`); this was a test defect. Live-arm content unchanged: depth reaches config.raw; fc is [H,2H] verbatim; 3 norms [H]; head block is full-attention. **RED-first BEHAVIOURAL** (reverting only the G1 line fails both cases 2/2). Trunk inertness: `test_gguf` 103, `test_gguf_qwen36_loader` 99, `test_gguf_keep_quant` 5958, `test_gguf_dequant` 215, `test_capi` 33/232 all unchanged; `tests/parity/test_qwen35_gguf_spec_decode.cpp:74,139` - spec-ON == spec-OFF token-exact with 13 proposed/11 accepted, plus an `ngram` regression guard (widens the cache, never runs the spec conv update) that was token-exact throughout and pinned the widening as innocent. Regression sweep all unchanged: ops_gdn 1825, gdn_metadata_builder 483, gdn_prefill_conv 28, gdn_spec_routing 12, gguf 103, gguf_qwen36_loader 99, gguf_keep_quant 5958, gguf_dequant 215, llm_engine 196, input_batch 163, runner 257, capi 232 **GPU CLOSE-OUT + DEVICE-DELTA ATTRIBUTION 2026-07-28 (`G5`-`G7`), ledger [parity-ledger.md#L800](parity-ledger.md#L800).** The GPU end-to-end gate re-run on a from-scratch RELEASE-TARGET build (`-DVLLM_CPP_CUDA_ARCHITECTURES=121a`, build dir DELETED first; arch VERIFIED by `build-cuda/CMakeFiles/vllm.dir/flags.make` `--generate-code=arch=compute_121a,code=[compute_121a,sm_121a]` and by `cuobjdump -lelf` 20 cubins ALL `sm_121a` zero sm_75, NOT by `CMakeCache.txt`, whose `CMAKE_CUDA_ARCHITECTURES:STRING=75` is the `enable_language(CUDA)` compiler-probe default shadowed by the normal variable at `CMakeLists.txt:186` - the prior wrong-arch conclusion was that decoy): dgx.casa GB10 under `flock $HOME/gpu.lock`, 35B A3B NVFP4 GGUF, **2/2 cases, 10/10 assertions, exit 0**, spec-ON token-identical to spec-OFF, 13 proposed / 11 accepted, 90.2 GiB peak RSS, 8m01s; re-run on the EXACT committed source **3/3 cases, 10/10 assertions, exit 0**, 7m25s, the new probe case SKIPping and adding zero assertions. **The CPU-vs-GPU token delta is a MEASURED near-tie, not a defect** (it was never this row's bar - spec-ON == spec-OFF WITHIN a device is): NEW double-gated spec-OFF-only probe `tests/parity/test_qwen35_gguf_spec_decode.cpp:217` (asset + `VLLM_MTP_GGUF_PROBE=1`, 20 alternatives per position, 484/484 assertions per arm, GPU then `CUDA_VISIBLE_DEVICES=` in one `flock` series) shows both arms picking `11751` at position 0 and forking at position 1 on a BIT-IDENTICAL prefix: GPU rank1 `13` -0.773180 over rank2 `11` -0.847055 (margin 0.0739 nats), CPU rank1 `11` -0.765499 over rank2 `13` -0.830374 (margin 0.0649 nats). Each device's pick is the other's rank 2, both ~7x inside the ratified 0.5-nat band, and the cross-device disagreement on the SAME token (0.057 and 0.082 nats) EXCEEDS the margin being decided, so rounding settles it; the 24 texts look unrelated only because positions 2+ cascade off that one coin flip. Margin sweep over all 24 positions: **GGUF GPU and GGUF CPU carry ZERO exact ties**, minimum margins 0.0482 and 0.0649 nats, and both arms reproduced their sequence across every run. **Gate 4 MET on the safetensors sibling of the same quantization run** (`FromModelDir` takes it unchanged): acceptance 12 proposed / 11 accepted vs the GGUF's 13 / 11. That arm, however, FAILS spec-ON == spec-OFF at concurrency 1 and does not reproduce its own spec-OFF sequence run to run, and the probe attributes both to THREE EXACT ties (positions 7, 10, 16, bit-identical logprobs) produced by its 1/16-grid quantized-GEMM logits - which EXONERATES the GGUF arm and opens a recorded, not-root-caused `SPEC-MTP` item on the safetensors NVFP4 path, not on this row. Gate 3 is NOT APPLICABLE twice over: no F16/F32 head-carrying export exists, and the only same-weights sibling is not token-stable against itself. **EVIDENCE RE-ANCHORED 2026-07-29 to a PRODUCTION-CONFIGURED build, because every GPU number above came from a build configured WITHOUT `-DVLLM_CPP_CUTLASS_DIR` and WITHOUT `-DVLLM_CPP_TRITON=ON`** (the defect `CLAIM-27B-GATE-RCA` proved, which runs the emulation fp4 GEMM + hand GDN kernels). Re-run from a clean `git archive` tree of `main` `3f34534d`, build proven correct three ways (configure log has ZERO `CUTLASS not found` and prints `CUTLASS found ... sm120a NVFP4 cutlass GEMM` + `FlashAttention-2 ... ENABLED for arch(es) [121a]` + the vendored `sm_121a` Triton-AOT lines with `MANIFEST hashes OK`; `cuobjdump -lelf` 40 cubins ALL `sm_121a`, zero `sm_75`; SACRED `test_qwen27_paged_engine` **235/235 exit 0**, and the build precondition proven to FIRE by recompiling only that TU without the two defines against the same `libvllm.a`, which throws and exits 1 with 0 assertions). **The row PASSES UNCHANGED:** `tests/parity/test_qwen35_gguf_spec_decode` **3/3 cases, 10/10 assertions, exit 0**, spec-ON token-identical to spec-OFF, **13 proposed / 11 accepted (identical to the recorded number)**, 90.26 GiB, 7m13.59s; loader gate 19 assertions on the Qwen3.5-2B and 18 on the 35B A3B, unchanged. **ONE recorded finding is RETRACTED by the re-measurement: the CPU-vs-GPU token delta was a BUILD artifact, not a device near-tie cascade.** On the production build both devices emit the SAME 24 tokens; the probe shows GPU rank1 `11` -0.763897 over rank2 `13` -0.824083 where the defective build had rank1 `13` -0.773180 over rank2 `11` -0.847055, while the CPU arm is bit-identical to the earlier measurement (CUTLASS and Triton are CUDA-only). Zero exact ties in either arm, min margins 0.060186 GPU / 0.064875 CPU, 484/484 assertions per arm. Evidence: [docs/BENCHMARKS.md](../docs/BENCHMARKS.md) top section, [parity-ledger.md](parity-ledger.md) | [specs/gguf-mtp-spec-decode.md](specs/gguf-mtp-spec-decode.md) | `DONE` | `edf91449` | -| `SPEC-DFLASH-GGUF` | DFlash speculative decoding from GGUF, two axes: (A) GGUF DRAFT + safetensors target, (B) GGUF target too. llama.cpp master carries a full `dflash` GGUF contract (arch string `dflash`, tensors `fc`/`enc.output_norm`/`output_norm`/`blk.N.*`, KVs `dflash.target_layers` + `dflash.target_hidden_size`); the arch is ABSENT from checkouts older than ~2026-07, so a stale tree reads as "no contract exists". The GGUF tensor set omits `token_embd`/`output` because the draft SHARES the target's embed+lm_head, which is exactly what `LoadDflashDraft` already does. Blockers are in the loader, not the model: `MakeDflashDraftConfig` reads `draft_dir/config.json` (a GGUF has none), `ResolveDflashDraftDir` probes for `config.json` so it cannot see a `.gguf`, and `LoadDflashDraft` is typed on `std::vector` for the shared bf16 head (the axis-B blocker). Axis A independently shippable. NO ABI change | T2 | llama.cpp `origin/master` @ 2026-07-28 (tag era `b10158`): `gguf-py/gguf/constants.py:547,1151,4350`; `gguf-py/gguf/tensor_mapping.py:1297-1305` (`ENC_OUTPUT_NORM`<-`model.hidden_norm`, `FC`<-`model.fc`); `conversion/qwen.py:351` (mask token via the standard tokenizer KV); `convert_hf_to_gguf.py --target-model-dir` | **GD1-GD7 LANDED 2026-07-28 (BOTH AXES COMPLETE and PROVEN end to end on GB10)**: `MakeDflashGgufConfig` + `LoadQwen3DFlashFromGguf` `src/vllm/model_executor/models/qwen3_dflash_gguf.cpp:88,227` (+ header), `IsDflashGgufDraft` + the `.gguf` branch in `ResolveDflashDraftDir`/`LoadDflashDraft` `src/vllm/entrypoints/model_loader.cpp:121,222`. Goes through the `TensorResolver` seam (unlike `SPEC-MTP-GGUF`) because dflash norms are RAW, so the existing `LoadQwen3DFlash` qkv/gate_up concatenation is reused unchanged. **`GD4` defect FIXED** (`model_loader.cpp:238-249`): the GGUF branch left `config.vocab_size` 0 - correct for `MakeDflashGgufConfig` (the DFLASH arch has no vocab KV and no `token_embd`) but fatal for the forward, which sizes the shared embedding view as `{config.vocab_size, H}`, so the first propose threw `cuda embedding: empty table (vocab 0)`. Now back-filled from the target's `embed_tokens` rows (the condition is on the VALUE, not the draft source, so it generalizes to a GGUF target). Load-level green had hidden it; only GENERATING found it. **GD5-GD7 = axis B**: `SharedHeadSource` `src/vllm/entrypoints/model_loader.cpp` re-expresses the shared bf16 `embed_tokens`+`lm_head` seam as a SOURCE and re-types `LoadDflashDraft`'s second parameter - THAT TYPE was the whole axis-B blocker - with the GGUF arm `LoadGgufSharedEmbedAndHeadBf16` `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:1035` reusing the trunk loader's tied-embedding rule and sidecar-aware dequant instead of restating them; the shared-head load moved into ONE common tail so all four (draft format x target container) combinations run identical code; the `dflash` half of the GGUF-branch rejection `model_loader.cpp` is deleted (the `mtp` half untouched) and the draft load is wired into the GGUF branch | `tests/vllm/models/test_qwen3_dflash_gguf.cpp:36,84` 2 cases / 47 assertions against the REAL published Qwen3.6-27B DFlash draft (env-gated `VLLM_DFLASH_GGUF_MODEL`, CI asset-free): the +1 target-layer offset undone against the KV read back from the same file, block_size/mask_token present, vocab_size left 0, layer_types cover every block, fc `[H, H*num_taps]` with `nk` SET, qkv/gate_up row-concat shapes, embed/lm_head left EMPTY for the target. **RED-first BEHAVIOURAL** (dropping the `-1` fails the offset checks). **`GD4` e2e gate** `tests/parity/test_qwen27_dflash_spec_decode.cpp:343` (second case, draft source env-driven via `VLLM_DFLASH_DRAFT`/`_B`; asset-gated, CI-inert): on dgx GB10 sm_121a against the Qwen3.6-27B NVFP4 safetensors target, the Q4_K_M GGUF draft and the bf16 z-lab safetensors draft produce **token-for-token IDENTICAL** DFlash-ON continuations with **IDENTICAL** accepted/proposed (20/80 on a 24-token prompt, 42/96 on a 48-token prompt), spec-OFF self-reproducible 3/3 and 0 exact ties (min margin 0.197/0.400 nats). Regression: gguf_mtp 19, qwen35_gguf_spec_decode 10, gguf 103, gguf_qwen36_loader 99, gguf_keep_quant 5958, ops_gdn 1825, llm_engine 196, capi 232, runner 257 all unchanged. **`GD5` unit gate** `tests/vllm/test_gguf_qwen36_loader.cpp` 3 new synthetic-GGUF cases (6 cases / 286 assertions total, CPU and the dgx CUDA build): the untied head really comes from `output.weight` and not the embedding (distinct fill values), the tied fallback aliases it onto `token_embd`, the `nk` flags separate the gather table from the MatmulBT weight, a file with no `token_embd` is refused. 3-mutant battery, 3 caught (`nk` flipped, head forced to the embedding, tied forced false). **`GD7` e2e gate** `tests/parity/test_qwen27_dflash_spec_decode.cpp` third case (targets env-driven via `VLLM_DFLASH_TARGET_B`; asset-gated, CI-inert): on dgx GB10 sm_121a the Qwen3.6-27B NVFP4 **GGUF** target + `Q4_K_M` GGUF draft loads, takes the shared head from the GGUF, generates, and its DFlash-ON continuation is **token-for-token IDENTICAL to that same target's spec-OFF** (24/24, the STRICT form) with acceptance ALIVE at 14/160; 1 case / 15 assertions, exit 0. **The spike's highest risk is EMPTY on this asset, proven not assumed**: the 27B NVFP4 GGUF stores `token_embd`/`output` as ggml BF16, byte-identical to the safetensors sibling (2,542,796,800 bytes each, ZERO differing), so B1's shared-head read is verbatim, not a dequant. Acceptance IS lower than the safetensors-target arm and is NOT chargeable to the head: the two containers diverge at index 4 with NO speculation, because `QUANT-GGUF-NVFP4` is dequant-only so the GGUF target computes in bf16 while the safetensors target runs the true W4A4 kernels. **RE-MEASURED 2026-07-29 on a PRODUCTION-CONFIGURED build (`CLAIM-GGUF-SPEC-REVERIFY`), because every GD4/GD7 GPU number above came from a build configured WITHOUT `-DVLLM_CPP_CUTLASS_DIR` and WITHOUT `-DVLLM_CPP_TRITON=ON`.** Build proven correct three ways (see the `SPEC-MTP-GGUF` row; SACRED 27B **235/235**, `cuobjdump` 40 cubins all `sm_121a`). **AXIS B HOLDS EXACTLY**: `test_qwen27_dflash_spec_decode -tc="dflash axis-B*"` **15/15 assertions, exit 0**, GGUF-target DFlash-ON token-identical to that target's own spec-OFF 24/24, acceptance **14/160 unchanged**, cross-target spec-OFF divergence still at index 4, 81.01 GiB peak RSS, 6m53.08s. **AXIS A WAS RED ON THE 48-TOKEN PROMPT (reproducibly, 3 of 3 runs) AND IS NOW CLOSED.** The RED was real: cross-format TOKEN identity held on both prompts, but the exact accept-count half of bar (a) failed (`arm_a.proposed == arm_b.proposed` / `arm_a.accepted == arm_b.accepted`) because the Q4_K_M draft measured **46/112** against the bf16 z-lab draft's **47/96** (one extra 16-wide propose block, one fewer acceptance, zero token difference), 15/17, exit 1; the 24-token prompt stayed green at 17/17 with both drafts at 15/144. **`GD9` 2026-07-29 root-caused it IN WEIGHT SPACE as ordinary `Q4_K_M` cost, category (a), not a defect in our GGUF draft path - and the bar's own premise ("Same weights, two containers") was false for the asset it was pointed at.** The publishing repo also carries an UNQUANTIZED `BF16` GGUF (3,471,497,440 B) beside `Q8_0`/`Q6_K`/`Q5_K`/`Q4_K_M`, which the spec had recorded as nonexistent; that retired the `NOT APPLICABLE` on gate 2. CPU gate `tests/vllm/models/test_qwen3_dflash_gguf.cpp` third case (asset-gated `VLLM_DFLASH_GGUF_BF16_MODEL` + `VLLM_DFLASH_ST_DIR`): `LoadQwen3DFlashFromGguf(BF16)` is **BYTE-IDENTICAL to `LoadQwen3DFlash(z-lab shards)` on all 58 tensors, 302/302 assertions, exit 0**, and FUNCTIONALLY RED against the `Q4_K_M` file (21/302 red, exactly the 21 quantized matmul tensors), so not a vacuous pass. Supporting: our `DequantGgufRowToBf16` is bit-equal to `gguf-py`'s `gguf.quants.dequantize` on the real `fc.weight` (Q4_K), `blk.0.attn_q.weight` (Q4_K) and `blk.2.ffn_down.weight` (Q6_K), zero differing bf16 values; the ladder's mean relative weight error is monotone and uniform with NO outlier tensor (BF16 0, Q8_0 5.6e-3, Q6_K 1.85e-2, Q5_K 3.85e-2, Q4_K_M 7.6e-2); the only numeric config delta is `rms_norm_eps` at 2.5e-9 relative. Also landed: an off-by-default `VT_SPEC_TRACE=1` per-block propose/accept trace in `GPUModelRunner::sample_tokens_with_rejection` (`src/vllm/v1/worker/gpu/runner.cpp`). **`GD10` 2026-07-29 CONFIRMED IT END TO END ON GB10 and closed gates 3 and 5.** Build proven production-configured three ways (configure log 0 `CUTLASS not found`; `cuobjdump -lelf` 40 cubins ALL `sm_121a` zero `sm_75` on both binaries; SACRED `test_qwen27_paged_engine` **235/235, exit 0**, 31.34s, 23.67 GiB). The **`BF16` GGUF draft reads EXACTLY 47/96**, the safetensors draft's own number, at 48 tokens on the discriminating prompt - reproduced 2 of 2 - plus 27/64 = 27/64 at 24 tokens and 15/144 = 15/144 on the second prompt, tokens IDENTICAL throughout, 17/17 exit 0 each time; the `Q4_K_M` arm reads 46/112 on the SAME binary in the SAME `flock` series. Restoring only the draft's numeric precision restores the count, so quantization is the whole cause and nothing structural survives. Bar (a) is consequently SPLIT rather than relaxed (`tests/parity/test_qwen27_dflash_spec_decode.cpp`): tokens stay EXACT unconditionally; accept counts are EXACT on a cross-FORMAT arm and BANDED (`abs(d_accepted) <= 2`, `abs(d_proposed) <= k*2`) on a cross-QUANTIZATION one, with the arm chosen by `IsQuantizedGgufDraft` reading the draft file's ggml types (`GgmlTraits().block_elems > 1`) rather than by a flag. The band is derived, not picked: measured `d_accepted` is 0, 0, -1, so the bound is that maximum plus one quantum; and `d_proposed = -k * d_accepted` EXACTLY once the token streams match (confirmed at -1 / +16), so the proposed bound follows. **Mutation-proved non-vacuous**: rebuilt at band 0 the `Q4_K_M` arm is 15/17 exit 1 while the `BF16` arm stays 17/17 exit 0 on the exact branch. **AXIS B BROADENED from ONE prompt to THREE**, strict form green on all: "The capital of France is" IDENTICAL 14/160 (15/15), "Write a Python function that reverses a string:" IDENTICAL 24/64 (15/15), "Photosynthesis is the process by which" IDENTICAL 15/128 (9/9), all exit 0, ~6m30-6m52 and ~81 GiB peak RSS each. The second prompt REFINES the recorded acceptance claim: the safetensors-target arm is ALSO 24/64 there with the two containers' DFlash-ON streams IDENTICAL, so the GGUF target's lower acceptance is prompt-dependent (their spec-OFF streams diverge at index 4 on the first prompt, index 16 on the second) and not a standing penalty; the cause remains `QUANT-GGUF-NVFP4` being dequant-only, with the shared head excluded by a byte comparison. Gates 1-5 and 7 MET; gate 6 (speed) `PENDING` BY DESIGN and not owed - a DFlash-ON throughput A/B between the two target containers is not a fair comparison until a native NVFP4 GGUF GEMM exists. Evidence: [docs/BENCHMARKS.md](../docs/BENCHMARKS.md) top section, [parity-ledger.md](parity-ledger.md#L845) | [specs/gguf-dflash-draft.md](specs/gguf-dflash-draft.md) | `DONE` | `c62f2fa3` | +| `SPEC-MTP-GGUF` | MTP speculative decoding from a GGUF TARGET. Today `FromModelDir` refuses `mtp`+GGUF outright (`src/vllm/entrypoints/model_loader.cpp:717-723`) on the original spike's assumption that GGUF exports carry no `mtp.*` ([mtp-spec-decode.md](specs/mtp-spec-decode.md):979-980, "until we re-export GGUFs with the head"). That is stale: llama.cpp's Qwen3.5 converter DOES emit the head, under layer-indexed `nextn` naming, and our own `HfConfigFromGguf` ALREADY reads `nextn_predict_layers` (it just discards the value into the trunk layer count). Gap is a `TensorResolver` over `GgufFile` mapping `mtp.*` onto `blk.{L+i}.nextn.*` with dequant-to-bf16, one config field, and narrowing the rejection to `dflash`. `ngram`+GGUF already works and is untouched. Qwen3.5/3.6 only (the widened spec KV path serves no other arch). NO ABI change | T2 | llama.cpp (the producer contract; vLLM has no GGUF MTP path) `conversion/qwen.py:535-604` `_Qwen35MtpMixin` (the authoritative `mtp.*`->`nextn` remapper + `add_nextn_predict_layers`); `gguf-py/gguf/constants.py:129,910-917,1494-1501`; `gguf-py/gguf/tensor_mapping.py` `NEXTN_*` | **G1-G3 LANDED 2026-07-28.** `HfConfigFromGguf` republishes the head depth `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:598` (`c.raw["mtp_num_hidden_layers"] = nextn`, previously read then discarded); the head loader `LoadQwen3_5MTPFromGguf` `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:1453` (+ decl `include/vllm/model_executor/models/qwen3_5_gguf_weights.h:143`) reusing the TRUNK helpers `OwnNormMinus1`/`OwnMatmulWeight`/`OwnBf16`/`LoadAttnGguf`/`LoadMoeGguf` so the head inherits the GGUF (w+1) norm storage, quantization/residency routing and torch [N,K] shapes; `NumMtpLayers`/`UsesDedicatedEmbeddings` exported out of the anon namespace `include/vllm/model_executor/models/qwen3_5_mtp.h`; rejection narrowed to dflash + a head-less-GGUF check `src/vllm/entrypoints/model_loader.cpp` and the head attached in the GGUF branch; **G4 GREEN + `CPU-SPEC-DIVERGENCE` FIXED 2026-07-28**: root cause `src/vllm/model_executor/models/qwen3_5.cpp:3616` sized the GDN state gather/scatter row by `(Kw-1)` while the speculative persistent row is `(Kw-1)+num_spec`, so `GatherRows`/`ScatterRows` mis-strode the slot AND every channel past the first, corrupting post-prefill recurrent state. Fix = `CopyStateRowsStrided` (same TU) used by `GatherStateF32`/`ScatterStateF32` when `cache.shape[2] != work.shape[2]`; the contiguous helpers are kept when the widths agree, so every non-spec path is byte-identical by construction. CPU-only in effect (the fp16/bf16 arm routes through the `GdnStateGather`/`Scatter` ops, so CUDA was never exposed; no GPU result affected) | `tests/vllm/models/test_qwen3_5_gguf_mtp.cpp:109,146,156,184` **4 cases, and the split is the 2026-08-21 repair** ([#1454](https://github.com/mudler/vllm.cpp/issues/1454)): the file used to be the env-gated pair ALONE, each opening on a bare `return`, so with `VLLM_MTP_GGUF_MODEL` unset it reported `test cases: 2 \| 2 passed`, **`assertions: 0`**, `Status: SUCCESS!`, exit 0 - which is every CI run of this repository, the variable being set nowhere in `.github/workflows/`. The `18 assertions` this cell used to record was the LIVE count and was never once reached in CI. Now `:109` and `:146` are **HERMETIC** (KV-only synthetic GGUFs, no weight bytes, 18 assertions on any machine) and pin the arithmetic the old file only NAMED in a comment above `CHECK(c.num_hidden_layers > 0)`: `num_hidden_layers + mtp_num_hidden_layers == block_count` over 65/1, 25/1 and 28/3 - the third arm separating `- nextn` from `- 1` - plus the head-less arm, where the key is NOT published and `NumMtpLayers` answering 1 for an absent key is exactly why the invariant cannot be written with that helper alone. `:156` and `:184` stay env-gated on `VLLM_MTP_GGUF_MODEL` (so CI stays asset-free) and now SKIP LOUDLY with a `MESSAGE` naming the variable, as `tests/vllm/entrypoints/test_gguf_mmproj_reach.cpp` does; `:156` re-derives the same invariant from the file's OWN `block_count` kv. Unset: **4 cases / 18 assertions / `Status: SUCCESS!` / rc 0**. Live on `Qwen3.8-27B-Q4_K_M.gguf` (`block_count` 65, `nextn_predict_layers` 1): **4 cases / 38 assertions / `Status: SUCCESS!` / rc 0**. Mutation-proved on the production line `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:889`, both compiling clean and both restored against a pre-taken sha256: `= block_count` (drop the subtraction) 3/4 cases, 9/18 red, exit 1; `= block_count - 1` (the wrong constant) 2/4 cases, 5/18 red, exit 1. The SAME mutations left the PREVIOUS file at 2/2 cases, 0 assertions, `SUCCESS!`, exit 0. Correctness of the production line is unchanged and was never in question (`1a4db5c3c`, `493327b4e`); this was a test defect. Live-arm content unchanged: depth reaches config.raw; fc is [H,2H] verbatim; 3 norms [H]; head block is full-attention. **RED-first BEHAVIOURAL** (reverting only the G1 line fails both cases 2/2). Trunk inertness: `test_gguf` 103, `test_gguf_qwen36_loader` 99, `test_gguf_keep_quant` 5958, `test_gguf_dequant` 215, `test_capi` 33/232 all unchanged; `tests/parity/test_qwen35_gguf_spec_decode.cpp:74,139` - spec-ON == spec-OFF token-exact with 13 proposed/11 accepted, plus an `ngram` regression guard (widens the cache, never runs the spec conv update) that was token-exact throughout and pinned the widening as innocent. Regression sweep all unchanged: ops_gdn 1825, gdn_metadata_builder 483, gdn_prefill_conv 28, gdn_spec_routing 12, gguf 103, gguf_qwen36_loader 99, gguf_keep_quant 5958, gguf_dequant 215, llm_engine 196, input_batch 163, runner 257, capi 232 **GPU CLOSE-OUT + DEVICE-DELTA ATTRIBUTION 2026-07-28 (`G5`-`G7`), ledger [parity-ledger.md#L800](parity-ledger.md#L800).** The GPU end-to-end gate re-run on a from-scratch RELEASE-TARGET build (`-DVLLM_CPP_CUDA_ARCHITECTURES=121a`, build dir DELETED first; arch VERIFIED by `build-cuda/CMakeFiles/vllm.dir/flags.make` `--generate-code=arch=compute_121a,code=[compute_121a,sm_121a]` and by `cuobjdump -lelf` 20 cubins ALL `sm_121a` zero sm_75, NOT by `CMakeCache.txt`, whose `CMAKE_CUDA_ARCHITECTURES:STRING=75` is the `enable_language(CUDA)` compiler-probe default shadowed by the normal variable at `CMakeLists.txt:186` - the prior wrong-arch conclusion was that decoy): dgx.casa GB10 under `flock $HOME/gpu.lock`, 35B A3B NVFP4 GGUF, **2/2 cases, 10/10 assertions, exit 0**, spec-ON token-identical to spec-OFF, 13 proposed / 11 accepted, 90.2 GiB peak RSS, 8m01s; re-run on the EXACT committed source **3/3 cases, 10/10 assertions, exit 0**, 7m25s, the new probe case SKIPping and adding zero assertions. **The CPU-vs-GPU token delta is a MEASURED near-tie, not a defect** (it was never this row's bar - spec-ON == spec-OFF WITHIN a device is): NEW double-gated spec-OFF-only probe `tests/parity/test_qwen35_gguf_spec_decode.cpp:217` (asset + `VLLM_MTP_GGUF_PROBE=1`, 20 alternatives per position, 484/484 assertions per arm, GPU then `CUDA_VISIBLE_DEVICES=` in one `flock` series) shows both arms picking `11751` at position 0 and forking at position 1 on a BIT-IDENTICAL prefix: GPU rank1 `13` -0.773180 over rank2 `11` -0.847055 (margin 0.0739 nats), CPU rank1 `11` -0.765499 over rank2 `13` -0.830374 (margin 0.0649 nats). Each device's pick is the other's rank 2, both ~7x inside the ratified 0.5-nat band, and the cross-device disagreement on the SAME token (0.057 and 0.082 nats) EXCEEDS the margin being decided, so rounding settles it; the 24 texts look unrelated only because positions 2+ cascade off that one coin flip. Margin sweep over all 24 positions: **GGUF GPU and GGUF CPU carry ZERO exact ties**, minimum margins 0.0482 and 0.0649 nats, and both arms reproduced their sequence across every run. **Gate 4 MET on the safetensors sibling of the same quantization run** (`FromModelDir` takes it unchanged): acceptance 12 proposed / 11 accepted vs the GGUF's 13 / 11. That arm, however, FAILS spec-ON == spec-OFF at concurrency 1 and does not reproduce its own spec-OFF sequence run to run, and the probe attributes both to THREE EXACT ties (positions 7, 10, 16, bit-identical logprobs) produced by its 1/16-grid quantized-GEMM logits - which EXONERATES the GGUF arm and opens a recorded, not-root-caused `SPEC-MTP` item on the safetensors NVFP4 path, not on this row. Gate 3 is NOT APPLICABLE twice over: no F16/F32 head-carrying export exists, and the only same-weights sibling is not token-stable against itself. **EVIDENCE RE-ANCHORED 2026-07-29 to a PRODUCTION-CONFIGURED build, because every GPU number above came from a build configured WITHOUT `-DVLLM_CPP_CUTLASS_DIR` and WITHOUT `-DVLLM_CPP_TRITON=ON`** (the defect `CLAIM-27B-GATE-RCA` proved, which runs the emulation fp4 GEMM + hand GDN kernels). Re-run from a clean `git archive` tree of `main` `3f34534d`, build proven correct three ways (configure log has ZERO `CUTLASS not found` and prints `CUTLASS found ... sm120a NVFP4 cutlass GEMM` + `FlashAttention-2 ... ENABLED for arch(es) [121a]` + the vendored `sm_121a` Triton-AOT lines with `MANIFEST hashes OK`; `cuobjdump -lelf` 40 cubins ALL `sm_121a`, zero `sm_75`; SACRED `test_qwen27_paged_engine` **235/235 exit 0**, and the build precondition proven to FIRE by recompiling only that TU without the two defines against the same `libvllm.a`, which throws and exits 1 with 0 assertions). **The row PASSES UNCHANGED:** `tests/parity/test_qwen35_gguf_spec_decode` **3/3 cases, 10/10 assertions, exit 0**, spec-ON token-identical to spec-OFF, **13 proposed / 11 accepted (identical to the recorded number)**, 90.26 GiB, 7m13.59s; loader gate 19 assertions on the Qwen3.5-2B and 18 on the 35B A3B, unchanged. **ONE recorded finding is RETRACTED by the re-measurement: the CPU-vs-GPU token delta was a BUILD artifact, not a device near-tie cascade.** On the production build both devices emit the SAME 24 tokens; the probe shows GPU rank1 `11` -0.763897 over rank2 `13` -0.824083 where the defective build had rank1 `13` -0.773180 over rank2 `11` -0.847055, while the CPU arm is bit-identical to the earlier measurement (CUTLASS and Triton are CUDA-only). Zero exact ties in either arm, min margins 0.060186 GPU / 0.064875 CPU, 484/484 assertions per arm. Evidence: [docs/BENCHMARKS.md](../docs/BENCHMARKS.md) top section, [parity-ledger.md](parity-ledger.md) | [specs/gguf-mtp-spec-decode.md](specs/gguf-mtp-spec-decode.md) | `DONE` | `edf91449` | +| `SPEC-DFLASH-GGUF` | DFlash speculative decoding from GGUF, two axes: (A) GGUF DRAFT + safetensors target, (B) GGUF target too. llama.cpp master carries a full `dflash` GGUF contract (arch string `dflash`, tensors `fc`/`enc.output_norm`/`output_norm`/`blk.N.*`, KVs `dflash.target_layers` + `dflash.target_hidden_size`); the arch is ABSENT from checkouts older than ~2026-07, so a stale tree reads as "no contract exists". The GGUF tensor set omits `token_embd`/`output` because the draft SHARES the target's embed+lm_head, which is exactly what `LoadDflashDraft` already does. Blockers are in the loader, not the model: `MakeDflashDraftConfig` reads `draft_dir/config.json` (a GGUF has none), `ResolveDflashDraftDir` probes for `config.json` so it cannot see a `.gguf`, and `LoadDflashDraft` is typed on `std::vector` for the shared bf16 head (the axis-B blocker). Axis A independently shippable. NO ABI change | T2 | llama.cpp `origin/master` @ 2026-07-28 (tag era `b10158`): `gguf-py/gguf/constants.py:547,1151,4350`; `gguf-py/gguf/tensor_mapping.py:1297-1305` (`ENC_OUTPUT_NORM`<-`model.hidden_norm`, `FC`<-`model.fc`); `conversion/qwen.py:351` (mask token via the standard tokenizer KV); `convert_hf_to_gguf.py --target-model-dir` | **GD1-GD7 LANDED 2026-07-28 (BOTH AXES COMPLETE and PROVEN end to end on GB10)**: `MakeDflashGgufConfig` + `LoadQwen3DFlashFromGguf` `src/vllm/model_executor/models/qwen3_dflash_gguf.cpp:88,227` (+ header), `IsDflashGgufDraft` + the `.gguf` branch in `ResolveDflashDraftDir`/`LoadDflashDraft` `src/vllm/entrypoints/model_loader.cpp:121,222`. Goes through the `TensorResolver` seam (unlike `SPEC-MTP-GGUF`) because dflash norms are RAW, so the existing `LoadQwen3DFlash` qkv/gate_up concatenation is reused unchanged. **`GD4` defect FIXED** (`model_loader.cpp:238-249`): the GGUF branch left `config.vocab_size` 0 - correct for `MakeDflashGgufConfig` (the DFLASH arch has no vocab KV and no `token_embd`) but fatal for the forward, which sizes the shared embedding view as `{config.vocab_size, H}`, so the first propose threw `cuda embedding: empty table (vocab 0)`. Now back-filled from the target's `embed_tokens` rows (the condition is on the VALUE, not the draft source, so it generalizes to a GGUF target). Load-level green had hidden it; only GENERATING found it. **GD5-GD7 = axis B**: `SharedHeadSource` `src/vllm/entrypoints/model_loader.cpp` re-expresses the shared bf16 `embed_tokens`+`lm_head` seam as a SOURCE and re-types `LoadDflashDraft`'s second parameter - THAT TYPE was the whole axis-B blocker - with the GGUF arm `LoadGgufSharedEmbedAndHeadBf16` `src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp:1040` reusing the trunk loader's tied-embedding rule and sidecar-aware dequant instead of restating them; the shared-head load moved into ONE common tail so all four (draft format x target container) combinations run identical code; the `dflash` half of the GGUF-branch rejection `model_loader.cpp` is deleted (the `mtp` half untouched) and the draft load is wired into the GGUF branch | `tests/vllm/models/test_qwen3_dflash_gguf.cpp:36,84` 2 cases / 47 assertions against the REAL published Qwen3.6-27B DFlash draft (env-gated `VLLM_DFLASH_GGUF_MODEL`, CI asset-free): the +1 target-layer offset undone against the KV read back from the same file, block_size/mask_token present, vocab_size left 0, layer_types cover every block, fc `[H, H*num_taps]` with `nk` SET, qkv/gate_up row-concat shapes, embed/lm_head left EMPTY for the target. **RED-first BEHAVIOURAL** (dropping the `-1` fails the offset checks). **`GD4` e2e gate** `tests/parity/test_qwen27_dflash_spec_decode.cpp:343` (second case, draft source env-driven via `VLLM_DFLASH_DRAFT`/`_B`; asset-gated, CI-inert): on dgx GB10 sm_121a against the Qwen3.6-27B NVFP4 safetensors target, the Q4_K_M GGUF draft and the bf16 z-lab safetensors draft produce **token-for-token IDENTICAL** DFlash-ON continuations with **IDENTICAL** accepted/proposed (20/80 on a 24-token prompt, 42/96 on a 48-token prompt), spec-OFF self-reproducible 3/3 and 0 exact ties (min margin 0.197/0.400 nats). Regression: gguf_mtp 19, qwen35_gguf_spec_decode 10, gguf 103, gguf_qwen36_loader 99, gguf_keep_quant 5958, ops_gdn 1825, llm_engine 196, capi 232, runner 257 all unchanged. **`GD5` unit gate** `tests/vllm/test_gguf_qwen36_loader.cpp` 3 new synthetic-GGUF cases (6 cases / 286 assertions total, CPU and the dgx CUDA build): the untied head really comes from `output.weight` and not the embedding (distinct fill values), the tied fallback aliases it onto `token_embd`, the `nk` flags separate the gather table from the MatmulBT weight, a file with no `token_embd` is refused. 3-mutant battery, 3 caught (`nk` flipped, head forced to the embedding, tied forced false). **`GD7` e2e gate** `tests/parity/test_qwen27_dflash_spec_decode.cpp` third case (targets env-driven via `VLLM_DFLASH_TARGET_B`; asset-gated, CI-inert): on dgx GB10 sm_121a the Qwen3.6-27B NVFP4 **GGUF** target + `Q4_K_M` GGUF draft loads, takes the shared head from the GGUF, generates, and its DFlash-ON continuation is **token-for-token IDENTICAL to that same target's spec-OFF** (24/24, the STRICT form) with acceptance ALIVE at 14/160; 1 case / 15 assertions, exit 0. **The spike's highest risk is EMPTY on this asset, proven not assumed**: the 27B NVFP4 GGUF stores `token_embd`/`output` as ggml BF16, byte-identical to the safetensors sibling (2,542,796,800 bytes each, ZERO differing), so B1's shared-head read is verbatim, not a dequant. Acceptance IS lower than the safetensors-target arm and is NOT chargeable to the head: the two containers diverge at index 4 with NO speculation, because `QUANT-GGUF-NVFP4` is dequant-only so the GGUF target computes in bf16 while the safetensors target runs the true W4A4 kernels. **RE-MEASURED 2026-07-29 on a PRODUCTION-CONFIGURED build (`CLAIM-GGUF-SPEC-REVERIFY`), because every GD4/GD7 GPU number above came from a build configured WITHOUT `-DVLLM_CPP_CUTLASS_DIR` and WITHOUT `-DVLLM_CPP_TRITON=ON`.** Build proven correct three ways (see the `SPEC-MTP-GGUF` row; SACRED 27B **235/235**, `cuobjdump` 40 cubins all `sm_121a`). **AXIS B HOLDS EXACTLY**: `test_qwen27_dflash_spec_decode -tc="dflash axis-B*"` **15/15 assertions, exit 0**, GGUF-target DFlash-ON token-identical to that target's own spec-OFF 24/24, acceptance **14/160 unchanged**, cross-target spec-OFF divergence still at index 4, 81.01 GiB peak RSS, 6m53.08s. **AXIS A WAS RED ON THE 48-TOKEN PROMPT (reproducibly, 3 of 3 runs) AND IS NOW CLOSED.** The RED was real: cross-format TOKEN identity held on both prompts, but the exact accept-count half of bar (a) failed (`arm_a.proposed == arm_b.proposed` / `arm_a.accepted == arm_b.accepted`) because the Q4_K_M draft measured **46/112** against the bf16 z-lab draft's **47/96** (one extra 16-wide propose block, one fewer acceptance, zero token difference), 15/17, exit 1; the 24-token prompt stayed green at 17/17 with both drafts at 15/144. **`GD9` 2026-07-29 root-caused it IN WEIGHT SPACE as ordinary `Q4_K_M` cost, category (a), not a defect in our GGUF draft path - and the bar's own premise ("Same weights, two containers") was false for the asset it was pointed at.** The publishing repo also carries an UNQUANTIZED `BF16` GGUF (3,471,497,440 B) beside `Q8_0`/`Q6_K`/`Q5_K`/`Q4_K_M`, which the spec had recorded as nonexistent; that retired the `NOT APPLICABLE` on gate 2. CPU gate `tests/vllm/models/test_qwen3_dflash_gguf.cpp` third case (asset-gated `VLLM_DFLASH_GGUF_BF16_MODEL` + `VLLM_DFLASH_ST_DIR`): `LoadQwen3DFlashFromGguf(BF16)` is **BYTE-IDENTICAL to `LoadQwen3DFlash(z-lab shards)` on all 58 tensors, 302/302 assertions, exit 0**, and FUNCTIONALLY RED against the `Q4_K_M` file (21/302 red, exactly the 21 quantized matmul tensors), so not a vacuous pass. Supporting: our `DequantGgufRowToBf16` is bit-equal to `gguf-py`'s `gguf.quants.dequantize` on the real `fc.weight` (Q4_K), `blk.0.attn_q.weight` (Q4_K) and `blk.2.ffn_down.weight` (Q6_K), zero differing bf16 values; the ladder's mean relative weight error is monotone and uniform with NO outlier tensor (BF16 0, Q8_0 5.6e-3, Q6_K 1.85e-2, Q5_K 3.85e-2, Q4_K_M 7.6e-2); the only numeric config delta is `rms_norm_eps` at 2.5e-9 relative. Also landed: an off-by-default `VT_SPEC_TRACE=1` per-block propose/accept trace in `GPUModelRunner::sample_tokens_with_rejection` (`src/vllm/v1/worker/gpu/runner.cpp`). **`GD10` 2026-07-29 CONFIRMED IT END TO END ON GB10 and closed gates 3 and 5.** Build proven production-configured three ways (configure log 0 `CUTLASS not found`; `cuobjdump -lelf` 40 cubins ALL `sm_121a` zero `sm_75` on both binaries; SACRED `test_qwen27_paged_engine` **235/235, exit 0**, 31.34s, 23.67 GiB). The **`BF16` GGUF draft reads EXACTLY 47/96**, the safetensors draft's own number, at 48 tokens on the discriminating prompt - reproduced 2 of 2 - plus 27/64 = 27/64 at 24 tokens and 15/144 = 15/144 on the second prompt, tokens IDENTICAL throughout, 17/17 exit 0 each time; the `Q4_K_M` arm reads 46/112 on the SAME binary in the SAME `flock` series. Restoring only the draft's numeric precision restores the count, so quantization is the whole cause and nothing structural survives. Bar (a) is consequently SPLIT rather than relaxed (`tests/parity/test_qwen27_dflash_spec_decode.cpp`): tokens stay EXACT unconditionally; accept counts are EXACT on a cross-FORMAT arm and BANDED (`abs(d_accepted) <= 2`, `abs(d_proposed) <= k*2`) on a cross-QUANTIZATION one, with the arm chosen by `IsQuantizedGgufDraft` reading the draft file's ggml types (`GgmlTraits().block_elems > 1`) rather than by a flag. The band is derived, not picked: measured `d_accepted` is 0, 0, -1, so the bound is that maximum plus one quantum; and `d_proposed = -k * d_accepted` EXACTLY once the token streams match (confirmed at -1 / +16), so the proposed bound follows. **Mutation-proved non-vacuous**: rebuilt at band 0 the `Q4_K_M` arm is 15/17 exit 1 while the `BF16` arm stays 17/17 exit 0 on the exact branch. **AXIS B BROADENED from ONE prompt to THREE**, strict form green on all: "The capital of France is" IDENTICAL 14/160 (15/15), "Write a Python function that reverses a string:" IDENTICAL 24/64 (15/15), "Photosynthesis is the process by which" IDENTICAL 15/128 (9/9), all exit 0, ~6m30-6m52 and ~81 GiB peak RSS each. The second prompt REFINES the recorded acceptance claim: the safetensors-target arm is ALSO 24/64 there with the two containers' DFlash-ON streams IDENTICAL, so the GGUF target's lower acceptance is prompt-dependent (their spec-OFF streams diverge at index 4 on the first prompt, index 16 on the second) and not a standing penalty; the cause remains `QUANT-GGUF-NVFP4` being dequant-only, with the shared head excluded by a byte comparison. Gates 1-5 and 7 MET; gate 6 (speed) `PENDING` BY DESIGN and not owed - a DFlash-ON throughput A/B between the two target containers is not a fair comparison until a native NVFP4 GGUF GEMM exists. Evidence: [docs/BENCHMARKS.md](../docs/BENCHMARKS.md) top section, [parity-ledger.md](parity-ledger.md#L845) | [specs/gguf-dflash-draft.md](specs/gguf-dflash-draft.md) | `DONE` | `c62f2fa3` | | `SPEC-REJECTION` | Rejection sampler. **I3 verify half LANDED (2026-07-24)**: per-request logits EXPANSION to `1 + k_i` rows (`StepInputs::cu_num_logits` / `num_draft_tokens_per_req` / expanded `logits_indices`) plus the GREEDY rejection sampler — accept a draft iff it equals the target argmax at its own position, emit the target argmax on the FIRST mismatch and stop, emit the bonus argmax when all `k_i` accept, `num_sampled = accepted + 1`, `num_rejected = k_i - accepted` (feeds I2's `num_computed_tokens` rollback and `InputBatch::num_accepted_tokens`). One additive vt op (`kGreedyRejectionSample`) with a CPU reference and a CUDA two-phase mirror of upstream's row-argmax + one-thread-per-request accept walk. DEFAULT-OFF and INERT: with no `SpeculativeConfig` no drafts are ever scheduled, `cu_num_logits` is `arange(num_reqs+1)`, `logits_indices` is the pre-change array and the runner never enters the rejection branch. STOCHASTIC/Gumbel, block verification, `apply_sampling_params` over the expanded batch, and the spec grammar bitmask stay DEFERRED (M-mtp-3). **I5b DRAFTER PREFILL INPUT-PREP LANDED (2026-07-24, `CLAIM-SPEC-MTP-I5B`)**: the draft-token input splice this row's I3 note deferred to I5 — `vllm::v1::prepare_prefill_inputs` + its `SpecPrefillInputs` output struct shift each request's `input_ids` left one within its query span, splice the just-sampled next token (`num_sampled>0 ? last_sampled[idx_mapping[r]] : next_prefill_tokens[...]`) into the freed slot, `query_len -= num_rejected`, and emit last-token index / query_start_loc / seq_lens + CG padding (mirror `speculator.py:469-588`, k=1 early-exit :236-238). A HOST routine in a NEW spec_decode-tree TU (no new CUDA kernel; mirrors the DEVICE-NEUTRAL `prepare_inputs`/`combine_sampled_and_draft_tokens` family — the DGX runner leaf ports the loop to the Triton kernel at I5d), unit-gated `test_prepare_prefill_inputs` 7 cases / 27 assertions RED-first, DEFAULT-OFF INERT (nothing calls it until I5d), additive by construction. Row stays `ACTIVE` — the e2e greedy token gate (M-mtp-1) is owed before `DONE` | T1 | `vllm/v1/worker/gpu/spec_decode/rejection_sampler.py:43,101-160`; `rejection_sampler_utils.py:524,564-585,628,828-841,846-849,863-1125`; `vllm/v1/worker/gpu/model_runner.py:866-898,1065-1077`; `vllm/v1/worker/gpu/input_batch.py:303-397,408-453`; **I5b** `vllm/v1/worker/gpu/spec_decode/autoregressive/speculator.py:469-588,236-238` | `include/vllm/v1/spec_decode/rejection_sampler.h`; `src/vllm/v1/spec_decode/rejection_sampler.cpp`; `include/vt/ops.h` (`kGreedyRejectionSample`, `vt::GreedyRejectionSample`); `src/vt/cpu/cpu_sample.cpp` (CPU reference); `src/vt/cuda/cuda_sample.cu` (`RejectionRowArgmaxKernel` + `GreedyRejectAcceptKernel`); `src/vt/ops.cpp`; `include/vllm/v1/worker/gpu/prepare_inputs.h` + `src/vllm/v1/worker/gpu/prepare_inputs.cpp` (the expansion); `include/vllm/v1/worker/gpu/runner.h` + `src/vllm/v1/worker/gpu/runner.cpp` (`step_num_logits`, `sample_tokens_with_rejection`); **I5b** `include/vllm/v1/worker/gpu/spec_decode/autoregressive/prepare_prefill_inputs.h` + `src/vllm/v1/worker/gpu/spec_decode/autoregressive/prepare_prefill_inputs.cpp` — anchor `include/vllm/v1/spec_decode/rejection_sampler.h:96` | `tests/vllm/v1/spec_decode/test_rejection_sampler.cpp`; `tests/vllm/v1/worker/test_prepare_inputs.cpp` (expansion + no-draft byte-identity); `tests/vt/test_cuda_ops.cpp` (CUDA==CPU bit-exact at vocab 248320); **I5b** `tests/vllm/v1/spec_decode/test_prepare_prefill_inputs.cpp` (7 cases / 27 assertions, RED-first) — anchor `tests/vllm/v1/spec_decode/test_rejection_sampler.cpp:128` | [mtp-spec-decode.md §2.4,§5](specs/mtp-spec-decode.md) | `ACTIVE` | `CLAIM-SPEC-REJECTION-I3`, `CLAIM-SPEC-MTP-I5B` | | `SPEC-GDN-SEGMENTS` | GDN speculative metadata and slot-snapshot rollback. **I4 LANDED (2026-07-24):** the spec/non-spec metadata split with decode→prefill reclassification (the #34845 case), the `T>1`/`IS_SPEC` GDN recurrence with per-timestep state snapshots, the conv sliding window advancing by the ACCEPTED count, and the k+1 state-slot allocation. DEFAULT-OFF and INERT (`num_spec==0` ⇒ `num_spec_decodes==0`, no shipped kernel branched — both spec kernels are NEW op ids). ROLLBACK PROVEN bit-exact: for every rejection point j the surviving SSM state and conv window are memcmp-identical to running only the accepted prefix through the shipped `vt::GdnDecode`/`CausalConv1dUpdate`, at the real 27B (Hv=48) and 35B (Hv=32) GDN dims on CPU and CUDA. MEASURED state cost: one f32 SSM slot = Hv·Dv·Dk·4B ⇒ 144 MiB/req (27B, 48 layers) / 60 MiB/req (35B, 30 layers) per extra slot; k=1 doubles the GDN SSM state. **I5a GDN LAYER ROUTING WIRED (2026-07-24, `CLAIM-SPEC-MTP-I5A`):** `GdnBlockPaged`'s `num_spec_decodes>0` branch now routes a PURE-spec batch through `vt::CausalConv1dSpecUpdate` + `vt::GdnSpecDecode` (mirror `qwen_gdn_linear_attn.py:1344-1357,1455-1475`), and the runner per-step upload (`StepDevInputs`/`BuildStepDevInputs` + the two decode-graph `Refresh` copies) now carries I4's six spec device tensors, gated by the extended `ValidateGdnAttentionMetadata` spec contract. DEFAULT-OFF INERT (`num_spec_decodes==0` ⇒ stub uploads + the identical non-spec branch). BIT-EXACT vs the I4 ops applied as a token-sequential decode chain, at the real 27B/35B GDN dims, via `GdnBlockPagedForTest` (`tests/vllm/models/test_qwen3_5_gdn_spec_routing.cpp`, CPU bit-exact + CUDA on-device); RED-first by a reverted stub (spec recurrence zeroed ⇒ 4/8 fail, maxΔ 1.3-1.6). MIXED spec+non-spec batch refused loudly — lands with I5d's runner loop. Row advances to `ACTIVE`: the M-mtp-1 e2e greedy token gate (verify/propose runner wiring) is owed before `DONE`, and `SPEC-MTP` STAYS `GATING` | T1 | `vllm/v1/attention/backends/gdn_attn.py:189-326,413-462`; `fla/ops/fused_sigmoid_gating.py:66-72,103-116,156-166`; `mamba/ops/causal_conv1d.py:818-1067,1181-1184`; `qwen_gdn_linear_attn.py:1329-1576`; `mamba_utils.py:213-234`; `mamba/abstract.py:55-59` | `include/vllm/v1/attention/backends/gdn_attn.h`; `src/vllm/v1/attention/backends/gdn_attn.cpp`; `include/vt/ops.h` (`kGdnSpecDecode`, `kCausalConv1dSpecUpdate`); `src/vt/ops.cpp`; `src/vt/cpu/cpu_ops.cpp`; `src/vt/cuda/cuda_gdn.cu`; `src/vllm/model_executor/models/qwen3_5_common.{h,cpp}` (`MakeQwen3_5KVCacheSpec`); **I5a:** `src/vllm/model_executor/models/qwen3_5.cpp` (`GdnBlockPaged` spec branch, `StepDevInputs`/`BuildStepDevInputs`, `ValidateGdnAttentionMetadata`), `src/vllm/model_executor/models/qwen3_5_internal.h` (`GdnBlockPagedForTest`) | `tests/vllm/v1/attention/test_gdn_metadata_builder.cpp` (20 cases / 483 assertions incl. the full upstream `GDN_BUILD_TEST_CASES` + default-off byte-identity); `tests/vt/test_ops_gdn.cpp` (reject-at-every-j rollback, CPU + CUDA, real dims); `tests/vllm/models/test_model_registry.cpp` (k+1 slot / widened-conv sizing + `num_spec==0` identity); **I5a** `tests/vllm/models/test_qwen3_5_gdn_spec_routing.cpp` (spec-routing bit-exact, RED-first) — anchor `tests/vllm/v1/attention/test_gdn_metadata_builder.cpp:83` | [mtp-spec-decode.md §3,§5](specs/mtp-spec-decode.md) | `ACTIVE` | `CLAIM-SPEC-GDN-I4`, `CLAIM-SPEC-MTP-I5A` | | `SPEC-DFLASH` | Block-diffusion drafter. **READINESS RE-ASSESSED 2026-07-25 (`CLAIM-SPEC-DFLASH-READINESS`, design-only, DONE) against the LANDED MTP machinery (`SPEC-MTP` I1..I7).** Verdict **GREEN, dispatch-ready, NO hardware/oracle/download blocker** (spec [§0](specs/dflash-spec-decode.md)). Refreshed reuse-vs-new map: DFlash gets FREE from landed MTP — the frozen spec-metadata ABI, the greedy rejection sampler (k-general, I3 tested k∈{1,3}), the GDN spec slot path + rollback + mixed spec/non-spec batch (`GdnBlockPagedMixedSpec`/`IndexSelect`/`IndexCopy`, general `num_spec`), the widened-cache-aware conv ops (I5e), the draft-KV layer pattern (`fa_draft`), the I5d/I7 runner verify/propose loop, and **`num_lookahead_tokens=k+1` ALREADY coded** (`speculative.h:91-108` `use_dflash()`); EXTENDS the single I5d-pre `hidden_tap` seam to multi-tap `[T,H×taps]`; builds NEW the `qwen3_dflash` drafter, the project's FIRST non-causal in-block attention primitive, context-KV precompute, `prepare_dflash_inputs`, and the uniform-1+k FULL CG. **k>1 verdict:** the landed rejection + GDN machinery is MECHANICALLY k-general (no `k==1` hardwiring) — DFlash's k=15 blocks need NO mechanism extension, only exercise/validation at scale (D4) + the k+1-slot memory measurement (~2.3 GiB/req 27B GDN state at block-16, the #1 risk, §5). **Checkpoint-fit:** both z-lab drafts EXIST on HF (27B 1.73 GB / 35B 368 MB bf16, DFlashDraftModel) and FIT the 119 GiB pool trivially (drafts NOT yet on dgx — D0 downloads ≤1.73 GB); the active dgx oracle `vllm-oracle-v0.25.0-stage` CONSTRUCTS DFlash (registry `DFlashDraftModel→qwen3_dflash`, speculator dir present) — soft D0 risk = confirm it SERVES DFlash+NVFP4 on sm_121 (non-causal backend; community `AEON-7/vllm-dflash` container proves the combination runs on GB10). W-plan D0-D6 in the spec. **D0+D1 LANDED 2026-07-26 (`CLAIM-DFLASH-D0D1`) on the ADVANCED pin `555967922`/vLLM 0.26.0.dev0 — `SPEC-DFLASH` → `ACTIVE`.** D0 UNBLOCKED (vllm#40898 resolved under `VLLM_USE_V2_MODEL_RUNNER=1`): the mixed-attn z-lab 27B draft CONSTRUCTS + the drafter is ALIVE (acceptance 2.21/8.80/4.75/4.57 > 1, `num_spec=16`, flashinfer-native fp8-KV, goldens committed); gate FORM measured STRICT MODE-MATCHED (vLLM-ON run-deterministic K>=3 but != vLLM-OFF — the k=16 block verify diverges at bf16 near-ties, so NOT the MTP three-way identity). D1 `DF-AUX-TAPS` DONE: `Qwen3_5AuxTaps` + `ModelForwardInput::aux_tap` route to `Qwen3_5{,Dense}Model::ForwardDeviceMultiTap` capturing `(hidden+res)` at `target_layer_ids` into `[T,H×taps]` (eagle3 `_maybe_add_hidden_state`, aux key L+1); config-gated byte-identical off. Unit gate 598 assertions (independent truncated-model reference, RED-first reversed-concat 384 fail); CUDA 697/697 + compute-sanitizer 0; INERTNESS PROVEN — 27B MTP e2e 9/9 + 27B text SACRED 235/235 byte-identical on the new oracle. **D2 `DF-DRAFT-MODEL` CODE LANDED + CPU-GATED 2026-07-26 (`CLAIM-DFLASH-D2`, kernel row `KERNEL-ATTN-DFLASH-BLOCK`):** the `qwen3_dflash` draft model (plain 5-layer Qwen3-dense reusing `dense_attn_block.h` ops), the project's FIRST non-causal / bidirectional attention primitive `vt::DFlashBlockAttention` (a SEPARATE op — causal `kAttention`/`kPagedAttention` byte-identical), the fc aux-combine, mask-embed, per-layer SWA/full resolution, and the z-lab loader. CPU gate GREEN (op 12/12 incl. RED non-causal; model forward 95/95 incl. RED full-layer-causal-flip + block isolation + fc RED); existing causal `test_ops_attention` 9/9 + `test_qwen3_forward` 1028 UNCHANGED. **D2 GPU PROMOTION GREEN on dgx (`CLAIM-DFLASH-D2`):** CUDA `-Werror` clean, CUDA==CPU 198412/198412 + compute-sanitizer 0, draft-forward parity vs the REAL vLLM draft (fc rel-L2 0.46%, hidden ≤1.3%, 11 STRICT + 5 near-tie ids), 27B SACRED 235/235 + MTP 9/9 byte-identical — **D2 DONE.** **D3 `DF-DRAFT-KV-PREP` DONE 2026-07-26 (`CLAIM-DFLASH-D3`):** `PrecomputeContextKV` + `PrepareDflashInputs` + `ForwardBlockLogitsWithContext` (reuse the UNCHANGED D2 kernel via [context;block]); GPU numeric-parity `test_qwen3_dflash_kvprep_parity` 61/61 (prepare INTEGER bit-exact vs vLLM's Triton kernel, context-KV K/V rel-L2 0.31%/0.26%, 13 STRICT + 3 near-tie = 16/16), CPU 114/114 RED-proven, inertness 235/235 + 9/9 + D2 37/37 byte-identical. **D4 `DF-ENGINE-INTEGRATION` propose brick + `dflash` config-select CODE LANDED + CPU-GATED 2026-07-26 (`CLAIM-DFLASH-D4D5`):** `DflashProposeBlock`/`SampleDflashBlockDrafts` (the non-autoregressive whole-block propose composing D3 `ForwardBlockLogitsWithContext` + greedy per-mask argmax, anchor not sampled, `dflash/speculator.py:300-413`) + `ParseSpeculativeConfigJson`/`ResolveDflash` accept `method:"dflash"`. CPU gate `test_dflash_propose` 5/19 GREEN (RED-first anchor-read fails 4/5; brick composes forward+sampler; empty-ctx degenerates to D2; config lookahead k+1). Additive + config-gated ⇒ MTP + non-spec byte-identical BY CONSTRUCTION (`git diff --stat` = new speculator TU + config accept-list + CMake + test, NO runner/model/loader/scheduler edit). **D5 `DF-ENGINE-INTEGRATION` runner-loop LANDED + e2e RUNS on dgx 2026-07-26 (`CLAIM-DFLASH-D5`):** full verify/propose loop wired — loader loads the SEPARATE z-lab draft (`LoadDflashDraft`, host bf16 + target-SHARED bf16 embed/lm_head) via a `--speculative-config` `model` key + `ResolveSpecConfig` dflash branch + `runner.set_dflash_draft`; the verify forward captures the D1 multi-tap (`aux_tap`→`ForwardDeviceMultiTap`) instead of the MTP single tap; `propose_drafts_dflash` ACCUMULATES the per-request combined-feature context (`CombineAuxFeatures(aux_tap)`) across steps and honors the `num_rejected` rollback by appending only the `(T_req−num_rejected)` accepted-prefix features, then runs `DflashProposeBlock` (k=16 GDN-spec exercised first time). **e2e (`test_qwen27_dflash_spec_decode`, 4 prompts×32 tok, our-DFlash-ON vs the committed vLLM-DFlash-ON golden): 2/4 STRICT token-exact (fibonacci, three-laws) + acceptance ~ vLLM on ALL 4 (accepted 19/39/29/25 vs golden 17/39/30/25, deltas +2/0/−1/0 — the MANDATORY dead-drafter-trap condition MET).** The 2 divergences (France tok11 `2972`↔`11751`, 17*23 tok12 `567`↔`488`) are SINGLE bf16 near-tie flips (17*23 RE-CONVERGES after one token = proven near-tie; France cascades from one flip) — the ratified near-tie ROOT the D0 gate-form anticipated, rooted in the D3-documented inline bf16 context-KV recompute envelope (~0.3-1.3% rel-L2), NOT a wiring bug (proven by the 2 exact prompts + near-exact acceptance + a non-trivial shared prefix). Inertness GREEN on this build: SACRED `test_qwen27_paged_engine` 235/235 + MTP `test_qwen27_spec_decode` 9/9 byte-identical; CUDA `-Werror` clean; NO new CUDA kernel (host orchestration reusing D1/D2/D3-sanitized ops). **NOT a clean strict-4/4 pass; STRICT 4/4 token-identity + the speed A/B = D6 (the persistent paged draft-KV bit-matching vLLM's fused context-KV projections + the uniform-1+k FULL CG).** Row STAYS `ACTIVE` (correctness at the ratified near-tie envelope; D6 remains) **D6 2026-07-27 (`CLAIM-DFLASH-D6`) — c1 SPEED A/B DONE + STRICT-irreducibility RCA + CG feasibility (records-only, NO source code):** (1) **c1 speed A/B** (`examples/vllm-bench` at `361189a7`, 8 prose+code prompts×256 tok greedy c1, 2 reps): our DFlash-ON = **2.50x TPOT (40.4 vs 101.2 ms) / 2.48x output-tput (24.4 vs 9.86 tok/s)** over our OFF, acceptance 0.22 (3.56/16), rep-stable <1.5%; `benchmark_binding=true`. vs vLLM-DFlash-ON graphed (same workload): vLLM-DFlash-ON graphed = 28.5 tok/s / 35.1 ms TPOT / acceptance_len 4.30 (same 8 prompts, `VLLM_USE_V2_MODEL_RUNNER=1`, mm-off, gpu_util 0.30), so OURS IS ~14% BELOW vLLM-DFlash-ON on output throughput (24.4 vs 28.5 tok/s) - both ~on-par at spec-OFF (9.86 vs 9.83 tok/s), but vLLM extracts a larger DFlash speedup (2.90x vs our 2.47x) because its draft step is fully device-resident + CUDA-graphed (ours host-orchestrates 13 downloads/step) + slightly higher acceptance (~4.3 vs ~3.6 draft tokens/step). The DONE speed bar (ours >= vLLM) is NOT met; closing it = the device-resident draft rewrite + FULL CG (D6 part 2). (2) **STRICT-4/4 proven bf16-IRREDUCIBLE** — the draft KV cache is bf16 not fp8 (`torch_utils.py:398` `auto`→model dtype; the D0 "fp8-KV" was the backend name, not the KV storage dtype), the D3 golden already compares pre-storage bf16 (residual K 0.31%/V 0.26% = sub-ULP kernel noise), and a fused multi-layer KV GEMM is per-element invariant to our per-layer GEMMs ⇒ bit-exact needs vLLM's exact kernels ⇒ the ratified near-tie gate is the FINAL correctness form (no fused-KV code landed). (3) **FULL CG BLOCKED** on a device-resident draft-path rewrite (the D5 path does 13 device→host downloads/step + host `[context;block]` interleaving) — the remaining throughput-parity increment (the perf form of persistent-paged-KV + the graph). Inertness by construction (the gated binary is the D5 binary; SACRED 235/235 + MTP 9/9 stand). Evidence tool `scripts/spec/vllm_dflash_timing.py`. **D7 2026-07-27 (`CLAIM-DFLASH-D7`) — within-step draft forward made DEVICE-RESIDENT (source-owning): `PrecomputeContextKVDevice` keeps per-layer K/V on device; `ForwardBlockLogitsWithContext` builds [context;block] with `vt::IndexCopy`/`IndexSelect` (removes ~30 D→H `Download`s/step). BIT-IDENTICAL (identity bf16↔f32 round-trips replaced) — e2e `test_qwen27_dflash_spec_decode` 27/27 SAME tokens (2/4 STRICT + 2/4 near-tie, acceptance 19/39/29/25), SACRED 235/235 + MTP 9/9, CUDA `-Werror` clean, compute-sanitizer 0 (198412). But the direct old-vs-new A/B = +2.0% output-tput (IN-NOISE) ⇒ D6's "downloads = the ~14% gap" REFUTED by measurement; ours 19.68 tok/s STILL ~33% BELOW vLLM-DFlash-ON 29.2 tok/s (reconstructed 8-prompt set, more prose-heavy); OFF parity our 9.97 ≥ vLLM 9.66. Residual re-attributed: acceptance (ours 2.49 vs vLLM ~3.13 accepted draft-tok/step, bf16-irreducible) + per-step context-KV RECOMPUTE (O(context²), needs the cross-step persistent paged draft-KV store) + eager-vs-graphed. SPEED BAR NOT met; SPEC-DFLASH stays `ACTIVE`; next = persistent paged draft-KV store → then FULL CG. **D9 2026-07-27 (`CLAIM-DFLASH-D9`) — PERSISTENT PAGED DRAFT-KV LANDED (bit-identical, +22.7% throughput, 0.69×→0.917×); D8 acceptance-ceiling REFUTED; residual = FULL CG ONLY:** `qwen3_dflash.cpp` `AppendContextKVHost` (project ONLY newly-accepted rows → per-layer bf16 K/V, append to `PrecomputedContextKV`) + `ForwardBlockLogitsWithPrecomputedKV` (upload the persistent store, NO re-projection) share the core `ForwardWithCtxKVDev` with the old recompute; `runner.cpp::propose_drafts_dflash` swaps the O(context²) per-step recompute (`dflash_ctx_feats_`) for an append-only per-request `dflash_kv_store_` (rollback=don't-append). NO new CUDA kernel; config-gated. BIT-IDENTICAL: CPU `test_dflash_propose` two new D9 cases = exact float equality vs full recompute; GPU e2e `test_qwen27_dflash_spec_decode` **27/27 SAME tokens** (acceptance 19/39/29/25, same divergences France@11/17×23@12); SACRED 235/235 + MTP 9/9 byte-identical; CUDA `-Werror` clean. **A/B (c1, 8 prose+code×256 tok input-len 512, 2 reps <0.1%, `benchmark_binding=true`):** ours-ON **25.75 tok/s** (was D8 20.99, +22.7%) / 38.40 ms TPOT / acc **3.68/step** vs vLLM-ON graphed **28.09** / 35.60 / acc 3.31 = **0.917×** (~8% below, was 0.69×). **Part 1 same-trajectory:** on the 2 token-identical-trajectory prompts ours per-step acceptance == vLLM's EXACTLY (fibonacci 7.80/7.80, three-laws 3.571/3.571, ratio 1.00) AND on the A/B ours acceptance (3.68) is HIGHER than vLLM's (3.31) ⇒ D8's 0.80–0.85× "bf16 acceptance ceiling" is a trajectory-divergence CONFOUND, REFUTED. Residual (~8%) = eager-vs-graphed ONLY (ours ON/OFF 2.60× vs vLLM 2.91×, OFF at parity, recompute eliminated, acceptance higher) — NOT an irreducible ceiling; the FULL uniform-(1+k) CG (device paged-KV store + paged attn, new-CUDA multi-file) is the SOLE un-landed increment. SPEC-DFLASH stays `ACTIVE` (speed not yet ≥ vLLM; residual isolated to FULL CG). **D12 2026-07-27 (`CLAIM-DFLASH-D12`) — A-wire + Part B LANDED + GPU-gated; Part C (capture) remaining; 0.917×:** A-wire makes the D11 Part-A device store the PRODUCTION path (`runner.{h,cpp}` `dflash_kv_store_`→`shared_ptr`, `MakeDeviceKVStore`/`AppendContextKVDevice`/`ForwardBlockLogitsWithDeviceKV`; GPU-gated e2e `test_qwen27_dflash_spec_decode` 27/27 all-exact acceptance 19/39/29/25 + SACRED 235/235 + MTP 9/9 byte-identical, `-Werror` clean). Part B adds `vt::DFlashPagedBlockAttention` (`OpId::kDFlashPagedBlockAttention`), the capture-safe paged kernel with EVERY metadata input a persistent DEVICE tensor and NO function-local host `cu_seqlens` upload (fixes the `cuda_ops.cu:1277-1280` capture-UAF class), gated CPU==CUDA + cross-check vs materialized `DFlashBlockAttention` `test_ops_dflash_paged_block_attn` 795648/795648 + compute-sanitizer 0. Speed 0.917× (A-wire eager + Part B not yet wired into the forward); `benchmark_binding=false`. Part C (static-shape capture + device mask-scatter + `BeginCapture`/replay + the ≥vLLM c1 A/B) is the SOLE remaining piece; if ours-ON-graphed ≥ vLLM-ON → SPEC-DFLASH DONE. Stays `ACTIVE`. **D13 2026-07-27 (`CLAIM-DFLASH-D13`) — Part C LANDED + GPU-GATED; capture-correctness PROVEN; c1 throughput NEAR-PARITY (ours 0.978x, ~2% below vLLM); gap CLOSED 0.917x→0.978x; STAYS `ACTIVE` (≥vLLM bar not yet met):** single-file additive change (`qwen3_dflash.cpp` +368/-58). (C.1) `DflashDeviceKVStore` → fixed-capacity PAGED cache (per-layer pool `[max_pages,16,Hkv,Dh]` + identity `block_table` + `seq_lens`; append = `vt::IndexCopy` scatter at slot==abs-pos, bit-identical to the D9/D11 store). (C.2) `ForwardPagedBody` runs the (1+k) block through the D12 `vt::DFlashPagedBlockAttention` reading the paged store (no `[context;block]` materialization, no function-local host uploads); runner P==1 propose routes through it, P>1 bit-identical materialized fallback. (C.3) per-request CUDA GRAPH over the paged draft step (warm-in-step repopulates the shared pool free-list right before `BeginCapture` — the fix for a `cudaMalloc`-in-capture `Get` miss from the intervening 27B target forward — then `BeginCapture → ForwardPagedBody → EndCaptureGraph`, replay with growing context entering only via in-place `seq_lens`). **Capture-correctness (MANDATORY): `test_qwen27_dflash_spec_decode` 27/27 with the graph (VT_DFLASH_GRAPH=1) BIT-IDENTICAL to eager (=0)** — same divergence tokens (France@11 got[…2972…], 17×23@12 got[…567…]), same acceptance 19/39/29/25 as D5/D7/D9/D12; graph ENGAGED (5 captures C=2048/5/4/15/6, 32+ replays); the token-diff is the capture-safety proof ([[cudagraph-capture-bakes-stack-addresses]]). **c1 A/B (one flock series, cold rep discarded, 8 prompts×256 tok):** our OFF 10.24 / our ON eager-paged 28.65 (28.69,28.61) / **our ON GRAPHED 28.70 (28.70,28.70), TPOT 34.40** / vLLM-ON graphed steady-state 29.35 (tight 3-rep 29.33/29.37/29.33, TPOT 34.07, acc_len 4.44); D9's 28.09 was a colder cross-session outlier — **NEAR-PARITY: ours 0.978× (~2% below) on the rigorous same-session band** (across sessions ours 28.70 falls inside vLLM's observed 28.09–29.37 range). ON/OFF 2.80× (vLLM ~2.98×), our OFF ≥ vLLM OFF. Per the acceptance rule ("below on any axis = an open gap; near-parity is NOT met"), the ≥vLLM bar is NOT met; STAYS `ACTIVE`. Residual (data-grounded): NOT acceptance (ours realized ~3.68 accepted draft-tok/step > vLLM's 3.44) and NOT launch/graph (both graphed, CG neutral) — per-step COMPUTE (~2% slower target-step); next lever = nsys both draft steps (`--cuda-graph-trace=node`), no premature ceiling. **ATTRIBUTION (supersedes D9):** the CUDA graph is perf-NEUTRAL (+0.3%); the ACTUAL lever was the paged context read (C.1/C.2) removing the D9/D12 per-layer `[context;block]` `IndexCopy` materialization of the whole growing context (25.75 D9 → 28.65 eager-paged, +11%) — the roadmap's "the full CG closes the gap" premise is corrected by measurement. Inertness VERIFIED on the capture binary: SACRED 235/235 + MTP 9/9 byte-identical, CUDA `-Werror` clean, no new kernel (D12 paged kernel already memcheck-0 795648), `check-device-leakage` not increased (paged path REMOVES the materialized-buffer allocs + host uploads). `benchmark_binding=true`. Correctness-complete (ratified near-tie); throughput NEAR-PARITY (0.978×, ~2% residual) ⇒ STAYS `ACTIVE` (the capture-correctness gate is MET; the ≥vLLM speed bar is the sole remaining item, a ~2% per-step-compute residual for an nsys). Anchors: `src/vllm/model_executor/models/qwen3_dflash.cpp` (`DflashDeviceKVStore` paged store, `ForwardPagedBody`, the per-request graph in `ForwardBlockLogitsWithDeviceKV`). **D14 2026-07-27 (`CLAIM-DFLASH-D14`) — SPEED GATE MET → SPEC-DFLASH `DONE`:** an nsys (`--cuda-graph-trace=node`) of the graphed spec-on step attributed the D13 ~2% residual to the from-scratch `DFlashPagedBlockAttentionKernel` draft attention (242.9 ms = 1.8% of GPU time, median ~460 us/call over context C~500-640, vs vLLM's fused flash draft-attn ~0.15%; BOTH engines run identical `cutlass_80_wmma` for the draft bf16 GEMMs, so the GEMMs were NOT the gap). Ported it to a WARP-scoped online-softmax variant `DFlashPagedBlockAttentionWarpKernel` (mirrors the shipped `AttentionWarpKernel`: one warp per (block-query,head), `__shfl_xor` butterfly reduction, register accumulator, NO `__syncthreads` storm; SAME paged/block combined-index read + causal/SWA mask + GQA; default ON, `VT_DFLASH_ATTN_BLOCK=1` keeps the bit-identical D12/D13 block kernel for A/B). Draft attn 242.9 → 77.9 ms (3.1x); our-ON c1 28.60 → 29.32 tok/s (+2.5%). **FINAL same-session 3-rep A/B (8 prompts×256 tok, cold leg discarded): our-ON graphed 29.42/29.27/29.32 (med 29.32) vs vLLM-ON graphed 29.240/29.247/29.233 (med 29.240) — our WORST rep (29.27) > vLLM's BEST (29.247), NON-OVERLAPPING bands, 1.003× ⇒ the ≥vLLM speed gate is MET.** Correctness UNCHANGED (output is exact by spec-decode construction — the target verify is untouched, only which draft proposals are accepted can shift): e2e `test_qwen27_dflash_spec_decode` 27/27 with graph==eager BIT-IDENTICAL, acceptance 19/39/29/25 unchanged (draft accepted 1629 identical warp-vs-block across the whole A/B set), 2/4 STRICT (France@11, 17×23@12 unchanged); CUDA==CPU `test_ops_dflash_paged_block_attn` 795648/795648 (warp within the f32 1e-4 / bf16 3e-2 envelope) + compute-sanitizer 0. Inertness SACRED 235/235 + MTP 9/9 byte-identical; CUDA `-Werror` clean; `check-device-leakage` not increased. `benchmark_binding=true`. Block-diffusion drafting is now correctness-complete (ratified near-tie) AND at/above vLLM throughput — this was the roadmap's FINAL open speed item. Anchors: `src/vt/cuda/cuda_ops.cu` (`DFlashPagedBlockAttentionWarpKernel` + `UseDflashAttnBlockKernel`; the D12 block kernel retained as the `VT_DFLASH_ATTN_BLOCK=1` reference). | T1 | `vllm/v1/worker/gpu/spec_decode/dflash/speculator.py`; `vllm/model_executor/models/qwen3_dflash.py`; `vllm/model_executor/models/interfaces.py:1382` (aux value); `eagle3_utils.py:41-56` (+1 shift) | `include/vllm/model_executor/models/qwen3_5.h` (`Qwen3_5AuxTaps`, `ForwardDeviceMultiTap`); `qwen3_5_dense.h`; `model_registry.h` (`aux_tap`); `src/vllm/model_executor/models/qwen3_5.cpp` (`MaybeCaptureAuxTap`/`ValidateAuxTapLayerIds`/`ForwardDeviceMultiTap`); `qwen3_5_moe.cpp`+`qwen3_5_dense.cpp` (routing); D2/D3 `include/vllm/model_executor/models/qwen3_dflash.h` + `src/vllm/model_executor/models/qwen3_dflash{,_weights}.cpp`; D4 `include/vllm/v1/worker/gpu/spec_decode/dflash/speculator.h` + `src/vllm/v1/worker/gpu/spec_decode/dflash/speculator.cpp` (`DflashProposeBlock`/`SampleDflashBlockDrafts`); D5 `src/vllm/entrypoints/model_loader.cpp` (`LoadDflashDraft`/`DflashDraft`) + `include/vllm/entrypoints/model_loader.h`; D5 `src/vllm/v1/worker/gpu/runner.cpp` (`set_dflash_draft`/`propose_drafts_dflash`/aux-tap capture) + `include/vllm/v1/worker/gpu/runner.h`; `src/vllm/config/speculative.cpp` + `include/vllm/config/speculative.h` (`ResolveDflash` + `dflash`/`model` parse); D14 warp kernel [cuda_ops.cu](../src/vt/cuda/cuda_ops.cu#L1433) | `tests/vllm/models/test_qwen27_paged_forward.cpp` (multi-tap 598); `tests/vt/test_ops_dflash_block_attn.cpp`; `tests/vllm/models/test_qwen3_dflash_forward.cpp`; `tests/vllm/v1/spec_decode/test_dflash_kvprep.cpp`; `tests/parity/test_qwen3_dflash_{draft,kvprep}_parity.cpp`; D4 `tests/vllm/v1/spec_decode/test_dflash_propose.cpp` (5/19, RED-first); D5 `tests/parity/test_qwen27_dflash_spec_decode.cpp` (e2e 27/27, 2/4 strict + acceptance~vLLM); `scripts/spec/d{0,2,3}_dflash_*.py`; `tests/parity/goldens/dflash_27b{,_draft,_kvprep}/`; D6 `scripts/spec/vllm_dflash_timing.py` (vLLM-DFlash c1 timing); D7 device-resident `src/vllm/model_executor/models/qwen3_dflash.cpp` (`PrecomputeContextKVDevice` + `ForwardBlockLogitsWithContext` via `vt::IndexCopy`/`IndexSelect`); D9 persistent paged draft-KV `qwen3_dflash.{h,cpp}` (`AppendContextKVHost`/`ForwardBlockLogitsWithPrecomputedKV`/`ForwardWithCtxKVDev`/`PrecomputedContextKV`) + `runner.{h,cpp}` (`dflash_kv_store_`/`propose_drafts_dflash`) + `tests/vllm/v1/spec_decode/test_dflash_propose.cpp` (2 D9 bit-identity cases); D12 A-wire `runner.{h,cpp}` (device store as production path) + D12 Part B `include/vt/ops.h`/`src/vt/ops.cpp`/`src/vt/cpu/cpu_ops.cpp`/`src/vt/cuda/cuda_ops.cu` (`kDFlashPagedBlockAttention`) + `tests/vt/test_ops_dflash_paged_block_attn.cpp` (CPU==CUDA + cross-check, 795648/795648 + sanitizer-0); D13 `src/vllm/model_executor/models/qwen3_dflash.cpp` (fixed-capacity paged `DflashDeviceKVStore` + `ForwardPagedBody` + the per-request draft-step CUDA graph in `ForwardBlockLogitsWithDeviceKV`); D14 [test_ops_dflash_paged_block_attn](../tests/vt/test_ops_dflash_paged_block_attn.cpp#L79) + [ledger](parity-ledger.md#L738) | [dflash-spec-decode.md](specs/dflash-spec-decode.md) | `DONE` | `489a7544` | diff --git a/.agents/specs/rocm-quant-gather.md b/.agents/specs/rocm-quant-gather.md index 656926934..17605d678 100644 --- a/.agents/specs/rocm-quant-gather.md +++ b/.agents/specs/rocm-quant-gather.md @@ -13,15 +13,19 @@ Spec base: `6db4bef906859e864c82523c01107473f7dcca29`. ## Now -`PENDING`. This commit defines the ROCm gather change before implementation. -This row uses one pull request, following the repository default. -The implementation requires a fresh implementer, fresh mutation review, and an -operator rerun. No product, GPU, oracle-runtime, or performance result is claimed. +`ACTIVE`. The native HIP gather and public compressed-embedding path are implemented. +The operator's final GPU run passed all 15 CTests and the required two-device case. +The public gate reaches all 19 formats. All 76 operation outputs +meet the pinned oracle gates, and matching native/primary traces pass. +The row uses one pull request and retains the reviewed full-attention prerequisite. -The primary plugin's embedding method covers 16 of the 19 admitted local -formats. Its gfx1100 runtime and upstream fixtures remain `PENDING`. -The fork's IQ1_XXXS graph and bounded model qualification remain `PENDING`. -Neither local scalar agreement nor an imported golden satisfies those gates. +The original 32 primary fixtures await download authority. The primary renderer refuses the exact Q4_0 fixture; both secondary bounded +models abort on their first decode. Their execution and cache-layout qualification +remain pending. Local preflight completes with its argument-dependent skips recorded. +Fresh mutation review and the operator's reviewed-head rerun remain required. The row is not ready to land or become `DONE`. + +The [row evidence](../../docs/bench-evidence/rocm-quant-gather/README.md) +records executing pins, exact recipes, stage hashes, rejected attempts, and limits. ## Scope @@ -56,7 +60,7 @@ Update this inventory and `Now` together when this child changes state. | ID | Upstream source | Local anchor | Tests and evidence | Spec | State | Owner | Issue | |---|---|---|---|---|---|---|---| -| `BACKEND-ROCM-QUANT-GATHER` | Plugin `_apply_gguf_embedding`, pinned codec sources | `vt::Embedding`, `KeepQuantGatherDType`, new ROCm gather | Focused and public gates in this spec | This file | `PENDING` | `row/BACKEND-ROCM-QUANT-GATHER` helper, operator verifies | #3093 | +| `BACKEND-ROCM-QUANT-GATHER` | Plugin `_apply_gguf_embedding`, pinned codec sources | `vt::Embedding`, `KeepQuantGatherDType`, new ROCm gather | Focused and public gates in this spec | This file | `ACTIVE` | `row/BACKEND-ROCM-QUANT-GATHER` helper, operator verifies | #3093 | ### Complete decoder set @@ -551,6 +555,10 @@ Require the focused test to fail for the intended reason after each mutation. 7. Replace bf16 rounding with truncation. 8. Remove the bounds-error record or its reporting. 9. Remove grid-stride continuation. +10. Remove the reader's Q8_K trait, then independently mis-size that trait. +11. Remove the embedding materializer role and independently weaken its default dot guard. +12. Permit a matrix repack for the embedding role. +13. Remove the queue-device binding before the error allocation and launch. The first three mutations must fail the public production test. The remaining mutations must fail their named focused cases. @@ -562,22 +570,30 @@ The operator reruns the final focused and full gates itself after a PASS review. Report exactly one state per applicable obligation: satisfied, narrowly waived, pending a named authority or resource, or failing. -At specification, the result inventory is: +The current result inventory is: | Obligation | Result | Authority or remaining evidence | |---|---|---| -| Committed spec before implementation | Satisfied by this commit | Implementation has not started | -| All 19 native decoder and error contracts | PENDING | Fresh implementer, gfx1100 mutex | -| All 19 public production paths | PENDING | Public API fixture and native run | -| Pinned-oracle model token equality | PENDING | Primary 16, stock MXFP4, fork IQ1_XXXS, 3 identical repeats | -| Primary plugin operation and bounded-model execution | PENDING | Exact plugin build and gfx1100 run | -| Original primary fixture coverage | PENDING | Cached files or approved 289,655,872-byte download | -| Stock secondary execution | PENDING | Exact stock build, decoder and bounded model | -| IQ1_XXXS fork graph and bounded model | PENDING | Exact fork executable and real model graph | -| Memory format and identical-tool traces | PENDING | Runtime capture and available profiler | -| CPU and ROCm regressions, full preflight | PENDING | Implementation head | -| Fresh mutation review | PENDING | Independent reviewer | -| Operator verification | PENDING | Operator rerun on reviewed head | +| Committed spec before implementation | Satisfied | Original spec plus materializer and reader amendments precede product edits | +| All 19 native decoder and error contracts | Satisfied on sealed native v4 | Nine cases and 11,784 assertions; required two-device case passes 16 assertions | +| All 19 public production paths | Satisfied on sealed native v4 | 228 completions, 2,850 assertions; all 456 capture files equal the trace run byte-for-byte | +| Pinned-oracle model token equality | PENDING | Primary 16, stock MXFP4 and fork IQ1_XXXS must emit matching tokens | +| Primary plugin operation execution | Satisfied | Exact native plugin, 64 synthetic outputs; original tolerances unchanged | +| Primary bounded-model execution | PENDING | Exact Q4_0 fixture reaches pinned renderer, which refuses Qwen3_5TextConfig before tokens | +| Original primary fixture coverage | PENDING | Developer authority for the 289,655,872-byte download; no fixtures downloaded | +| Stock secondary operation execution | Satisfied | Q8_K direct pinned decoder and MXFP4 real GET_ROWS, including applicable stock geometry | +| Stock secondary bounded model | PENDING | First decode aborts; upstream context padding also differs from required cache geometry | +| IQ1_XXXS fork operation execution | Satisfied | Real pinned fork GET_ROWS; exact outputs and applicable stock geometry | +| IQ1_XXXS fork bounded model | PENDING | First decode aborts; requested 64 cells resolve to 256 | +| Operation memory format and identical-tool traces | Satisfied | Identical rocprofv3 1.3.5; native allocation events and separate primary tensor telemetry | +| Native model memory format | Satisfied | 228 public engines: 912 BF16 KV reads, 912 two-byte writes, one matching 16,384-byte allocation per engine; allocation role attributed through source | +| Matched oracle model memory | PENDING | Primary renderer refusal and secondary cache padding/model aborts | +| CPU regressions | Satisfied | Five CPU targets passed; accelerator-only targets reported three explicit skips | +| ROCm regressions | Satisfied | Clean HIP build; all 15 CTests executed and passed in sealed native v4 | +| Applicable local preflight | Satisfied with explicit skips | Full staged driver exits 0 with no failures and five argument-dependent skips; CPU ISA passes separately; final commit classification accompanies the handoff | +| Combined CUDA/HIP expectation execution | PENDING | No combined build was available for this qualification | +| Fresh mutation review | PENDING | Independent reviewer on immutable implementation head | +| Operator verification | PENDING | Operator rerun after final scoped review | Performance is not an acceptance claim in this correctness row. No benchmark ID, throughput ratio, latency claim, or performance ceiling changes. @@ -605,10 +621,18 @@ It reported no failures and five argument-dependent skips. These were `check-arm-isa-build.py`, `check-cpu-isa-build.py`, `check-cuda-fat-gencode.py`, `check-pr-size.py`, and `check-triton-aot-multiarch.py`. This result is not an all-green preflight. The spec changes no build or product file. -The staged preflight and explicit change-size check remain required before commit. +The implementation's final staged preflight exits 0 with no failures and the same five argument-dependent skips. +The explicit CPU ISA check passes. Final commit classification accompanies the immutable handoff. Implementation evidence must add exact source and binary revisions, build commands, model and fixture hashes, environment, mutex identity, contention, and exit codes. Keep oracle outputs and restoration hashes in this row's evidence directory. + +Implementation captures, matching operation traces, oracle output archives, and +remaining qualification failures are retained in the linked row evidence. +The first public red was invalidated by the separate full-attention state defect; +only the subsequent zero-provider-selection result is the intended implementation red. +Q8_K reader and materializer refusals were then captured in their executing order. +The queue-device test captured invalid stream use before the binding repair. Do not commit downloaded sample GGUF files. ## Risks and stop conditions diff --git a/CMakeLists.txt b/CMakeLists.txt index d91f9a495..c206dcae5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1717,6 +1717,7 @@ if(VLLM_CPP_HIP) src/vt/rocm/rocm_backend.hip src/vt/rocm/rocm_rmsnorm.hip src/vt/rocm/rocm_embedding.hip + src/vt/rocm/rocm_embedding_quant.hip src/vt/rocm/rocm_dense_basic.hip src/vt/rocm/rocm_matmul_hipblaslt.hip src/vt/rocm/rocm_paged_attn.hip @@ -1745,6 +1746,7 @@ if(VLLM_CPP_HIP) src/vt/rocm/rocm_backend.hip src/vt/rocm/rocm_rmsnorm.hip src/vt/rocm/rocm_embedding.hip + src/vt/rocm/rocm_embedding_quant.hip src/vt/rocm/rocm_dense_basic.hip src/vt/rocm/rocm_matmul_hipblaslt.hip src/vt/rocm/rocm_paged_attn.hip diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 18a2c3ef4..88f3d3022 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -109,7 +109,7 @@ by #2794 (goldens predate the pin) and #2817 (the advance). | NVFP4 shared-expert `down_proj` kept bf16 (no f32 round-trip) | ✅ `VT_SHARED_DOWN_BF16` default-ON; bit-identical (both consumers widen bf16 in-kernel and re-round on store), SACRED 315/315 + 235/235 on BOTH arms with unchanged assertion counts; +2.05% c8 / +0.79% c4 on 35B-A3B | ☐ | ☐ | ☐ | | NVFP4 `lm_head` kept packed (no dequant at load) | ✅ `VT_LMHEAD_FP4` default-ON, #213; CUDA-gated on `nvidia`@`0893e160` (continuations byte-identical packed vs dequant, 235/235; RSS -1.70 GiB on CUDA, owed a re-measure; a no-fp4-GEMM backend keeps one bf16 operand too) | ✅ | ☐ | ☐ | | GGUF k-quants and i-quants | ✅ (CPU grouped keep-quant MoE bf16 regression in `b4f5610a` fixed 2026-08-06). **CPU quant compute is ISA-tiered:** Arm has i8mm + repack; x86_64 portable-only, MEASURED open on every axis (CIQ `G5`, #433). **IQ4_NL (20) and Q5_0 (6)** added for `qwen4exp` (#1989), decode bit-exact vs llama.cpp `b10451`; they are the ragged-K landing spots of upstream's own `tensor_type_fallback` (`IQ4_XS -> IQ4_NL`, `Q4_K -> Q5_0`, `llama-quant.cpp:374`). **IQ2_XS (17) and IQ4_XS (23)** added for the staged `unsloth/GLM-5.3-Flash-GGUF` UD-Q2_K_XL arm (#2240), decode bit-exact vs llama.cpp `b10451` over REAL bytes from that checkpoint; "UD-Q2_K_XL" names a target average and not a format, and 82 of that file's 1412 tensors are IQ2_XS against two that are Q2_K. Both keep their blocks on the GEMM arm too as of #2247, which added their keep-quant `vec_dot` rows against the Q8_K activation — IQ4_XS pairs with Q8_K and not with the Q8_0 of its codebook sibling IQ4_NL, because its block is a 256-element super-block — gated BIT FOR BIT against the oracle's own kernels on those same real checkpoint bytes. **Both also have a CUDA keep-quant kernel as of #2260**, which is what stops these two encodings draining a CUDA stream to the host cores on every expert GEMM and stops the fused `MoeGateUpSwiGLUGrouped` seam refusing them outright; the CUDA arm is gated against the same oracle numbers on the same real bytes, and against a stream capture, because a dtype that falls back to the host is correct, slow and invisible to every value comparison. That is what takes the artifact from 426.72 GiB resident to 101.14 GiB, measured by driving the production residency decision over all 1412 of its tensors. **IQ4_NL, Q5_0 and Q4_0 have a CUDA keep-quant kernel as of [#2419](https://github.com/mudler/vllm.cpp/issues/2419)**, on a SECOND templated GEMM beside the Q8_K one: these are 32-element encodings that dot a `BlockQ8_0` activation, so the 256-element super-block GEMM the twelve other dtypes share cannot take them at all. Before it the dense and grouped CUDA seams drained the stream and ran the CPU kernel -- MEASURED on GB10 to SEGFAULT rather than merely to be slow, because `Backend::Alloc` is a plain `cudaMalloc` and the CPU kernel dereferences a device pointer -- and the fused `MoeGateUpSwiGLUGrouped` seam threw by name. This is the released `unsloth/Qwen3.8-Flash-Next-GGUF` UD-IQ1_S expert path specifically, and the encodings are forced rather than chosen -- its `expert_feed_forward_length` is 640, so every routed expert row is indivisible by 256 and no K-quant can encode it, which also means the `ffn_down_exps` tower's K = 640 is refused by the Q8_K seams whatever dtype it carries. The device dots are bit-exact against this tree's CPU arm per block; the discriminating gate is a STREAM CAPTURE, because a host fallback returns the same numbers and no value comparison can see it. MXFP4 (39) is the one 32-element encoding still falling back, and is owed. **IQ3_S (21)** added for the `unsloth` "UD" dynamic-quant family ([#2510](https://github.com/mudler/vllm.cpp/issues/2510)), decode bit-exact vs llama.cpp `b10451` over REAL bytes from `Qwen3.8-27B-UD-Q4_K_M.gguf`; it was the ONE hole in the reader's i-quant run 16..23, and four tensors out of that file's 866 refused the whole 16.4 GB artifact while every other encoding in it was already handled. **It is the one FILE encoding here that DECODES and does not DOT**: a gather table keeps its blocks, a GEMM weight EXPANDS to bf16 on every device, and the keep-quant `vec_dot` is owed jointly with the CUDA `WType` arm, because landing the CPU half alone routes every CUDA IQ3_S GEMM through the host fallback that was measured to segfault on a discrete card. On the measured artifact that expansion is 146.13 MiB of blocks against 680.00 MiB of bf16, 3.4 % of a 15.33 GiB file. Q4_1 (3) and Q5_1 (7) remain absent, so a `-Q5_K_M` build of a ragged-K model still refuses | ☐ | ☐ | ✅ | -| GGUF gather tables kept QUANTIZED (one row dequantized per gathered token) | ✅ CPU, `qwen35`/`qwen35moe`/`qwen3next`/`qwen4exp`. `vt::Embedding` takes a block-quantized table, decoding one row per id — a port of llama.cpp's `ggml_compute_forward_get_rows_q`. Without it a 51.2 G-parameter n-gram table expands from 28.8 GB of IQ4_NL to 102.4 GB of bf16, which no device here has (#1989). This is a residency DEFAULT CHANGE on already-shipped GGUF models, not only a new arm: an existing `qwen35` file with a quantized `token_embd` now keeps it compressed on CPU where it used to expand. Tokens do not move (every GGUF-path gather writes a bf16 output and the bf16 round is idempotent over the old expand-then-widen), so the change is memory-only today. `deepseek4` and `laguna` are NOT reached: both consume `token_embd` as a flat host f32 array, so their loaders narrow the policy for that tensor and keep expanding it. A gather's admission is the ROW DECODER and not the `vec_dot`, so IQ2_XS and IQ4_XS joined this set the moment their decoders landed (#2240), a wave before they could keep on the GEMM arm; Q8_K is now the only encoding that still tells the two admission rules apart. **CUDA joined it** (KGATHER, [spec](../.agents/specs/cuda-quant-gather.md)). `EmbeddingKernelCuda` decodes a block row across all 19 encodings `vt::cpu::BlockToFloat` decodes (IQ3_S joined with [#2510](https://github.com/mudler/vllm.cpp/issues/2510)), so a gather table stays block-resident ON THE CARD. The gate is a REGISTRY QUERY and not a device list: `vt::Embedding` routes a block table to `OpId::kEmbeddingQuant` and `DeviceQuantGatherSupported` is `OpRegistered(kEmbeddingQuant, dev)`, so a backend advertises the capability by registering the kernel and a device with no decoder refuses BY NAME. **MEASURED ON A GPU**, nvcc 13.0.88, 2026-08-31, and the two boxes measured DIFFERENT things: **thor:gpu0 (Jetson Thor, sm_110)** ran the branch HEAD through the production registration — 7 of 7 cases at 250 assertions, every encoding bit-exact against the CPU arm in f32 and bf16 out with i32 and i64 ids, against a pre-arm RED leg that failed by name at 32 assertions, and deleting the single production registration reds 5 of 7 cases, so the arm is reached and not merely present. **dgx:gpu0 (NVIDIA GB10, sm_121a)** then ran the SAME head leg green — 7 of 7 at 250, M5 red, every verdict matching thor — so the arm is proven on BOTH architectures and [#2393](https://github.com/mudler/vllm.cpp/issues/2393) is closed. This is what makes a GPU arm of `qwen4exp` possible at all — its n-gram table is 26.822 GiB of IQ4_NL against 95.368 GiB expanded, on a box with ~119.6 GiB for everything — and it is a shape llama.cpp does NOT have: its CUDA `get_rows` dispatches the legacy quants only and aborts on every K-quant and every IQ type, so the llama.cpp column overstates the denominator for the encodings that matter here. Like the CPU arm this is a residency DEFAULT CHANGE on already-shipped GGUF models, and it reaches more than `qwen4exp`: a `token_embd` in a block encoding now keeps its blocks on CUDA where it used to expand, `qwen35` GGUFs included. **For a bf16 output the values do not move** (both routes decode with the same scalar expressions and round once); **for an f32 output the new path is strictly MORE precise than expand-then-widen**, which is a behaviour change on already-shipped models and not merely a memory one. **Owed: the gather arms of METAL, VULKAN, ROCM and TENSTORRENT ([#2394](https://github.com/mudler/vllm.cpp/issues/2394)), which still refuse because each of their gather kernels asserts a float table by name. No throughput number is claimed | ☐ | ☐ | ✅ `get_rows` for ~20 types, CPU and CUDA | +| GGUF gather tables kept QUANTIZED (one row dequantized per gathered token) | ✅ CPU, `qwen35`/`qwen35moe`/`qwen3next`/`qwen4exp`. `vt::Embedding` takes a block-quantized table, decoding one row per id — a port of llama.cpp's `ggml_compute_forward_get_rows_q`. Without it a 51.2 G-parameter n-gram table expands from 28.8 GB of IQ4_NL to 102.4 GB of bf16, which no device here has (#1989). This is a residency DEFAULT CHANGE on already-shipped GGUF models, not only a new arm: an existing `qwen35` file with a quantized `token_embd` now keeps it compressed on CPU where it used to expand. Tokens do not move (every GGUF-path gather writes a bf16 output and the bf16 round is idempotent over the old expand-then-widen), so the change is memory-only today. `deepseek4` and `laguna` are NOT reached: both consume `token_embd` as a flat host f32 array, so their loaders narrow the policy for that tensor and keep expanding it. A gather's admission is the ROW DECODER and not the `vec_dot`, so IQ2_XS and IQ4_XS joined this set the moment their decoders landed (#2240), a wave before they could keep on the GEMM arm; Q8_K is now the only encoding that still tells the two admission rules apart. **CUDA joined it** (KGATHER, [spec](../.agents/specs/cuda-quant-gather.md)). `EmbeddingKernelCuda` decodes a block row across all 19 encodings `vt::cpu::BlockToFloat` decodes (IQ3_S joined with [#2510](https://github.com/mudler/vllm.cpp/issues/2510)), so a gather table stays block-resident ON THE CARD. The gate is a REGISTRY QUERY and not a device list: `vt::Embedding` routes a block table to `OpId::kEmbeddingQuant` and `DeviceQuantGatherSupported` is `OpRegistered(kEmbeddingQuant, dev)`, so a backend advertises the capability by registering the kernel and a device with no decoder refuses BY NAME. **MEASURED ON A GPU**, nvcc 13.0.88, 2026-08-31, and the two boxes measured DIFFERENT things: **thor:gpu0 (Jetson Thor, sm_110)** ran the branch HEAD through the production registration — 7 of 7 cases at 250 assertions, every encoding bit-exact against the CPU arm in f32 and bf16 out with i32 and i64 ids, against a pre-arm RED leg that failed by name at 32 assertions, and deleting the single production registration reds 5 of 7 cases, so the arm is reached and not merely present. **dgx:gpu0 (NVIDIA GB10, sm_121a)** then ran the SAME head leg green — 7 of 7 at 250, M5 red, every verdict matching thor — so the arm is proven on BOTH architectures and [#2393](https://github.com/mudler/vllm.cpp/issues/2393) is closed. This is what makes a GPU arm of `qwen4exp` possible at all — its n-gram table is 26.822 GiB of IQ4_NL against 95.368 GiB expanded, on a box with ~119.6 GiB for everything — and it is a shape llama.cpp does NOT have: its CUDA `get_rows` dispatches the legacy quants only and aborts on every K-quant and every IQ type, so the llama.cpp column overstates the denominator for the encodings that matter here. Like the CPU arm this is a residency DEFAULT CHANGE on already-shipped GGUF models, and it reaches more than `qwen4exp`: a `token_embd` in a block encoding now keeps its blocks on CUDA where it used to expand, `qwen35` GGUFs included. **For a bf16 output the values do not move** (both routes decode with the same scalar expressions and round once); **for an f32 output the new path is strictly MORE precise than expand-then-widen**, which is a behaviour change on already-shipped models and not merely a memory one. **ROCm now registers a native HIP gather for all 19 admitted encodings** ([spec](../.agents/specs/rocm-quant-gather.md), [#3093](https://github.com/mudler/vllm.cpp/issues/3093)). The gfx1100 public gate passes each codec against its dense control, and matching operation traces retain compressed tables with direct bf16 output. Original primary fixtures and pinned model qualification remain pending. **Owed: the gather arms of METAL, VULKAN and TENSTORRENT ([#2394](https://github.com/mudler/vllm.cpp/issues/2394))**, whose gather kernels still require floating tables. No throughput number is claimed | ☐ | ☐ | ✅ `get_rows` for ~20 types, CPU and CUDA | | GGUF F16 weights kept resident as F16 (no BF16 promotion) | ✅ `VT_GGUF_KEEP_F16` default-ON (CPU), the f16 GEMM computes on it directly. Default settled 2026-08-17, a memory-for-speed trade: 1.05 GiB less peak RSS for ~9% prefill and ~1.4% decode, tokens identical. `0` opts out | ☐ | ☐ | ✅ `ggml_vec_dot_f16` | | GGUF is a TWO-engine comparison at these pins (#979) | ✅ text-only `qwen35`, no `clip` projector (#821) | ☐ REMOVED from the tree in `6635279d8`, now an unpinned out-of-tree `vllm-gguf-plugin` | ☐ full stack present, `qwen3_5` unreachable behind FOUR blockers, and the load path has NO completeness guard so a clean-looking load proves nothing | ✅ native, `LLM_ARCH_QWEN35` | | EXL3 trellis (exllamav3; codebooks 0 (3INST), 1 (MCG) and 2 (`mul1`), Hadamard-128 + sign vectors, NO scales) | ◐ **A stock EXL3 checkpoint GENERATES**: `turboderp/Llama-3.2-1B-Instruct-exl3` @ 3.0bpw loads through the shared dense container and emits coherent text from `vllm-cli` on a CUDA queue and on a CPU queue, which reaches `LlamaForCausalLM` and Qwen3-dense together. The scheme sits on vLLM's own `LinearMethodBase` seam, so it is no longer a DeepSeek-V4-private arm. `bits` and the codebook are both read PER TENSOR — the published 3.0bpw Llama has a 3-bit body and a 6-bit head, and ships no `mcg` marker, which means codebook 0 and not MCG. **The DeepSeek-V4 arm is separate and unchanged**: its rank-sliced SparkInfer artifact loads and executes end to end on a synthetic checkpoint. The rank-sliced `0xSero/deepseek-v4-flash-0731-spark` routed-expert tower coalesces TP4->TP1 at load, the `carried-*` half (block-wise FP8 + BF16 + F32) is dequantized into the host-float tower the forward composes with, and `DeepseekV4Model::Forward` runs the whole model, dispatching one `vt::Exl3MoeMlp` per MoE layer over the routed experts (`bits == 3`, `mcg` codebook). **The REAL artifact still does not run**: its DSA compressor and indexer tensors are twice the width the host forward indexes and the loader refuses them by name, and its tokenizer is not read (#1924). **The device half is now PARTLY VERIFIED** (GB10 `sm_121a`, 2026-08-28): `had_r_128` is BYTE-IDENTICAL CUDA-vs-CPU, `exl3_gemm` matches the f64 reference at `rel_rms 5.538e-4` against a `1.0e-3` bound, and the `m<=8` GEMV meets tier 3c at `5.160e-4` against `6.0e-3`. What is STILL unverified on a device is the FUSED MoE arm, which cannot run on this code at all: it needs a device-resident tower and `CudaBackend::DeviceMemoryIsHostAddressable()` is false by design, so the routed-expert path executes on a CPU queue today. No speed number is claimed on any axis. **Codebook 2 (`mul1`) and the 4- and 5-bit widths are now implemented** so that `Mia-AiLab/Qwen3.8-27B-EXL3-3.5bpw` -- **409** trellis modules, 137 at 3 bpw, 270 at 4, one at 5 and one at 6, every one of them `mul1`-marked -- is no longer refused by name ([#2495](https://github.com/mudler/vllm.cpp/issues/2495)). The count read 272 until 2026-09-02 and was an UNDERCOUNT that omitted the 137 bits-3 modules, which is why `(3, 2)` was missing from the CUDA instantiation list and every MLP projection of that target refused on a CUDA queue. **`(3, 2)` is now instantiated and gated on `dgx:gpu0`** (GB10, driver `580.173.02`), agreeing with the CPU decoder at `rel_rms 3.02544e-07` against a `1.0e-3` bound ([#2574](https://github.com/mudler/vllm.cpp/issues/2574)). cb 2 is a DIFFERENT decode and not a third multiplier: it sums the four bytes of the product into an fp16 bit pattern and maps it with a fused fp16 affine, and the host arm is gated against hand-computed upstream values rather than against itself. **A ROCm arm now exists too** ([#2433](https://github.com/mudler/vllm.cpp/issues/2433), [spec](../.agents/specs/backend-rocm-exl3.md)): `Exl3Gemm` on `gfx1151` is a transcription of the PORTABLE CPU reference rather than a port of the CUDA kernel -- 90 KiB of requested shared memory does not fit a 64 KiB AMD LDS, and `m16n8k16`, `ldmatrix` and `cp.async` have no AMD form -- and because it uses no matrix cores it is gated at BYTE equality with the CPU arm on all three codebooks, not at a tolerance. It covers every width the host arm decodes, so the CUDA instantiation list below does not bound it. On the CUDA device arm `(3,0)`, `(3,1)`, `(6,0)`, `(3,2)`, `(4,2)`, `(5,2)` and `(6,2)` are instantiated -- `(3,2)` is the width the undercount cost, added and device-gated by [#2574](https://github.com/mudler/vllm.cpp/issues/2574); every other width and codebook and the device-resident tower are owed ([spec](../.agents/specs/quant-exl3-mul1.md)). **The `m<=8` GEMV is a SEPARATE arm set from that list and a separate row** ([`QUANT-EXL3-PERF`](../.agents/specs/quant-exl3-perf.md), [#2570](https://github.com/mudler/vllm.cpp/issues/2570)): upstream instantiates `(4,0) (4,1) (4,2) (2,1) (2,2) (3,1) (3,2)` and this tree now carries `(3,1)`, `(3,2)` and `(4,2)`, so **407 of that checkpoint's 409 trellis modules** reach the small-m fast path where before NO module of it could -- the only arm was `(3,1)` and the artifact contains zero `(3,1)` tensors. `(3,2)` was one template argument; `(4,2)`, the 270-module arm, was a KERNEL port: a per-width `LSTRIDE`, two 24-lane guards that exist only because a 3-bit tile is 24 uint32 rather than 32, and a separate `dq8_regs_4bits` window read. `(4,0)`, `(4,1)` and the whole 2 bpw arm stay OWED -- no artifact in this tree carries a 4-bit tensor at either of the first two codebooks, and nothing builds them, so that the kernel would compile for them is an inference and not a measurement. **Instantiating an arm is necessary and not sufficient**: `Exl3GemvSelectConfig` is upstream's envelope verbatim and DECLINES, and on Blackwell EVERY shape of this checkpoint, at both widths, is admitted only where `size_n / 32 <= narrow_coresident`, an occupancy query. The wide config is not an escape from it: its band needs `size_k <= 4096` and the smallest 4-bit `k` here is 5120. The thresholds are `>= 544` and `>= 160` at the two bits-3 shapes and 32, 160, 192, 320, 384 and 544 across the six bits-4 ones, all pinned in `tests/vt/test_exl3_gemv.cpp` from both sides. **The throughput effect is now MEASURED on GB10, and it is a NULL** ([#2570](https://github.com/mudler/vllm.cpp/issues/2570)): three interleaved rounds on one binary read 17.20/17.18/17.09 tok/s with the arm off against 17.22/17.12/17.09 with it on, a 1.3% spread and no separation. `nsys --cuda-graph-trace=node` shows why, and it is a DECLINE and not an ineffective kernel: `exl3_gemv_kernel` appears 0 times at the default and 4 times only when forced. GB10 reports `SM_COUNT=48 MAX_THREADS_PER_SM=1536`, so the narrow config's 512-thread blocks ceiling `narrow_coresident` at 144, and only shapes needing `<= 144` are admitted -- 34 of the checkpoint's 409 modules, 0.75% of its trellis bytes. The arms are correct, upstream-faithful and device-gated; on THIS part the envelope declines them. `m == 8` is unmeasured, because the draft legs did not run. **The FUSED MoE mgemm is a SEPARATE arm set from that list**, and upstream's own bound on it is narrower: `exl3_moe.cu:184` admits `mcg` and `mul1` and refuses 3INST, so codebook 0 is not a MoE arm upstream either. It now instantiates bits 3, 4, 5 and 6 at codebook 1 where it carried bits 3 alone ([#2756](https://github.com/mudler/vllm.cpp/issues/2756)); before that a mcg expert tower at any other width could not run on a CUDA queue by ANY path, because the fused arm is default-ON and its refusal is not caught, and the `VT_DSV4_EXL3_FUSED_MOE=0` rollback lands on a GEMM arm set with no `(4,1)`, `(5,1)` or `(6,1)` either. Codebook 2 on the fused arm is owed as a LOADER slice and not a kernel one: five sites pin the codebook to 1 before the kernel is chosen, so a cb-2 instantiation added alone would be dead code. **Its GDN linear-attention tower now loads and runs too** ([#2495](https://github.com/mudler/vllm.cpp/issues/2495) item 4, [spec](../.agents/specs/model-qwen35-gdn-exl3.md)): 48 of that model's 64 layers are `linear_attention`, and the three projections of each were refused by name because nothing in the GDN forward consumed an `Exl3Weight`. The arm holds THREE trellises rather than one merged `in_proj_qkvz` owner, because the artifact ships `in_proj_qkv` and `in_proj_z` as two independently quantized tensors whose sign vectors are fitted per projection, so the bf16 merge has no trellis analogue. It also accepts the F16 `in_proj_a`/`in_proj_b` the artifact stores beside its BF16 `conv1d`, `norm`, `A_log` and `dt_bias`. **The DFlash2 DRAFT loader now has an EXL3 arm too** ([#2495](https://github.com/mudler/vllm.cpp/issues/2495) item 7, [spec](../.agents/specs/model-dflash2-exl3.md)): `Mia-AiLab/Qwen3.8-27B-DFlash2-EXL3-5.0bpw` ships all 36 of its modules at bits 5 with a `mul1` marker, and `LoadQwen3DFlash` died on `fc.weight`, which an EXL3 module does not ship. The arm holds SEVEN trellises per layer rather than the merged `qkv_proj` and `gate_up_proj` owners the bf16 reader builds, for the same reason the GDN tower holds three. It also accepts the F16 `candidate_selector.hidden_projection` and `*_conv.kernel_projection` the repack left unquantized beside their BF16 `base_kernel` and codebooks — a second refusal that was invisible until the first was gone. **Its `mtp.*` draft head loads and runs too, and all THREE readers of the target's trellis head now compute with it packed** ([#2495](https://github.com/mudler/vllm.cpp/issues/2495) items 5 and 6, [spec](../.agents/specs/model-qwen35-exl3-head.md)): the MTP loader refused nine quantized `mtp.*` tensors as "expected BF16", and the MTP draft's `ComputeLogits` plus the DFlash/DSpark draft's SHARED head read knew only bf16 and NVFP4. The head is COMPUTED WITH rather than widened, which is what upstream does without a branch because its head is an `nn.Module` and `_apply_head` calls `lm_head.quant_method.apply`; a dequantized copy of the real 248320x5120 head would be 2.543 GB against 0.953 GB packed. The shared read also used to fall off the end of its bf16 loop and return SILENTLY with every owner empty when no arm matched, which is exactly what this target does -- it ships no `lm_head.weight` at all -- and it now refuses by name ([#2569](https://github.com/mudler/vllm.cpp/issues/2569)). **The checkpoint's real inventory is 409 quantized modules, not the 272 this row previously recorded**, measured from both downloaded shards' headers: bits 3 x137, 4 x270, 5 x1, 6 x1, every one `mul1`, and no tensor in the file has `scale` in its name. `(bits 3, codebook 2)` is now instantiated on the CUDA GEMM and gated on a device, so those 137 modules no longer refuse by name ([#2574](https://github.com/mudler/vllm.cpp/issues/2574), owned by `QUANT-EXL3-MUL1`, not by this row). **THE 27B CHECKPOINT NOW RUNS ON CUDA AND GENERATES.** On `dgx:gpu0` (GB10, driver 580.173.02, `sm_121a`) the published `Mia-AiLab/Qwen3.8-27B-EXL3-3.5bpw` loads and emits ` Paris. The capital of Germany is Berlin. The capital of Italy is` at `rc=0`, with both shard sha256 values recomputed on the device. Warm decode is **16.7 tok/s** target-only and **48.7 tok/s** with its DFlash2 EXL3 draft at k=7, interleaved on one binary, and the two arms are **token-identical** ([`qwen38-27b-exl3-gb10`](benchmarks/qwen38-27b-exl3-gb10.md)). **That is NOT a reproduction of the upstream README's 47.5 tok/s**, and must not be quoted beside it: theirs is HumanEval-style at T=0.6 with acceptance 4.43, this is greedy T=0 on a prompt that continues into a list of capitals, the context is 8192 rather than 262144 with no NVFP4 KV cache, and the shipped paged draft route had to be disabled (#2274). A matched HumanEval-style run at T=0.6 with acceptance reported is owed | ☐ no EXL3 at the parity pin | ☐ | ☐ | diff --git a/docs/bench-evidence/rocm-quant-gather/README.md b/docs/bench-evidence/rocm-quant-gather/README.md new file mode 100644 index 000000000..28ec3c184 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/README.md @@ -0,0 +1,187 @@ +# ROCm quantized gather evidence + +Row: `BACKEND-ROCM-QUANT-GATHER`. +Issue: [#3093](https://github.com/mudler/vllm.cpp/issues/3093). +The [committed spec](../../../.agents/specs/rocm-quant-gather.md) defines the gates. + +The native operation, public dense control, and matching operation traces pass. +Pinned model qualification and the original upstream fixture gate remain pending. +This evidence makes no throughput, latency, model token parity, or performance claim. + +## Identity and scope + +The implementation started from spec commit `670e6d78ddf55231394748e0032939fd53dc56a5`. +The Q8_K materializer amendment preceded its code at `376223f000f85683f2881136e38ee52892d8d3a8`. +The reader amendment preceded its code at `2e5adfb85a255528bffa5d3cdb016efb2bab70d8`. +The prerequisite full-attention repair was independently reviewed at +`6a7bcb77637e66df34429208e3a4055e0945a875` and cherry-picked before the intended red run. +Its later runner expectation repair was imported as spec `8c9101fa4` and test commit `b46852d13`. +Those three dependency files equal donor `694f04525174d0c2dac8030ba8f1398f2683ec82` byte-for-byte. + +Early captures identify uncommitted source with complete file and executable hashes. +Their hashes describe the measured stages, including defects repaired before the final implementation. +They are not claims that every early artifact equals the final commit. +The final commit and review receipts identify the final acceptance candidate. + +All native GPU commands ran through the operator on the supplied gfx1100 host. +The operator held its recorded file mutex and checked input hashes around each run. +The two-device bounds test used visible devices `0,1`; other native runs used device `0`. +Helper builds and secondary oracle runs were CPU-only. +Every listed absolute path records this measured environment and is not a default. + +The primary runtime uses vLLM `e126687a9a828d513c01a07cd69f025f27d63280` and plugin +`d4c1f0d082fc7cd4350da56689109a01c1f29d6c`. +It runs in the existing image +`sha256:80aab4c182a1f3eeebe286173977e57fcaf10a049b41f475655b35d285de31dc`. +The separate plugin artifact contains native extension +`592af79c210496e96eaa7bd409ae0a67e7de8c334aa9f782082c7639ba300138`. +The build recipe, log, and complete artifact hashes are retained here. +No existing oracle runtime was modified. + +Stock llama.cpp is `10bf611e533d81f739128304991c5e133c6aebd8`. +The registered IQ1_XXXS fork is `36fe8e1cc7f2b3b8c92fdda0ab07600141921786`. +The [independent oracle audit](oracle-audit-report.md) verifies their source archives, +executing decoder chain, binaries, plugin artifact, and captured outputs. +That audit is separate from implementation mutation review. + +## Red and green results + +Raw `.log` filenames in this document refer to unchanged files inside `raw-logs.tar.gz`. +The archive preserves original whitespace and hashes. + +| Gate | Observed result | Evidence | +|---|---|---| +| Initial public attempt | Wrong-reason failure in unused GDN state validation; not the intended red | `public-red.log` | +| Public attempt after reviewed prerequisite | Intended failure: zero compressed provider selections; 10 of 11 assertions passed | `public-red-after-prerequisite.log` and sealed recipe | +| Q8_K reader | Type 15 refused before materialization | `q8k-reader-red.log` | +| Q8_K materializer after reader repair | Reader passed; dot-only materializer guard refused decoder-only Q8_K | `materializer-second-red.log` | +| Q8_K reader and role-aware materializer | Two cases, 18 assertions passed; reader regression passed 36 cases, 133 assertions | `materializer-focused-green.log`, `reader-regressions-green.log` | +| Queue device binding | Ambient device 1 caused invalid stream use for queue 0 before the fix; 16 assertions passed after binding queue 0 | `ambient-device-witness-v1.log`, `ambient-device-witness-v2.log` | +| Native focused v2 | Seven executed CTests passed, including all 19 public model variants | `native-focused-v2.log`, operator receipts | +| Final native v4 | All 15 CTests executed and passed; primitive suite 9 cases and 11,784 assertions; public suite 2,850 assertions; required two-device case 16 assertions | `native-final-v4-focused-and-rocm-regressions.log`, `native-final-v4-required-ambient-device.log`, sealed commands and operator receipts | +| Native/primary/secondary operation comparison | All 76 outputs passed; 68 were byte-identical | `synthetic-parity-v2.json`, independent operator comparison | +| Applicable stock GET_ROWS shape | Width 256, five rows, four IDs; all six native outputs matched the pinned secondary result | `stock-shapes-v1-operator-results.json` | +| CPU-only configuration | Five CPU targets passed; three accelerator-only targets skipped explicitly; the imported runner suite passes 41 cases and 1,914 assertions | `cpu-configure.log`, `cpu-focused-green.log`, `cpu-runner-green.log` | + +The model builder fixes seed `0x524f434d`, geometry, tokenizer metadata, and tensor values. +The two-regeneration manifest confirms all 38 model hashes, without changing fixture bytes between red and green. +The public path uses 19 codecs, two prompts, three repeats, and a fresh engine for each request and dense control. +It checks all four greedy token IDs and all 512 captured logits byte-for-byte. +The final public run additionally writes each completion's tokens and raw F32 logits with +`VT_ROCM_GATHER_PUBLIC_EVIDENCE`. + +## Numerical oracle evidence + +`native-operation-captures.tar.gz` preserves 76 native outputs and its report. +`primary-operation-captures.tar.gz` preserves 64 primary outputs and its report. +`secondary-operation-captures.tar.gz` preserves the six actual upstream F32 outputs. +The native BF16 secondary comparison applies explicit round-to-nearest-even to those F32 outputs. +It does not claim that either secondary graph executed BF16 output. + +The primary gate preserves `atol=0.01`, `rtol=0.04`, widths 256/1024, and both admitted output dtypes. +The local ABI flattens the upstream two-by-two IDs; the primary harness restores that shape. +IQ1_M and F16 output exceed the shared local contracts and remain explicit exclusions. +The generated 128-row corpus does not replace the 32 original upstream GGUF fixtures. +Their 289,655,872-byte download awaits the developer's authority under issue #3093. + +Eight nonidentical comparisons are confined to Q6_K and IQ3_S, across two widths and output dtypes. +Q6_K's primary decoder rounds intermediate products to F16; the local decoder uses F32 products. +IQ3_S's primary codebook contains effective values of 15.5 where the local/stock codebook contains 15. +All differences satisfy the unchanged upstream tolerance. +The [arithmetic diagnostic](oracle-audit-arithmetic-explanation.json) reproduces both executing expressions. +It explains the runtime outputs and does not replace them with a scalar oracle. + +Stock GET_ROWS excludes Q8_K, so the harness calls its pinned `dequantize_row_q8_K` directly. +MXFP4 and IQ1_XXXS execute real upstream GET_ROWS graphs. +The additional stock-shape corpus preserves its applicable width 256, five rows, four IDs, and contiguous unbatched layout. +Its deterministic packed values and first/last/middle/repeated IDs adapt upstream's unrecorded random input. +The local suite explicitly refuses batched tables and strided IDs. +Upstream cases with batched tables, floating-only dtypes, or backward gradients exceed this gather ABI. + +## Memory and matching traces + +Both implementations used the same 32 packed tables, widths 256/1024, four I64 IDs, and requested F32/BF16 outputs. +Both used the exact existing rocprofv3 1.3.5 profiler and its isolated prefix. +The prefix contains profiler dependencies and excludes HIP/HSA/BLAS runtime replacements. +Version 2 adds allocation events to both sides; its inputs, executable, and harness equal version 1. +The trace-only primary harness omits the already-verified full-table dense control. +Every traced output equals the same implementation's untraced output byte-for-byte. + +The native trace contains 64 fused gather kernels, with 32 F32 and 32 BF16 template instantiations. +Its 192 correlated `hipMalloc` events exactly match 32 packed tables, 32 ID arrays, +64 output arrays, and 64 error records of 16 bytes. +There is no extra native device allocation for selected packed rows or an F32 staging output. +The profiler's host runtime allocations are identified separately. + +The primary trace contains 64 GPU packed-row selections and 64 native decoder launches. +Each output uses the requested F32 or BF16 decoder template. +Its caching allocator appears as a backing pool in the profiler. +Separate PyTorch telemetry measures each tensor operation: the live delta equals its output size; +the peak delta adds selected packed rows rounded to the observed 512-byte allocator unit. +Those tensor counters are not profiler allocation-size measurements. + +The source chain in the independent audit and these executed GPU kernels establish selected-row native decode. +The trace harness contains no dense-control or host-dequantization call. +Provider counts are an additional reachability check, not the only evidence against host fallback. +A separate trace runs the complete public model test: 228 engines and 2,850 assertions passed. +All 456 preserved capture files contain exact dense-control and repeat token/logit bytes. +The operator verified every capture, kernel correlation, and device allocation independently. +The model trace executes 912 BF16 KV reads, 912 two-byte KV writes, and 456 direct BF16 quantized gathers. +It records 228 `hipMalloc` allocations of 16,384 bytes, matching one KV pool per engine. +The source allocates four pages of `16 * 1 * (64 + 64) * 2 = 4096` bytes each. +The allocator-to-KV attribution uses that source chain: CSV does not expose kernel argument pointers. +The observed cache template dtype and byte counts are preserved separately from this attribution. +`public-model-trace-captures.tar.gz` retains complete profiler CSVs, completion captures, and the scratch capture audit. +This establishes native BF16 cache storage; matching oracle model memory remains pending. + +## Remaining qualifications + +The stock and fork bounded model attempts both abort on their first decode before emitting tokens. +The observed assertion is `ggml-backend.cpp:194::GGML_ASSERT(buffer)` through hybrid memory input setup. +An unused recurrent input is the source-based hypothesis, not a proven object-allocation diagnosis. +Their context request of 64 resolves to 256 cache cells through the pinned upstream padding rule. +Their BF16 KV payload is therefore 65,536 bytes, against the spec's requested 16,384 bytes. +That configuration adaptation and both model executions remain pending under issue #3093. +The fork's independent real 2.4T qualification remains owed under issue #933. + +The primary model attempt uses this row's exact Q4_0 fixture, SHA256 +`663597e28852d64097f7a67542675e4575ee158d3c5e6e2143aadd1b4188f4af`. +The first attempt failed because Triton's default cache path was unwritable. +That operational failure is not a model compatibility result. +The second attempt supplies writable task-local cache paths without changing the model, HF config, or oracle code. +It reaches the pinned renderer and refuses `Qwen3_5TextConfig` where `Qwen3_5Config` is required. +It emits no tokens. The full traceback and sealed recipe preserve that actual model refusal. +The operator checked 340 input files before and after the second attempt. +No further model adaptation is approved; this gate remains pending under issue #3093. +The final v4 operator audit confirms all 456 completion files equal the traced run byte-for-byte. +All 33 sealed source, library, and executable files remained unchanged during v4. +The row stays active until model execution, original fixtures, fresh mutation review, +and the operator's reviewed-head rerun meet their respective requirements. + +## Full preflight + +The first full staged run found two stale source citations after the materializer edit. +The corrected engine-matrix rows change only `SPEC-MTP-GGUF` and `SPEC-DFLASH-GGUF` line anchors. +Every unrelated row remains byte-identical, and the anchor baseline stays at 28. +The record gate then passes with 937 valid anchors, 28 stale anchors, and five pre-existing broken anchors. +The final full staged rerun exits 0 with no failures and five argument-dependent skips. +All 31 translation units in its host syntax scope compile. +This is not an all-green preflight, because a skipped check executes nothing. +The separate CPU ISA check passes against the actual CPU-only compile commands. +The ARM ISA, CUDA code-generation, and CUDA Triton artifact checks do not apply to this x86_64 HIP configuration. +Exact commit path classification runs after committing and accompanies the handoff. +Combined CUDA/HIP execution remains pending because no combined build was available. +The raw final log and explicit CPU ISA result are archived unchanged. +`preflight-final-staged-result.json` records the exact command, environment, staged tree, statuses, and skip dispositions. + +## Reproduction + +Build and run the focused commands in the spec under the operator's GPU authority. +Generate operation inputs with `rocm_quant_gather_capture generate DIRECTORY`. +Run `primary.py capture`, `secondary.cpp`'s `gather` mode, and native `capture` with the sealed corpus. +`compare.py` compares the native report against each independently executed oracle. +`stock_shapes.py` exports the applicable secondary geometry without downloading or changing packed values. +`audit_trace.py` verifies each trace against its untraced outputs and checks the memory evidence. + +Exact argv, environment, source hashes, executable hashes, and operator receipts accompany each stage. +Downloaded upstream GGUF fixtures and generated model weights are not committed here. diff --git a/docs/bench-evidence/rocm-quant-gather/ambient-device-witness-v1.json b/docs/bench-evidence/rocm-quant-gather/ambient-device-witness-v1.json new file mode 100644 index 000000000..6dab41372 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/ambient-device-witness-v1.json @@ -0,0 +1,54 @@ +{ + "version": 1, + "row": "BACKEND-ROCM-QUANT-GATHER", + "head": "376223f000f85683f2881136e38ee52892d8d3a8", + "cwd": "/home/vikash/vllm.cpp-rdna3-gather-impl", + "env": { + "HIP_VISIBLE_DEVICES": "0,1", + "ROCR_VISIBLE_DEVICES": "0,1", + "VT_ROCM_GATHER_REQUIRE_TWO_DEVICES": "1", + "TMPDIR": "/home/vikash/.cache/rdna3-gather-impl/tmp" + }, + "argv": [ + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant", + "--test-case=ROCm gather follows the queue device when the ambient device differs", + "--abort-after=1" + ], + "log": "/home/vikash/.cache/rdna3-gather-impl/evidence/ambient-device-witness-v1.log", + "authority": "Operator runs this bounded witness under the recorded global GPU mutex with devices0 and1 visible", + "expectation": "Require two devices. Queue/table/output reside on0; ambient device switches to1 before shared vt::Embedding. Check correct rows, bounds exception, and immediate recovery. No device-binding implementation change precedes this witness.", + "files": { + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vt/test_rocm_embedding_quant.cpp": { + "bytes": 17542, + "sha256": "7026334d9ab70b3fa56cf0c4af4012f054e539ba37a48c586732742d7278a927" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/CMakeLists.txt": { + "bytes": 275318, + "sha256": "45ee683859f89aa7c4c8d5ec253e46a0cf4d8de5eb33ac5f196c8fd413d3cba1" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_embedding_quant.hip": { + "bytes": 7556, + "sha256": "5934d1727c96ec8e76f4e7dc3805e15d271fb528b7c0ad6c3a5d2863a179686b" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_embedding_quant.h": { + "bytes": 554, + "sha256": "1b2b31617d660b64f622e692089423ce1657df102322558a4ab731f521952bc5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_quant_dequant.h": { + "bytes": 25507, + "sha256": "413dc138254cc72f8dccbc87268581217c93dec8f8acaea159f3f39569c37e62" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_quant_iq_tables.h": { + "bytes": 110865, + "sha256": "d267d25ff1dd3f67749c251f87047f4b70c9650a99d04b524ff6c3313596a349" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/libvllm.a": { + "bytes": 95078500, + "sha256": "acbf7ceb5c2efa04ff56189e04de549ebe760ba70f3d7967f684f2e7709431cb" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant": { + "bytes": 30954024, + "sha256": "f2dd2bfa912713cd7e6599dd868a1f347487fcf4b8da537b464a31f5cb576eae" + } + } +} diff --git a/docs/bench-evidence/rocm-quant-gather/ambient-device-witness-v2.operator-receipt.json b/docs/bench-evidence/rocm-quant-gather/ambient-device-witness-v2.operator-receipt.json new file mode 100644 index 000000000..24df9a3d4 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/ambient-device-witness-v2.operator-receipt.json @@ -0,0 +1,29 @@ +{ + "name": "ambient-device-v2", + "argv": [ + "flock", + "-n", + "-F", + "/home/vikash/gpu.lock", + "env", + "HIP_VISIBLE_DEVICES=0,1", + "ROCR_VISIBLE_DEVICES=0,1", + "VT_ROCM_GATHER_REQUIRE_TWO_DEVICES=1", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "timeout", + "180s", + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant", + "--test-case=ROCm gather follows the queue device when the ambient device differs", + "--abort-after=1" + ], + "exit_code": 0, + "elapsed_seconds": 0.5165746212005615, + "manifest_sha256": "2928aa6cbc417a3993c86481cbdd6c3ba4e35072bbf703212976344bda57fed0", + "log_sha256": "38fec7edbc44a0e557538088a130e98da012892fdec43f29234989d35718209e", + "all_101_manifest_inputs_verified_before_after": true, + "core_dumps_disabled": true, + "summary": [ + "[doctest] test cases: 1 | 1 passed | 0 failed | 8 skipped", + "[doctest] assertions: 16 | 16 passed | 0 failed |" + ] +} diff --git a/docs/bench-evidence/rocm-quant-gather/materializer-second-red.json b/docs/bench-evidence/rocm-quant-gather/materializer-second-red.json new file mode 100644 index 000000000..f7aae2d18 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/materializer-second-red.json @@ -0,0 +1,44 @@ +{ + "version": 1, + "head": "2e5adfb85a255528bffa5d3cdb016efb2bab70d8", + "argv": [ + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf_keep_quant", + "--test-case=Q8_K*" + ], + "env": { + "HIP_VISIBLE_DEVICES": "-1", + "ROCR_VISIBLE_DEVICES": "-1" + }, + "exit": 1, + "result": "Reader case passed; ordinary loader throws at OwnGgufQuantBlocks KeepQuantDType guard, qwen3_5_gguf_weights.cpp:89. All12 assertions passed before exception.", + "files": { + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vllm/model_executor/model_loader/gguf_reader.cpp": { + "bytes": 29998, + "sha256": "2901344cb8252ac3c66cacd9b2ae137a814217425df28c387bbdade83d9c12e5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp": { + "bytes": 90319, + "sha256": "9ee863b7821648d43deaaed288408f3fcd13dd089ace8109bf12233d4212e944" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/include/vllm/model_executor/models/qwen3_5_gguf_weights.h": { + "bytes": 17840, + "sha256": "ecb95af1c711afc2c2eefef5de7aba88bcefd3f61453fb25b92b7df4f3d9053d" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vllm/test_gguf_keep_quant.cpp": { + "bytes": 134876, + "sha256": "65a5e5a40f19d8e264bc1bb341c2a8276a3719c59c7faa2c91b4f4b7bfe9dd92" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/libvllm.a": { + "bytes": 95078844, + "sha256": "48d0ab6c0541c20ba4e3d87df07da1aa31c14baac87dcfb995d4af8f73c64b25" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf_keep_quant": { + "bytes": 31354600, + "sha256": "5970560b000d16d7e86390417793317ff2b06f4e4bd5232603b8304fc715ed5d" + }, + "/home/vikash/.cache/rdna3-gather-impl/evidence/materializer-second-red.log": { + "bytes": 846, + "sha256": "4d8846fe34ed7c6abb0d7bdeb4853674de3f4a2fc4b45c95fbd8fa59d1f23397" + } + } +} diff --git a/docs/bench-evidence/rocm-quant-gather/native-final-v4-commands.json b/docs/bench-evidence/rocm-quant-gather/native-final-v4-commands.json new file mode 100644 index 000000000..4fabe7a15 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/native-final-v4-commands.json @@ -0,0 +1,191 @@ +{ + "row": "BACKEND-ROCM-QUANT-GATHER", + "version": 4, + "base_head": "b46852d13f7c8776557dab170e02ebea50cdfdec", + "implementation": "Frozen gather candidate after trailing-space-only table cleanup and imported runner expectation repair; complete clean HIP617-step build plus updatedtest_runner target", + "files": { + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant": { + "bytes": 30952192, + "sha256": "d0d85c52aed0efa959752b6acafe1aac03c19b985543ccffc09f3008a6e23280" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_capi_rocm_embedding_quant": { + "bytes": 30926000, + "sha256": "6a8f7e1029b904c94c0d76561f0291cd17fd7b3e4db29e2d95e3b33894c74efd" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf_keep_quant": { + "bytes": 31352656, + "sha256": "28e3502d940688a0a2b795e93f0456595e55b13e4508a8e0d7b448f8a3b977b2" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_ops_embedding_quant": { + "bytes": 30843664, + "sha256": "adf3962f3f99c7e28cd2cbded31e36b8a324908fa6a6fa610d354b5b4de29b4a" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf_dequant": { + "bytes": 30960400, + "sha256": "0c6f4d003de2ec308fbef18d661843dfc21c59f9d31b27a9a0c8eda1f42f9fa3" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_backend_cross_device": { + "bytes": 31467496, + "sha256": "4a03440c90f387a391ca312b769f0e3cf949909598575ff902c0f67b4fdc756f" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf": { + "bytes": 31012152, + "sha256": "e6e2e2caee1e8ef17cbcd4dca5dca578c3c1e8cdb35c4cbad9bf259646eee9d1" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_arch": { + "bytes": 30868192, + "sha256": "c47ed82bb92734a5e2b1b434a82bc1708c6bde19c3c5c2a00f1f6b79fde069a0" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_backend": { + "bytes": 30908448, + "sha256": "d9eb4e31e6e0e04802e15ca49c4fbe6063201468571cc45f60d9669eb9793147" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_fp8_kv_cache": { + "bytes": 30927608, + "sha256": "021a7cb5bb215a38dc59cf41bf63a5a4191535abe0a9dc4ab257cd18d8e5457f" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_ops_rocm_silu_rounding": { + "bytes": 30858504, + "sha256": "e73f9429d1900b37c346b9ab5a670cf4d459b98896e7b16d60e7db70bce2b055" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_exl3_rocm": { + "bytes": 30863768, + "sha256": "3b99314fccc7732b30eb25b59d895c04ba724db3253d6c8510c494e31acb8cbf" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gemma4_rocm_fp8_seams": { + "bytes": 30859872, + "sha256": "0a6552809425f62481ae04386ce29bb670d3375032eeef43841d73b928c93b2c" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_backend_multidevice": { + "bytes": 30837568, + "sha256": "f506061d963e2cc97054d65b1ecfa78cbb8358435d57a5bf5dcfc0dd3fb285df" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/libvllm.a": { + "bytes": 95078032, + "sha256": "e1e56ec9535a7501a8313986861dfa7bed3fde35f50dbdbc3ba05c4aac7b1afa" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/CMakeLists.txt": { + "bytes": 175502, + "sha256": "e5bea1baa842ac0257fb29d61cb6ef37977d975d6ac0478f81d6e677fe85ce32" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/include/vllm/model_executor/models/qwen3_5_gguf_weights.h": { + "bytes": 18080, + "sha256": "ed37c245f574d2f42df14b40261a8ecb6ae56c159588a82e1550fc49ccaf4655" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vllm/model_executor/model_loader/gguf_keep_quant.cpp": { + "bytes": 26770, + "sha256": "d4b45702692b41359a1e8efd836bb28a14fbbe37a06ee28d818e88b885c01a2b" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vllm/model_executor/model_loader/gguf_reader.cpp": { + "bytes": 29998, + "sha256": "2901344cb8252ac3c66cacd9b2ae137a814217425df28c387bbdade83d9c12e5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp": { + "bytes": 90683, + "sha256": "685ca1623c336876768038a8aa28260694cd4207a1ac1e2d488bc81e451be4fb" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_embedding_quant.h": { + "bytes": 554, + "sha256": "1b2b31617d660b64f622e692089423ce1657df102322558a4ab731f521952bc5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_embedding_quant.hip": { + "bytes": 7777, + "sha256": "d3989353ece6a0c09e1f68ac16c5dbe8c949cd32c3831f41d4c2af835a3512e5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_ops.hip": { + "bytes": 22703, + "sha256": "650a7d033b3ce3fc7a6c9a2e6bcfa80963c172ad5ef58421e2956892aac80935" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_quant_dequant.h": { + "bytes": 24573, + "sha256": "a00ad5d98ae63fbb37683c1e26aa5494ca48a95f10c98bb817b6e780de481546" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_quant_iq_tables.h": { + "bytes": 110855, + "sha256": "bdee96a810ce7ceab6102025ea053ca7ecdb3caea5118727e02bbe69d7d784f7" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/CMakeLists.txt": { + "bytes": 275318, + "sha256": "45ee683859f89aa7c4c8d5ec253e46a0cf4d8de5eb33ac5f196c8fd413d3cba1" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/capi/rocm_quant_gather_fixture.h": { + "bytes": 8283, + "sha256": "339414f93e59e6be9a4ca545d5e762bb2816714343f466e218dbc2b69483bdfd" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/capi/test_rocm_embedding_quant.cpp": { + "bytes": 7710, + "sha256": "39ac4db3befafc27f7b986bf1691d6bde22448507f2c7e349b3235bed8e6aa01" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vllm/test_gguf_keep_quant.cpp": { + "bytes": 135199, + "sha256": "636d70c30cf28d7d3564874ac8195fda694da597998f44d53fee2df28f67820c" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vt/test_cuda_embedding_quant.cpp": { + "bytes": 23248, + "sha256": "ae4b5d161eda0e1c18b9534b640cfec467f4cc788fb84de4e4ffc95e8eece5f7" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vt/test_rocm_embedding_quant.cpp": { + "bytes": 17753, + "sha256": "e94888dbbaa772f643516dc532d1ea8400fb6741d65ba715f19dde04706e3023" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vllm/v1/worker/test_runner.cpp": { + "bytes": 176769, + "sha256": "8b70d78678245776737965cd461123b62716ed1d2cf130d604234e67519f09b2" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_runner": { + "bytes": 31530376, + "sha256": "e6d2d50be84e022817f0f9aaf54acd2c5196b9f1a50a2ec40a0e60acaed78b6e" + } + }, + "runs": [ + { + "name": "focused-and-rocm-regressions", + "argv": [ + "ctest", + "--test-dir", + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather", + "--output-on-failure", + "--verbose", + "-R", + "^(test_rocm_embedding_quant|test_capi_rocm_embedding_quant|test_gguf_keep_quant|test_ops_embedding_quant|test_gguf_dequant|test_backend_cross_device|test_gguf|test_rocm_arch|test_rocm_backend|test_rocm_fp8_kv_cache|test_ops_rocm_silu_rounding|test_exl3_rocm|test_gemma4_rocm_fp8_seams|test_backend_multidevice|test_runner)$" + ], + "env": { + "HIP_VISIBLE_DEVICES": "0", + "ROCR_VISIBLE_DEVICES": "0", + "TMPDIR": "/home/vikash/.cache/rdna3-gather-impl/tmp", + "VT_ROCM_GATHER_PUBLIC_EVIDENCE": "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures", + "VT_ROCM_GATHER_TEST_CORPUS": "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/random-corpus" + }, + "cwd": "/home/vikash/vllm.cpp-rdna3-gather-impl", + "log": "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/focused-and-regressions.log" + }, + { + "name": "required-ambient-device", + "argv": [ + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant", + "--test-case=ROCm gather follows the queue device when the ambient device differs", + "--abort-after=1" + ], + "env": { + "HIP_VISIBLE_DEVICES": "0,1", + "ROCR_VISIBLE_DEVICES": "0,1", + "TMPDIR": "/home/vikash/.cache/rdna3-gather-impl/tmp", + "VT_ROCM_GATHER_REQUIRE_TWO_DEVICES": "1" + }, + "cwd": "/home/vikash/vllm.cpp-rdna3-gather-impl", + "log": "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/ambient-device.log" + } + ], + "authority": "Only root operator runs GPU commands under its recorded mutex", + "expected": [ + "All15 CTests execute and pass; no CTest skip accepted", + "19codecs*2prompts*3fresh-engine repeats*2arms produces228 completions, each with4tokens and512 finite logits", + "All native quantized completions and repeatedruns match their same-binary dense controls exactly", + "Separate required2-device witness passes row selection,fullwidthbounds,and recovery after ambient1/queue0 switching" + ], + "build_logs": [ + "/home/vikash/.cache/rdna3-gather-impl/evidence/hip-final-clean-build.log", + "/home/vikash/.cache/rdna3-gather-impl/evidence/hip-runner-build.log" + ], + "dependency": "Imported78c7441bdspec+694f04525test as8c9101fa4/b46852d13; imported3files byteequal donor; gatherstagedfiles byteequal acrossimport" +} diff --git a/docs/bench-evidence/rocm-quant-gather/native-final-v4-operator-capture-audit.json b/docs/bench-evidence/rocm-quant-gather/native-final-v4-operator-capture-audit.json new file mode 100644 index 000000000..747a84943 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/native-final-v4-operator-capture-audit.json @@ -0,0 +1,470 @@ +{ + "result": "PASS", + "ctests_passed": 15, + "ctest_skips": 0, + "two_device_assertions": 16, + "public_engines": 228, + "completion_artifacts": 456, + "all_captures_byte_exact_vs_traced_v3": true, + "all_logits_finite": true, + "artifacts": { + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r0-p0-dense-logits-f32.bin": "a12eac02c8cb84a149c02e369eb4d29fa4ee4c89eeebaddeda5094c23ff5f2cb", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r0-p0-dense-tokens.txt": "9a7e87be2f90b2b51878e3424b3db457b410e5d5930fa22755d5534c1967cf08", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r0-p0-quant-logits-f32.bin": "a12eac02c8cb84a149c02e369eb4d29fa4ee4c89eeebaddeda5094c23ff5f2cb", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r0-p0-quant-tokens.txt": "9a7e87be2f90b2b51878e3424b3db457b410e5d5930fa22755d5534c1967cf08", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r0-p1-dense-logits-f32.bin": "d9850e483046535eee14e396c7321e91c4aa4e9fcd7ebc7a20336b6277152522", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r0-p1-dense-tokens.txt": "d7e6f2acae98af061483b4dd0722cbcf784e9683720ef4e509fb05574219d7bd", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r0-p1-quant-logits-f32.bin": "d9850e483046535eee14e396c7321e91c4aa4e9fcd7ebc7a20336b6277152522", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r0-p1-quant-tokens.txt": "d7e6f2acae98af061483b4dd0722cbcf784e9683720ef4e509fb05574219d7bd", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r1-p0-dense-logits-f32.bin": "a12eac02c8cb84a149c02e369eb4d29fa4ee4c89eeebaddeda5094c23ff5f2cb", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r1-p0-dense-tokens.txt": "9a7e87be2f90b2b51878e3424b3db457b410e5d5930fa22755d5534c1967cf08", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r1-p0-quant-logits-f32.bin": "a12eac02c8cb84a149c02e369eb4d29fa4ee4c89eeebaddeda5094c23ff5f2cb", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r1-p0-quant-tokens.txt": "9a7e87be2f90b2b51878e3424b3db457b410e5d5930fa22755d5534c1967cf08", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r1-p1-dense-logits-f32.bin": "d9850e483046535eee14e396c7321e91c4aa4e9fcd7ebc7a20336b6277152522", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r1-p1-dense-tokens.txt": "d7e6f2acae98af061483b4dd0722cbcf784e9683720ef4e509fb05574219d7bd", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r1-p1-quant-logits-f32.bin": "d9850e483046535eee14e396c7321e91c4aa4e9fcd7ebc7a20336b6277152522", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r1-p1-quant-tokens.txt": "d7e6f2acae98af061483b4dd0722cbcf784e9683720ef4e509fb05574219d7bd", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r2-p0-dense-logits-f32.bin": "a12eac02c8cb84a149c02e369eb4d29fa4ee4c89eeebaddeda5094c23ff5f2cb", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r2-p0-dense-tokens.txt": "9a7e87be2f90b2b51878e3424b3db457b410e5d5930fa22755d5534c1967cf08", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r2-p0-quant-logits-f32.bin": "a12eac02c8cb84a149c02e369eb4d29fa4ee4c89eeebaddeda5094c23ff5f2cb", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r2-p0-quant-tokens.txt": "9a7e87be2f90b2b51878e3424b3db457b410e5d5930fa22755d5534c1967cf08", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r2-p1-dense-logits-f32.bin": "d9850e483046535eee14e396c7321e91c4aa4e9fcd7ebc7a20336b6277152522", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r2-p1-dense-tokens.txt": "d7e6f2acae98af061483b4dd0722cbcf784e9683720ef4e509fb05574219d7bd", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r2-p1-quant-logits-f32.bin": "d9850e483046535eee14e396c7321e91c4aa4e9fcd7ebc7a20336b6277152522", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_S-r2-p1-quant-tokens.txt": "d7e6f2acae98af061483b4dd0722cbcf784e9683720ef4e509fb05574219d7bd", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r0-p0-dense-logits-f32.bin": "0fcf54423ce21a21cb3a7cd3d78416a09cff71c384209cacd47348347f4f00a4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r0-p0-dense-tokens.txt": "4f6b598fc3142001dd0d3a933236c33e84e8fc4d0aebdeee00f2ba561604f386", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r0-p0-quant-logits-f32.bin": "0fcf54423ce21a21cb3a7cd3d78416a09cff71c384209cacd47348347f4f00a4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r0-p0-quant-tokens.txt": "4f6b598fc3142001dd0d3a933236c33e84e8fc4d0aebdeee00f2ba561604f386", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r0-p1-dense-logits-f32.bin": "93569bd6ea15cbc8b61fd0f43bfc3ae89fc13d7e568dd47d497fbfe373e56d69", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r0-p1-dense-tokens.txt": "b4985b0433260dd2dbff82591a824a5daaef6afac7e83265573bc7c67b7d4baa", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r0-p1-quant-logits-f32.bin": "93569bd6ea15cbc8b61fd0f43bfc3ae89fc13d7e568dd47d497fbfe373e56d69", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r0-p1-quant-tokens.txt": "b4985b0433260dd2dbff82591a824a5daaef6afac7e83265573bc7c67b7d4baa", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r1-p0-dense-logits-f32.bin": "0fcf54423ce21a21cb3a7cd3d78416a09cff71c384209cacd47348347f4f00a4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r1-p0-dense-tokens.txt": "4f6b598fc3142001dd0d3a933236c33e84e8fc4d0aebdeee00f2ba561604f386", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r1-p0-quant-logits-f32.bin": "0fcf54423ce21a21cb3a7cd3d78416a09cff71c384209cacd47348347f4f00a4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r1-p0-quant-tokens.txt": "4f6b598fc3142001dd0d3a933236c33e84e8fc4d0aebdeee00f2ba561604f386", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r1-p1-dense-logits-f32.bin": "93569bd6ea15cbc8b61fd0f43bfc3ae89fc13d7e568dd47d497fbfe373e56d69", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r1-p1-dense-tokens.txt": "b4985b0433260dd2dbff82591a824a5daaef6afac7e83265573bc7c67b7d4baa", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r1-p1-quant-logits-f32.bin": "93569bd6ea15cbc8b61fd0f43bfc3ae89fc13d7e568dd47d497fbfe373e56d69", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r1-p1-quant-tokens.txt": "b4985b0433260dd2dbff82591a824a5daaef6afac7e83265573bc7c67b7d4baa", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r2-p0-dense-logits-f32.bin": "0fcf54423ce21a21cb3a7cd3d78416a09cff71c384209cacd47348347f4f00a4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r2-p0-dense-tokens.txt": "4f6b598fc3142001dd0d3a933236c33e84e8fc4d0aebdeee00f2ba561604f386", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r2-p0-quant-logits-f32.bin": "0fcf54423ce21a21cb3a7cd3d78416a09cff71c384209cacd47348347f4f00a4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r2-p0-quant-tokens.txt": "4f6b598fc3142001dd0d3a933236c33e84e8fc4d0aebdeee00f2ba561604f386", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r2-p1-dense-logits-f32.bin": "93569bd6ea15cbc8b61fd0f43bfc3ae89fc13d7e568dd47d497fbfe373e56d69", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r2-p1-dense-tokens.txt": "b4985b0433260dd2dbff82591a824a5daaef6afac7e83265573bc7c67b7d4baa", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r2-p1-quant-logits-f32.bin": "93569bd6ea15cbc8b61fd0f43bfc3ae89fc13d7e568dd47d497fbfe373e56d69", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ1_XXXS-r2-p1-quant-tokens.txt": "b4985b0433260dd2dbff82591a824a5daaef6afac7e83265573bc7c67b7d4baa", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r0-p0-dense-logits-f32.bin": "3a74972628df200ac04f4ce356f5f150f592e937fed7ea866f9125006c1999e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r0-p0-dense-tokens.txt": "875c78829fd811d7a96f406ddae171e8ab6f9da5d3abaf7a58fe1591ac37d09c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r0-p0-quant-logits-f32.bin": "3a74972628df200ac04f4ce356f5f150f592e937fed7ea866f9125006c1999e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r0-p0-quant-tokens.txt": "875c78829fd811d7a96f406ddae171e8ab6f9da5d3abaf7a58fe1591ac37d09c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r0-p1-dense-logits-f32.bin": "44d929b443672c840e4beaf127704b7ffc61ac84432b4198d6c001d8d8a606ca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r0-p1-dense-tokens.txt": "5a60ff63d8a76bd112296973a0d2347198187605b555bdaff55aca4709774f17", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r0-p1-quant-logits-f32.bin": "44d929b443672c840e4beaf127704b7ffc61ac84432b4198d6c001d8d8a606ca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r0-p1-quant-tokens.txt": "5a60ff63d8a76bd112296973a0d2347198187605b555bdaff55aca4709774f17", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r1-p0-dense-logits-f32.bin": "3a74972628df200ac04f4ce356f5f150f592e937fed7ea866f9125006c1999e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r1-p0-dense-tokens.txt": "875c78829fd811d7a96f406ddae171e8ab6f9da5d3abaf7a58fe1591ac37d09c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r1-p0-quant-logits-f32.bin": "3a74972628df200ac04f4ce356f5f150f592e937fed7ea866f9125006c1999e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r1-p0-quant-tokens.txt": "875c78829fd811d7a96f406ddae171e8ab6f9da5d3abaf7a58fe1591ac37d09c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r1-p1-dense-logits-f32.bin": "44d929b443672c840e4beaf127704b7ffc61ac84432b4198d6c001d8d8a606ca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r1-p1-dense-tokens.txt": "5a60ff63d8a76bd112296973a0d2347198187605b555bdaff55aca4709774f17", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r1-p1-quant-logits-f32.bin": "44d929b443672c840e4beaf127704b7ffc61ac84432b4198d6c001d8d8a606ca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r1-p1-quant-tokens.txt": "5a60ff63d8a76bd112296973a0d2347198187605b555bdaff55aca4709774f17", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r2-p0-dense-logits-f32.bin": "3a74972628df200ac04f4ce356f5f150f592e937fed7ea866f9125006c1999e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r2-p0-dense-tokens.txt": "875c78829fd811d7a96f406ddae171e8ab6f9da5d3abaf7a58fe1591ac37d09c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r2-p0-quant-logits-f32.bin": "3a74972628df200ac04f4ce356f5f150f592e937fed7ea866f9125006c1999e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r2-p0-quant-tokens.txt": "875c78829fd811d7a96f406ddae171e8ab6f9da5d3abaf7a58fe1591ac37d09c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r2-p1-dense-logits-f32.bin": "44d929b443672c840e4beaf127704b7ffc61ac84432b4198d6c001d8d8a606ca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r2-p1-dense-tokens.txt": "5a60ff63d8a76bd112296973a0d2347198187605b555bdaff55aca4709774f17", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r2-p1-quant-logits-f32.bin": "44d929b443672c840e4beaf127704b7ffc61ac84432b4198d6c001d8d8a606ca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_S-r2-p1-quant-tokens.txt": "5a60ff63d8a76bd112296973a0d2347198187605b555bdaff55aca4709774f17", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r0-p0-dense-logits-f32.bin": "36df7f97f56e8f060f479812f9886fbff833c71272afb286d63e0516f9e7f4b9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r0-p0-dense-tokens.txt": "f56786f89cb750e27989ce8fbe94c0fbe2979ff20b3ad9bca475de6077c019e4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r0-p0-quant-logits-f32.bin": "36df7f97f56e8f060f479812f9886fbff833c71272afb286d63e0516f9e7f4b9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r0-p0-quant-tokens.txt": "f56786f89cb750e27989ce8fbe94c0fbe2979ff20b3ad9bca475de6077c019e4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r0-p1-dense-logits-f32.bin": "548f8e0e2c754c3e0e84d5c69e907c7a506bae4f65942f66d48e454b1f4dc93c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r0-p1-dense-tokens.txt": "0d739dc6493c26f87bef42fa11ceca6d4070430e42edb7eab3131be2bc8d0d21", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r0-p1-quant-logits-f32.bin": "548f8e0e2c754c3e0e84d5c69e907c7a506bae4f65942f66d48e454b1f4dc93c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r0-p1-quant-tokens.txt": "0d739dc6493c26f87bef42fa11ceca6d4070430e42edb7eab3131be2bc8d0d21", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r1-p0-dense-logits-f32.bin": "36df7f97f56e8f060f479812f9886fbff833c71272afb286d63e0516f9e7f4b9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r1-p0-dense-tokens.txt": "f56786f89cb750e27989ce8fbe94c0fbe2979ff20b3ad9bca475de6077c019e4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r1-p0-quant-logits-f32.bin": "36df7f97f56e8f060f479812f9886fbff833c71272afb286d63e0516f9e7f4b9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r1-p0-quant-tokens.txt": "f56786f89cb750e27989ce8fbe94c0fbe2979ff20b3ad9bca475de6077c019e4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r1-p1-dense-logits-f32.bin": "548f8e0e2c754c3e0e84d5c69e907c7a506bae4f65942f66d48e454b1f4dc93c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r1-p1-dense-tokens.txt": "0d739dc6493c26f87bef42fa11ceca6d4070430e42edb7eab3131be2bc8d0d21", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r1-p1-quant-logits-f32.bin": "548f8e0e2c754c3e0e84d5c69e907c7a506bae4f65942f66d48e454b1f4dc93c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r1-p1-quant-tokens.txt": "0d739dc6493c26f87bef42fa11ceca6d4070430e42edb7eab3131be2bc8d0d21", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r2-p0-dense-logits-f32.bin": "36df7f97f56e8f060f479812f9886fbff833c71272afb286d63e0516f9e7f4b9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r2-p0-dense-tokens.txt": "f56786f89cb750e27989ce8fbe94c0fbe2979ff20b3ad9bca475de6077c019e4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r2-p0-quant-logits-f32.bin": "36df7f97f56e8f060f479812f9886fbff833c71272afb286d63e0516f9e7f4b9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r2-p0-quant-tokens.txt": "f56786f89cb750e27989ce8fbe94c0fbe2979ff20b3ad9bca475de6077c019e4", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r2-p1-dense-logits-f32.bin": "548f8e0e2c754c3e0e84d5c69e907c7a506bae4f65942f66d48e454b1f4dc93c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r2-p1-dense-tokens.txt": "0d739dc6493c26f87bef42fa11ceca6d4070430e42edb7eab3131be2bc8d0d21", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r2-p1-quant-logits-f32.bin": "548f8e0e2c754c3e0e84d5c69e907c7a506bae4f65942f66d48e454b1f4dc93c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XS-r2-p1-quant-tokens.txt": "0d739dc6493c26f87bef42fa11ceca6d4070430e42edb7eab3131be2bc8d0d21", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r0-p0-dense-logits-f32.bin": "f0d5fd5743bded857c178438485b67b8375bc0bb34c147399d5627a55432b65f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r0-p0-dense-tokens.txt": "58a2878ab37c154e1fe91e7e1bc12c7286ce7d49308111c694f74578a00bf005", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r0-p0-quant-logits-f32.bin": "f0d5fd5743bded857c178438485b67b8375bc0bb34c147399d5627a55432b65f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r0-p0-quant-tokens.txt": "58a2878ab37c154e1fe91e7e1bc12c7286ce7d49308111c694f74578a00bf005", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r0-p1-dense-logits-f32.bin": "eeeb557f78f3e6a475eccbc15a4da924b22df8f78e5be6a8d2705eeab9af5b79", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r0-p1-dense-tokens.txt": "54fbd51d02319038c7a63142ffa3181793eda4aa2fbb66b38a8015273cf5064c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r0-p1-quant-logits-f32.bin": "eeeb557f78f3e6a475eccbc15a4da924b22df8f78e5be6a8d2705eeab9af5b79", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r0-p1-quant-tokens.txt": "54fbd51d02319038c7a63142ffa3181793eda4aa2fbb66b38a8015273cf5064c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r1-p0-dense-logits-f32.bin": "f0d5fd5743bded857c178438485b67b8375bc0bb34c147399d5627a55432b65f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r1-p0-dense-tokens.txt": "58a2878ab37c154e1fe91e7e1bc12c7286ce7d49308111c694f74578a00bf005", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r1-p0-quant-logits-f32.bin": "f0d5fd5743bded857c178438485b67b8375bc0bb34c147399d5627a55432b65f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r1-p0-quant-tokens.txt": "58a2878ab37c154e1fe91e7e1bc12c7286ce7d49308111c694f74578a00bf005", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r1-p1-dense-logits-f32.bin": "eeeb557f78f3e6a475eccbc15a4da924b22df8f78e5be6a8d2705eeab9af5b79", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r1-p1-dense-tokens.txt": "54fbd51d02319038c7a63142ffa3181793eda4aa2fbb66b38a8015273cf5064c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r1-p1-quant-logits-f32.bin": "eeeb557f78f3e6a475eccbc15a4da924b22df8f78e5be6a8d2705eeab9af5b79", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r1-p1-quant-tokens.txt": "54fbd51d02319038c7a63142ffa3181793eda4aa2fbb66b38a8015273cf5064c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r2-p0-dense-logits-f32.bin": "f0d5fd5743bded857c178438485b67b8375bc0bb34c147399d5627a55432b65f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r2-p0-dense-tokens.txt": "58a2878ab37c154e1fe91e7e1bc12c7286ce7d49308111c694f74578a00bf005", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r2-p0-quant-logits-f32.bin": "f0d5fd5743bded857c178438485b67b8375bc0bb34c147399d5627a55432b65f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r2-p0-quant-tokens.txt": "58a2878ab37c154e1fe91e7e1bc12c7286ce7d49308111c694f74578a00bf005", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r2-p1-dense-logits-f32.bin": "eeeb557f78f3e6a475eccbc15a4da924b22df8f78e5be6a8d2705eeab9af5b79", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r2-p1-dense-tokens.txt": "54fbd51d02319038c7a63142ffa3181793eda4aa2fbb66b38a8015273cf5064c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r2-p1-quant-logits-f32.bin": "eeeb557f78f3e6a475eccbc15a4da924b22df8f78e5be6a8d2705eeab9af5b79", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ2_XXS-r2-p1-quant-tokens.txt": "54fbd51d02319038c7a63142ffa3181793eda4aa2fbb66b38a8015273cf5064c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r0-p0-dense-logits-f32.bin": "2bb6e26b95a8769c188508d6dce0af84836eed0549539c6a1411fecae31bdeca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r0-p0-dense-tokens.txt": "eec0fb4c95ed29a3f891875812aca630adf32ec6a766606e119966f24968f36e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r0-p0-quant-logits-f32.bin": "2bb6e26b95a8769c188508d6dce0af84836eed0549539c6a1411fecae31bdeca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r0-p0-quant-tokens.txt": "eec0fb4c95ed29a3f891875812aca630adf32ec6a766606e119966f24968f36e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r0-p1-dense-logits-f32.bin": "23ea09894c993dc9396570b3f478cbbcb1720910e9d59484913c0783874f8634", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r0-p1-dense-tokens.txt": "6ffc3fa9bde8b1ceb93084fd6935c87eb598f2dcbc82fedfe30ab49993cb752a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r0-p1-quant-logits-f32.bin": "23ea09894c993dc9396570b3f478cbbcb1720910e9d59484913c0783874f8634", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r0-p1-quant-tokens.txt": "6ffc3fa9bde8b1ceb93084fd6935c87eb598f2dcbc82fedfe30ab49993cb752a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r1-p0-dense-logits-f32.bin": "2bb6e26b95a8769c188508d6dce0af84836eed0549539c6a1411fecae31bdeca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r1-p0-dense-tokens.txt": "eec0fb4c95ed29a3f891875812aca630adf32ec6a766606e119966f24968f36e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r1-p0-quant-logits-f32.bin": "2bb6e26b95a8769c188508d6dce0af84836eed0549539c6a1411fecae31bdeca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r1-p0-quant-tokens.txt": "eec0fb4c95ed29a3f891875812aca630adf32ec6a766606e119966f24968f36e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r1-p1-dense-logits-f32.bin": "23ea09894c993dc9396570b3f478cbbcb1720910e9d59484913c0783874f8634", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r1-p1-dense-tokens.txt": "6ffc3fa9bde8b1ceb93084fd6935c87eb598f2dcbc82fedfe30ab49993cb752a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r1-p1-quant-logits-f32.bin": "23ea09894c993dc9396570b3f478cbbcb1720910e9d59484913c0783874f8634", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r1-p1-quant-tokens.txt": "6ffc3fa9bde8b1ceb93084fd6935c87eb598f2dcbc82fedfe30ab49993cb752a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r2-p0-dense-logits-f32.bin": "2bb6e26b95a8769c188508d6dce0af84836eed0549539c6a1411fecae31bdeca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r2-p0-dense-tokens.txt": "eec0fb4c95ed29a3f891875812aca630adf32ec6a766606e119966f24968f36e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r2-p0-quant-logits-f32.bin": "2bb6e26b95a8769c188508d6dce0af84836eed0549539c6a1411fecae31bdeca", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r2-p0-quant-tokens.txt": "eec0fb4c95ed29a3f891875812aca630adf32ec6a766606e119966f24968f36e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r2-p1-dense-logits-f32.bin": "23ea09894c993dc9396570b3f478cbbcb1720910e9d59484913c0783874f8634", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r2-p1-dense-tokens.txt": "6ffc3fa9bde8b1ceb93084fd6935c87eb598f2dcbc82fedfe30ab49993cb752a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r2-p1-quant-logits-f32.bin": "23ea09894c993dc9396570b3f478cbbcb1720910e9d59484913c0783874f8634", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_S-r2-p1-quant-tokens.txt": "6ffc3fa9bde8b1ceb93084fd6935c87eb598f2dcbc82fedfe30ab49993cb752a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r0-p0-dense-logits-f32.bin": "b768a528c46498035f34a3ac95cab600ba61f4d56cea952df5f6c3d27613b5e8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r0-p0-dense-tokens.txt": "4943727e005a07b88e1d3db4bc7abce36e199e114b454d2ec3d62d9faf60abe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r0-p0-quant-logits-f32.bin": "b768a528c46498035f34a3ac95cab600ba61f4d56cea952df5f6c3d27613b5e8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r0-p0-quant-tokens.txt": "4943727e005a07b88e1d3db4bc7abce36e199e114b454d2ec3d62d9faf60abe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r0-p1-dense-logits-f32.bin": "67846e04c1eaea0fe3852b28e2de589413806f458b1b4fe7195fd30dc619014e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r0-p1-dense-tokens.txt": "94a991cc39d4778e6ae402f021b9e5b60bb74c6d35371fdde93fa9293f467ed1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r0-p1-quant-logits-f32.bin": "67846e04c1eaea0fe3852b28e2de589413806f458b1b4fe7195fd30dc619014e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r0-p1-quant-tokens.txt": "94a991cc39d4778e6ae402f021b9e5b60bb74c6d35371fdde93fa9293f467ed1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r1-p0-dense-logits-f32.bin": "b768a528c46498035f34a3ac95cab600ba61f4d56cea952df5f6c3d27613b5e8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r1-p0-dense-tokens.txt": "4943727e005a07b88e1d3db4bc7abce36e199e114b454d2ec3d62d9faf60abe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r1-p0-quant-logits-f32.bin": "b768a528c46498035f34a3ac95cab600ba61f4d56cea952df5f6c3d27613b5e8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r1-p0-quant-tokens.txt": "4943727e005a07b88e1d3db4bc7abce36e199e114b454d2ec3d62d9faf60abe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r1-p1-dense-logits-f32.bin": "67846e04c1eaea0fe3852b28e2de589413806f458b1b4fe7195fd30dc619014e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r1-p1-dense-tokens.txt": "94a991cc39d4778e6ae402f021b9e5b60bb74c6d35371fdde93fa9293f467ed1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r1-p1-quant-logits-f32.bin": "67846e04c1eaea0fe3852b28e2de589413806f458b1b4fe7195fd30dc619014e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r1-p1-quant-tokens.txt": "94a991cc39d4778e6ae402f021b9e5b60bb74c6d35371fdde93fa9293f467ed1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r2-p0-dense-logits-f32.bin": "b768a528c46498035f34a3ac95cab600ba61f4d56cea952df5f6c3d27613b5e8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r2-p0-dense-tokens.txt": "4943727e005a07b88e1d3db4bc7abce36e199e114b454d2ec3d62d9faf60abe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r2-p0-quant-logits-f32.bin": "b768a528c46498035f34a3ac95cab600ba61f4d56cea952df5f6c3d27613b5e8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r2-p0-quant-tokens.txt": "4943727e005a07b88e1d3db4bc7abce36e199e114b454d2ec3d62d9faf60abe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r2-p1-dense-logits-f32.bin": "67846e04c1eaea0fe3852b28e2de589413806f458b1b4fe7195fd30dc619014e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r2-p1-dense-tokens.txt": "94a991cc39d4778e6ae402f021b9e5b60bb74c6d35371fdde93fa9293f467ed1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r2-p1-quant-logits-f32.bin": "67846e04c1eaea0fe3852b28e2de589413806f458b1b4fe7195fd30dc619014e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ3_XXS-r2-p1-quant-tokens.txt": "94a991cc39d4778e6ae402f021b9e5b60bb74c6d35371fdde93fa9293f467ed1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r0-p0-dense-logits-f32.bin": "9b403f07e9feb65f83b0172ca46b071149eb906af0e5d36a034597936d377140", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r0-p0-dense-tokens.txt": "22e18ce184d52df1b65612ccd102ad67da3a84a9113d0a44a024417af5bcfb96", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r0-p0-quant-logits-f32.bin": "9b403f07e9feb65f83b0172ca46b071149eb906af0e5d36a034597936d377140", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r0-p0-quant-tokens.txt": "22e18ce184d52df1b65612ccd102ad67da3a84a9113d0a44a024417af5bcfb96", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r0-p1-dense-logits-f32.bin": "9f126f54b75e1662b2f05dd3a27d7cd0f94cd0f5b1f613ef9981b8221b2c2473", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r0-p1-dense-tokens.txt": "a63747c494ced4489b012152ec3679571588809e20674b40827f5a874229ade0", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r0-p1-quant-logits-f32.bin": "9f126f54b75e1662b2f05dd3a27d7cd0f94cd0f5b1f613ef9981b8221b2c2473", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r0-p1-quant-tokens.txt": "a63747c494ced4489b012152ec3679571588809e20674b40827f5a874229ade0", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r1-p0-dense-logits-f32.bin": "9b403f07e9feb65f83b0172ca46b071149eb906af0e5d36a034597936d377140", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r1-p0-dense-tokens.txt": "22e18ce184d52df1b65612ccd102ad67da3a84a9113d0a44a024417af5bcfb96", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r1-p0-quant-logits-f32.bin": "9b403f07e9feb65f83b0172ca46b071149eb906af0e5d36a034597936d377140", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r1-p0-quant-tokens.txt": "22e18ce184d52df1b65612ccd102ad67da3a84a9113d0a44a024417af5bcfb96", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r1-p1-dense-logits-f32.bin": "9f126f54b75e1662b2f05dd3a27d7cd0f94cd0f5b1f613ef9981b8221b2c2473", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r1-p1-dense-tokens.txt": "a63747c494ced4489b012152ec3679571588809e20674b40827f5a874229ade0", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r1-p1-quant-logits-f32.bin": "9f126f54b75e1662b2f05dd3a27d7cd0f94cd0f5b1f613ef9981b8221b2c2473", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r1-p1-quant-tokens.txt": "a63747c494ced4489b012152ec3679571588809e20674b40827f5a874229ade0", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r2-p0-dense-logits-f32.bin": "9b403f07e9feb65f83b0172ca46b071149eb906af0e5d36a034597936d377140", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r2-p0-dense-tokens.txt": "22e18ce184d52df1b65612ccd102ad67da3a84a9113d0a44a024417af5bcfb96", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r2-p0-quant-logits-f32.bin": "9b403f07e9feb65f83b0172ca46b071149eb906af0e5d36a034597936d377140", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r2-p0-quant-tokens.txt": "22e18ce184d52df1b65612ccd102ad67da3a84a9113d0a44a024417af5bcfb96", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r2-p1-dense-logits-f32.bin": "9f126f54b75e1662b2f05dd3a27d7cd0f94cd0f5b1f613ef9981b8221b2c2473", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r2-p1-dense-tokens.txt": "a63747c494ced4489b012152ec3679571588809e20674b40827f5a874229ade0", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r2-p1-quant-logits-f32.bin": "9f126f54b75e1662b2f05dd3a27d7cd0f94cd0f5b1f613ef9981b8221b2c2473", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_NL-r2-p1-quant-tokens.txt": "a63747c494ced4489b012152ec3679571588809e20674b40827f5a874229ade0", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r0-p0-dense-logits-f32.bin": "bac4f07548c176f275a0269531759617db69c9eb17a773e001cc2e77b2346498", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r0-p0-dense-tokens.txt": "ef283a43caf4f8405f5e904413a57710312f4e12a336152f31109ed76574a44d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r0-p0-quant-logits-f32.bin": "bac4f07548c176f275a0269531759617db69c9eb17a773e001cc2e77b2346498", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r0-p0-quant-tokens.txt": "ef283a43caf4f8405f5e904413a57710312f4e12a336152f31109ed76574a44d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r0-p1-dense-logits-f32.bin": "ac2ec0e11ede8681b22e93e0cb81919d659188a560671b12e468d3b87f2a71a2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r0-p1-dense-tokens.txt": "d4369c9904e0f80f86964a593f74108543f9f76ff1817010ec007448a58ce8f5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r0-p1-quant-logits-f32.bin": "ac2ec0e11ede8681b22e93e0cb81919d659188a560671b12e468d3b87f2a71a2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r0-p1-quant-tokens.txt": "d4369c9904e0f80f86964a593f74108543f9f76ff1817010ec007448a58ce8f5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r1-p0-dense-logits-f32.bin": "bac4f07548c176f275a0269531759617db69c9eb17a773e001cc2e77b2346498", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r1-p0-dense-tokens.txt": "ef283a43caf4f8405f5e904413a57710312f4e12a336152f31109ed76574a44d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r1-p0-quant-logits-f32.bin": "bac4f07548c176f275a0269531759617db69c9eb17a773e001cc2e77b2346498", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r1-p0-quant-tokens.txt": "ef283a43caf4f8405f5e904413a57710312f4e12a336152f31109ed76574a44d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r1-p1-dense-logits-f32.bin": "ac2ec0e11ede8681b22e93e0cb81919d659188a560671b12e468d3b87f2a71a2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r1-p1-dense-tokens.txt": "d4369c9904e0f80f86964a593f74108543f9f76ff1817010ec007448a58ce8f5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r1-p1-quant-logits-f32.bin": "ac2ec0e11ede8681b22e93e0cb81919d659188a560671b12e468d3b87f2a71a2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r1-p1-quant-tokens.txt": "d4369c9904e0f80f86964a593f74108543f9f76ff1817010ec007448a58ce8f5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r2-p0-dense-logits-f32.bin": "bac4f07548c176f275a0269531759617db69c9eb17a773e001cc2e77b2346498", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r2-p0-dense-tokens.txt": "ef283a43caf4f8405f5e904413a57710312f4e12a336152f31109ed76574a44d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r2-p0-quant-logits-f32.bin": "bac4f07548c176f275a0269531759617db69c9eb17a773e001cc2e77b2346498", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r2-p0-quant-tokens.txt": "ef283a43caf4f8405f5e904413a57710312f4e12a336152f31109ed76574a44d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r2-p1-dense-logits-f32.bin": "ac2ec0e11ede8681b22e93e0cb81919d659188a560671b12e468d3b87f2a71a2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r2-p1-dense-tokens.txt": "d4369c9904e0f80f86964a593f74108543f9f76ff1817010ec007448a58ce8f5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r2-p1-quant-logits-f32.bin": "ac2ec0e11ede8681b22e93e0cb81919d659188a560671b12e468d3b87f2a71a2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/IQ4_XS-r2-p1-quant-tokens.txt": "d4369c9904e0f80f86964a593f74108543f9f76ff1817010ec007448a58ce8f5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r0-p0-dense-logits-f32.bin": "e33ea09097900b44138ae433200515096377bbd3357756f3db005eb2db9dd8d9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r0-p0-dense-tokens.txt": "64b38996e1f2c242ddb8d62371ea481ac25b14c58ef551059ca4088f795607fe", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r0-p0-quant-logits-f32.bin": "e33ea09097900b44138ae433200515096377bbd3357756f3db005eb2db9dd8d9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r0-p0-quant-tokens.txt": "64b38996e1f2c242ddb8d62371ea481ac25b14c58ef551059ca4088f795607fe", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r0-p1-dense-logits-f32.bin": "98fd81184c9f74af0c19eba787ae63a4d437b0ffc0b36c3c351a88c3e3187307", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r0-p1-dense-tokens.txt": "6c192a29861569bdc7b0a2bed1803e5182f7ec343ff07ef7bebe90e37e466219", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r0-p1-quant-logits-f32.bin": "98fd81184c9f74af0c19eba787ae63a4d437b0ffc0b36c3c351a88c3e3187307", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r0-p1-quant-tokens.txt": "6c192a29861569bdc7b0a2bed1803e5182f7ec343ff07ef7bebe90e37e466219", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r1-p0-dense-logits-f32.bin": "e33ea09097900b44138ae433200515096377bbd3357756f3db005eb2db9dd8d9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r1-p0-dense-tokens.txt": "64b38996e1f2c242ddb8d62371ea481ac25b14c58ef551059ca4088f795607fe", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r1-p0-quant-logits-f32.bin": "e33ea09097900b44138ae433200515096377bbd3357756f3db005eb2db9dd8d9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r1-p0-quant-tokens.txt": "64b38996e1f2c242ddb8d62371ea481ac25b14c58ef551059ca4088f795607fe", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r1-p1-dense-logits-f32.bin": "98fd81184c9f74af0c19eba787ae63a4d437b0ffc0b36c3c351a88c3e3187307", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r1-p1-dense-tokens.txt": "6c192a29861569bdc7b0a2bed1803e5182f7ec343ff07ef7bebe90e37e466219", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r1-p1-quant-logits-f32.bin": "98fd81184c9f74af0c19eba787ae63a4d437b0ffc0b36c3c351a88c3e3187307", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r1-p1-quant-tokens.txt": "6c192a29861569bdc7b0a2bed1803e5182f7ec343ff07ef7bebe90e37e466219", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r2-p0-dense-logits-f32.bin": "e33ea09097900b44138ae433200515096377bbd3357756f3db005eb2db9dd8d9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r2-p0-dense-tokens.txt": "64b38996e1f2c242ddb8d62371ea481ac25b14c58ef551059ca4088f795607fe", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r2-p0-quant-logits-f32.bin": "e33ea09097900b44138ae433200515096377bbd3357756f3db005eb2db9dd8d9", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r2-p0-quant-tokens.txt": "64b38996e1f2c242ddb8d62371ea481ac25b14c58ef551059ca4088f795607fe", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r2-p1-dense-logits-f32.bin": "98fd81184c9f74af0c19eba787ae63a4d437b0ffc0b36c3c351a88c3e3187307", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r2-p1-dense-tokens.txt": "6c192a29861569bdc7b0a2bed1803e5182f7ec343ff07ef7bebe90e37e466219", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r2-p1-quant-logits-f32.bin": "98fd81184c9f74af0c19eba787ae63a4d437b0ffc0b36c3c351a88c3e3187307", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/MXFP4-r2-p1-quant-tokens.txt": "6c192a29861569bdc7b0a2bed1803e5182f7ec343ff07ef7bebe90e37e466219", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r0-p0-dense-logits-f32.bin": "eb857003fdc2acab5e54ef4dfe66d2082a47bf48979956df07bb530b9b235eac", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r0-p0-dense-tokens.txt": "73c1682ca9381abc586e1250d23d462bd2f22a818f9c39e70d054d622f0db012", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r0-p0-quant-logits-f32.bin": "eb857003fdc2acab5e54ef4dfe66d2082a47bf48979956df07bb530b9b235eac", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r0-p0-quant-tokens.txt": "73c1682ca9381abc586e1250d23d462bd2f22a818f9c39e70d054d622f0db012", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r0-p1-dense-logits-f32.bin": "c0b6a4f54e05aa528ae7cc198985a5302163913cfdfaaae291d26b939989a10f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r0-p1-dense-tokens.txt": "f21e668e2d4c939025118a530d8921ff3efdc7f7e87f47a092811345a7cb5cfc", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r0-p1-quant-logits-f32.bin": "c0b6a4f54e05aa528ae7cc198985a5302163913cfdfaaae291d26b939989a10f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r0-p1-quant-tokens.txt": "f21e668e2d4c939025118a530d8921ff3efdc7f7e87f47a092811345a7cb5cfc", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r1-p0-dense-logits-f32.bin": "eb857003fdc2acab5e54ef4dfe66d2082a47bf48979956df07bb530b9b235eac", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r1-p0-dense-tokens.txt": "73c1682ca9381abc586e1250d23d462bd2f22a818f9c39e70d054d622f0db012", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r1-p0-quant-logits-f32.bin": "eb857003fdc2acab5e54ef4dfe66d2082a47bf48979956df07bb530b9b235eac", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r1-p0-quant-tokens.txt": "73c1682ca9381abc586e1250d23d462bd2f22a818f9c39e70d054d622f0db012", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r1-p1-dense-logits-f32.bin": "c0b6a4f54e05aa528ae7cc198985a5302163913cfdfaaae291d26b939989a10f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r1-p1-dense-tokens.txt": "f21e668e2d4c939025118a530d8921ff3efdc7f7e87f47a092811345a7cb5cfc", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r1-p1-quant-logits-f32.bin": "c0b6a4f54e05aa528ae7cc198985a5302163913cfdfaaae291d26b939989a10f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r1-p1-quant-tokens.txt": "f21e668e2d4c939025118a530d8921ff3efdc7f7e87f47a092811345a7cb5cfc", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r2-p0-dense-logits-f32.bin": "eb857003fdc2acab5e54ef4dfe66d2082a47bf48979956df07bb530b9b235eac", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r2-p0-dense-tokens.txt": "73c1682ca9381abc586e1250d23d462bd2f22a818f9c39e70d054d622f0db012", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r2-p0-quant-logits-f32.bin": "eb857003fdc2acab5e54ef4dfe66d2082a47bf48979956df07bb530b9b235eac", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r2-p0-quant-tokens.txt": "73c1682ca9381abc586e1250d23d462bd2f22a818f9c39e70d054d622f0db012", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r2-p1-dense-logits-f32.bin": "c0b6a4f54e05aa528ae7cc198985a5302163913cfdfaaae291d26b939989a10f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r2-p1-dense-tokens.txt": "f21e668e2d4c939025118a530d8921ff3efdc7f7e87f47a092811345a7cb5cfc", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r2-p1-quant-logits-f32.bin": "c0b6a4f54e05aa528ae7cc198985a5302163913cfdfaaae291d26b939989a10f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q2_K-r2-p1-quant-tokens.txt": "f21e668e2d4c939025118a530d8921ff3efdc7f7e87f47a092811345a7cb5cfc", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r0-p0-dense-logits-f32.bin": "a7ded008caba30e7ad44549a6399f7766dc66959abe3a0ba4d803ec47d39fc50", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r0-p0-dense-tokens.txt": "215b4d0bb3d0a2093449e92943f4a781e97cd390fe14532747df279fa19f5053", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r0-p0-quant-logits-f32.bin": "a7ded008caba30e7ad44549a6399f7766dc66959abe3a0ba4d803ec47d39fc50", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r0-p0-quant-tokens.txt": "215b4d0bb3d0a2093449e92943f4a781e97cd390fe14532747df279fa19f5053", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r0-p1-dense-logits-f32.bin": "68d1deb01a916a62f73c242ff0c8aa1fff22c9327bc2662b234faca6b647cfe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r0-p1-dense-tokens.txt": "8efd532e2ba609398099add4119a772f55deb5f8b43aee77b1c06ebf692c8a19", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r0-p1-quant-logits-f32.bin": "68d1deb01a916a62f73c242ff0c8aa1fff22c9327bc2662b234faca6b647cfe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r0-p1-quant-tokens.txt": "8efd532e2ba609398099add4119a772f55deb5f8b43aee77b1c06ebf692c8a19", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r1-p0-dense-logits-f32.bin": "a7ded008caba30e7ad44549a6399f7766dc66959abe3a0ba4d803ec47d39fc50", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r1-p0-dense-tokens.txt": "215b4d0bb3d0a2093449e92943f4a781e97cd390fe14532747df279fa19f5053", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r1-p0-quant-logits-f32.bin": "a7ded008caba30e7ad44549a6399f7766dc66959abe3a0ba4d803ec47d39fc50", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r1-p0-quant-tokens.txt": "215b4d0bb3d0a2093449e92943f4a781e97cd390fe14532747df279fa19f5053", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r1-p1-dense-logits-f32.bin": "68d1deb01a916a62f73c242ff0c8aa1fff22c9327bc2662b234faca6b647cfe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r1-p1-dense-tokens.txt": "8efd532e2ba609398099add4119a772f55deb5f8b43aee77b1c06ebf692c8a19", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r1-p1-quant-logits-f32.bin": "68d1deb01a916a62f73c242ff0c8aa1fff22c9327bc2662b234faca6b647cfe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r1-p1-quant-tokens.txt": "8efd532e2ba609398099add4119a772f55deb5f8b43aee77b1c06ebf692c8a19", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r2-p0-dense-logits-f32.bin": "a7ded008caba30e7ad44549a6399f7766dc66959abe3a0ba4d803ec47d39fc50", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r2-p0-dense-tokens.txt": "215b4d0bb3d0a2093449e92943f4a781e97cd390fe14532747df279fa19f5053", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r2-p0-quant-logits-f32.bin": "a7ded008caba30e7ad44549a6399f7766dc66959abe3a0ba4d803ec47d39fc50", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r2-p0-quant-tokens.txt": "215b4d0bb3d0a2093449e92943f4a781e97cd390fe14532747df279fa19f5053", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r2-p1-dense-logits-f32.bin": "68d1deb01a916a62f73c242ff0c8aa1fff22c9327bc2662b234faca6b647cfe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r2-p1-dense-tokens.txt": "8efd532e2ba609398099add4119a772f55deb5f8b43aee77b1c06ebf692c8a19", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r2-p1-quant-logits-f32.bin": "68d1deb01a916a62f73c242ff0c8aa1fff22c9327bc2662b234faca6b647cfe6", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q3_K-r2-p1-quant-tokens.txt": "8efd532e2ba609398099add4119a772f55deb5f8b43aee77b1c06ebf692c8a19", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r0-p0-dense-logits-f32.bin": "6a29993af6d6ca6fa96ae46168a2a440c5b55a714613b34054138928aa16c150", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r0-p0-dense-tokens.txt": "1a96f3b52d51bf85a5c2da89c0132bba345cfbe6822d28fde4df078bc2cfa91e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r0-p0-quant-logits-f32.bin": "6a29993af6d6ca6fa96ae46168a2a440c5b55a714613b34054138928aa16c150", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r0-p0-quant-tokens.txt": "1a96f3b52d51bf85a5c2da89c0132bba345cfbe6822d28fde4df078bc2cfa91e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r0-p1-dense-logits-f32.bin": "f2ddfbe1d64ce169916fcaaa4965f81dc1c8b259a062987c7caba5f66fafb101", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r0-p1-dense-tokens.txt": "22500293108517f09d87796a3f7dbd21fc2fe3dce64b8055561bb52bbe4c62e3", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r0-p1-quant-logits-f32.bin": "f2ddfbe1d64ce169916fcaaa4965f81dc1c8b259a062987c7caba5f66fafb101", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r0-p1-quant-tokens.txt": "22500293108517f09d87796a3f7dbd21fc2fe3dce64b8055561bb52bbe4c62e3", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r1-p0-dense-logits-f32.bin": "6a29993af6d6ca6fa96ae46168a2a440c5b55a714613b34054138928aa16c150", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r1-p0-dense-tokens.txt": "1a96f3b52d51bf85a5c2da89c0132bba345cfbe6822d28fde4df078bc2cfa91e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r1-p0-quant-logits-f32.bin": "6a29993af6d6ca6fa96ae46168a2a440c5b55a714613b34054138928aa16c150", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r1-p0-quant-tokens.txt": "1a96f3b52d51bf85a5c2da89c0132bba345cfbe6822d28fde4df078bc2cfa91e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r1-p1-dense-logits-f32.bin": "f2ddfbe1d64ce169916fcaaa4965f81dc1c8b259a062987c7caba5f66fafb101", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r1-p1-dense-tokens.txt": "22500293108517f09d87796a3f7dbd21fc2fe3dce64b8055561bb52bbe4c62e3", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r1-p1-quant-logits-f32.bin": "f2ddfbe1d64ce169916fcaaa4965f81dc1c8b259a062987c7caba5f66fafb101", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r1-p1-quant-tokens.txt": "22500293108517f09d87796a3f7dbd21fc2fe3dce64b8055561bb52bbe4c62e3", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r2-p0-dense-logits-f32.bin": "6a29993af6d6ca6fa96ae46168a2a440c5b55a714613b34054138928aa16c150", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r2-p0-dense-tokens.txt": "1a96f3b52d51bf85a5c2da89c0132bba345cfbe6822d28fde4df078bc2cfa91e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r2-p0-quant-logits-f32.bin": "6a29993af6d6ca6fa96ae46168a2a440c5b55a714613b34054138928aa16c150", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r2-p0-quant-tokens.txt": "1a96f3b52d51bf85a5c2da89c0132bba345cfbe6822d28fde4df078bc2cfa91e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r2-p1-dense-logits-f32.bin": "f2ddfbe1d64ce169916fcaaa4965f81dc1c8b259a062987c7caba5f66fafb101", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r2-p1-dense-tokens.txt": "22500293108517f09d87796a3f7dbd21fc2fe3dce64b8055561bb52bbe4c62e3", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r2-p1-quant-logits-f32.bin": "f2ddfbe1d64ce169916fcaaa4965f81dc1c8b259a062987c7caba5f66fafb101", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_0-r2-p1-quant-tokens.txt": "22500293108517f09d87796a3f7dbd21fc2fe3dce64b8055561bb52bbe4c62e3", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r0-p0-dense-logits-f32.bin": "ba7793887d37de36034092d2857b137937dd9e13c418f4f654c22399485fb1e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r0-p0-dense-tokens.txt": "90d2fcdc8e20f50bbd988f2d23ee2dd7eba08f1c420f12c993a5e0dbcd758208", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r0-p0-quant-logits-f32.bin": "ba7793887d37de36034092d2857b137937dd9e13c418f4f654c22399485fb1e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r0-p0-quant-tokens.txt": "90d2fcdc8e20f50bbd988f2d23ee2dd7eba08f1c420f12c993a5e0dbcd758208", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r0-p1-dense-logits-f32.bin": "1322e504646e3e15b283321eada9374f13a0828c974e7ca557eaf86633791818", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r0-p1-dense-tokens.txt": "ec0ebc3beeceeacf89c91be6151c16306b55412197d0f981606139853ee3741e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r0-p1-quant-logits-f32.bin": "1322e504646e3e15b283321eada9374f13a0828c974e7ca557eaf86633791818", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r0-p1-quant-tokens.txt": "ec0ebc3beeceeacf89c91be6151c16306b55412197d0f981606139853ee3741e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r1-p0-dense-logits-f32.bin": "ba7793887d37de36034092d2857b137937dd9e13c418f4f654c22399485fb1e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r1-p0-dense-tokens.txt": "90d2fcdc8e20f50bbd988f2d23ee2dd7eba08f1c420f12c993a5e0dbcd758208", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r1-p0-quant-logits-f32.bin": "ba7793887d37de36034092d2857b137937dd9e13c418f4f654c22399485fb1e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r1-p0-quant-tokens.txt": "90d2fcdc8e20f50bbd988f2d23ee2dd7eba08f1c420f12c993a5e0dbcd758208", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r1-p1-dense-logits-f32.bin": "1322e504646e3e15b283321eada9374f13a0828c974e7ca557eaf86633791818", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r1-p1-dense-tokens.txt": "ec0ebc3beeceeacf89c91be6151c16306b55412197d0f981606139853ee3741e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r1-p1-quant-logits-f32.bin": "1322e504646e3e15b283321eada9374f13a0828c974e7ca557eaf86633791818", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r1-p1-quant-tokens.txt": "ec0ebc3beeceeacf89c91be6151c16306b55412197d0f981606139853ee3741e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r2-p0-dense-logits-f32.bin": "ba7793887d37de36034092d2857b137937dd9e13c418f4f654c22399485fb1e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r2-p0-dense-tokens.txt": "90d2fcdc8e20f50bbd988f2d23ee2dd7eba08f1c420f12c993a5e0dbcd758208", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r2-p0-quant-logits-f32.bin": "ba7793887d37de36034092d2857b137937dd9e13c418f4f654c22399485fb1e5", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r2-p0-quant-tokens.txt": "90d2fcdc8e20f50bbd988f2d23ee2dd7eba08f1c420f12c993a5e0dbcd758208", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r2-p1-dense-logits-f32.bin": "1322e504646e3e15b283321eada9374f13a0828c974e7ca557eaf86633791818", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r2-p1-dense-tokens.txt": "ec0ebc3beeceeacf89c91be6151c16306b55412197d0f981606139853ee3741e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r2-p1-quant-logits-f32.bin": "1322e504646e3e15b283321eada9374f13a0828c974e7ca557eaf86633791818", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q4_K-r2-p1-quant-tokens.txt": "ec0ebc3beeceeacf89c91be6151c16306b55412197d0f981606139853ee3741e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r0-p0-dense-logits-f32.bin": "cf2ccd95a7b8375519261c639be7467e40203cafb3cde030bbafc5aef5963d2f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r0-p0-dense-tokens.txt": "427052e9db2f5e8f6eddfb6a98154c16eff216b251ba8f1840952fb7c7209637", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r0-p0-quant-logits-f32.bin": "cf2ccd95a7b8375519261c639be7467e40203cafb3cde030bbafc5aef5963d2f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r0-p0-quant-tokens.txt": "427052e9db2f5e8f6eddfb6a98154c16eff216b251ba8f1840952fb7c7209637", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r0-p1-dense-logits-f32.bin": "457e6c0d4286b64fb0dd97aabe20e4107be09dee93a09546ba0e7fa1cadffa6a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r0-p1-dense-tokens.txt": "e2b25d5e20be62588e06d09c515205068040405642be6ed02e2540fcc74b1f2c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r0-p1-quant-logits-f32.bin": "457e6c0d4286b64fb0dd97aabe20e4107be09dee93a09546ba0e7fa1cadffa6a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r0-p1-quant-tokens.txt": "e2b25d5e20be62588e06d09c515205068040405642be6ed02e2540fcc74b1f2c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r1-p0-dense-logits-f32.bin": "cf2ccd95a7b8375519261c639be7467e40203cafb3cde030bbafc5aef5963d2f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r1-p0-dense-tokens.txt": "427052e9db2f5e8f6eddfb6a98154c16eff216b251ba8f1840952fb7c7209637", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r1-p0-quant-logits-f32.bin": "cf2ccd95a7b8375519261c639be7467e40203cafb3cde030bbafc5aef5963d2f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r1-p0-quant-tokens.txt": "427052e9db2f5e8f6eddfb6a98154c16eff216b251ba8f1840952fb7c7209637", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r1-p1-dense-logits-f32.bin": "457e6c0d4286b64fb0dd97aabe20e4107be09dee93a09546ba0e7fa1cadffa6a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r1-p1-dense-tokens.txt": "e2b25d5e20be62588e06d09c515205068040405642be6ed02e2540fcc74b1f2c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r1-p1-quant-logits-f32.bin": "457e6c0d4286b64fb0dd97aabe20e4107be09dee93a09546ba0e7fa1cadffa6a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r1-p1-quant-tokens.txt": "e2b25d5e20be62588e06d09c515205068040405642be6ed02e2540fcc74b1f2c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r2-p0-dense-logits-f32.bin": "cf2ccd95a7b8375519261c639be7467e40203cafb3cde030bbafc5aef5963d2f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r2-p0-dense-tokens.txt": "427052e9db2f5e8f6eddfb6a98154c16eff216b251ba8f1840952fb7c7209637", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r2-p0-quant-logits-f32.bin": "cf2ccd95a7b8375519261c639be7467e40203cafb3cde030bbafc5aef5963d2f", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r2-p0-quant-tokens.txt": "427052e9db2f5e8f6eddfb6a98154c16eff216b251ba8f1840952fb7c7209637", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r2-p1-dense-logits-f32.bin": "457e6c0d4286b64fb0dd97aabe20e4107be09dee93a09546ba0e7fa1cadffa6a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r2-p1-dense-tokens.txt": "e2b25d5e20be62588e06d09c515205068040405642be6ed02e2540fcc74b1f2c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r2-p1-quant-logits-f32.bin": "457e6c0d4286b64fb0dd97aabe20e4107be09dee93a09546ba0e7fa1cadffa6a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_0-r2-p1-quant-tokens.txt": "e2b25d5e20be62588e06d09c515205068040405642be6ed02e2540fcc74b1f2c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r0-p0-dense-logits-f32.bin": "bf4285247160b2c71f5991b24a0fea641179b0165bb9793d53756252e714e1d2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r0-p0-dense-tokens.txt": "ec1982beff344ea4cf333e6232679cb7ca76428940bc61c051c1cf3cbec1163d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r0-p0-quant-logits-f32.bin": "bf4285247160b2c71f5991b24a0fea641179b0165bb9793d53756252e714e1d2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r0-p0-quant-tokens.txt": "ec1982beff344ea4cf333e6232679cb7ca76428940bc61c051c1cf3cbec1163d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r0-p1-dense-logits-f32.bin": "449c119478742aa639c1445fd367cb45b6c483cf23116725d7c761e5ca3a5945", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r0-p1-dense-tokens.txt": "89ec82c13f27a3a4b16da852d26341e7b93a1e3254b9bba9e408ee670f344528", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r0-p1-quant-logits-f32.bin": "449c119478742aa639c1445fd367cb45b6c483cf23116725d7c761e5ca3a5945", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r0-p1-quant-tokens.txt": "89ec82c13f27a3a4b16da852d26341e7b93a1e3254b9bba9e408ee670f344528", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r1-p0-dense-logits-f32.bin": "bf4285247160b2c71f5991b24a0fea641179b0165bb9793d53756252e714e1d2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r1-p0-dense-tokens.txt": "ec1982beff344ea4cf333e6232679cb7ca76428940bc61c051c1cf3cbec1163d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r1-p0-quant-logits-f32.bin": "bf4285247160b2c71f5991b24a0fea641179b0165bb9793d53756252e714e1d2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r1-p0-quant-tokens.txt": "ec1982beff344ea4cf333e6232679cb7ca76428940bc61c051c1cf3cbec1163d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r1-p1-dense-logits-f32.bin": "449c119478742aa639c1445fd367cb45b6c483cf23116725d7c761e5ca3a5945", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r1-p1-dense-tokens.txt": "89ec82c13f27a3a4b16da852d26341e7b93a1e3254b9bba9e408ee670f344528", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r1-p1-quant-logits-f32.bin": "449c119478742aa639c1445fd367cb45b6c483cf23116725d7c761e5ca3a5945", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r1-p1-quant-tokens.txt": "89ec82c13f27a3a4b16da852d26341e7b93a1e3254b9bba9e408ee670f344528", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r2-p0-dense-logits-f32.bin": "bf4285247160b2c71f5991b24a0fea641179b0165bb9793d53756252e714e1d2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r2-p0-dense-tokens.txt": "ec1982beff344ea4cf333e6232679cb7ca76428940bc61c051c1cf3cbec1163d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r2-p0-quant-logits-f32.bin": "bf4285247160b2c71f5991b24a0fea641179b0165bb9793d53756252e714e1d2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r2-p0-quant-tokens.txt": "ec1982beff344ea4cf333e6232679cb7ca76428940bc61c051c1cf3cbec1163d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r2-p1-dense-logits-f32.bin": "449c119478742aa639c1445fd367cb45b6c483cf23116725d7c761e5ca3a5945", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r2-p1-dense-tokens.txt": "89ec82c13f27a3a4b16da852d26341e7b93a1e3254b9bba9e408ee670f344528", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r2-p1-quant-logits-f32.bin": "449c119478742aa639c1445fd367cb45b6c483cf23116725d7c761e5ca3a5945", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q5_K-r2-p1-quant-tokens.txt": "89ec82c13f27a3a4b16da852d26341e7b93a1e3254b9bba9e408ee670f344528", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r0-p0-dense-logits-f32.bin": "753f7878a49cef082ff4b1077f944f345e1b7bf1c15e78e83f48ed2897f5b17e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r0-p0-dense-tokens.txt": "c4f67126f67de6cdba3146cbbeef84e1038d5a67ec2f89d10e1f45872723ec09", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r0-p0-quant-logits-f32.bin": "753f7878a49cef082ff4b1077f944f345e1b7bf1c15e78e83f48ed2897f5b17e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r0-p0-quant-tokens.txt": "c4f67126f67de6cdba3146cbbeef84e1038d5a67ec2f89d10e1f45872723ec09", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r0-p1-dense-logits-f32.bin": "7a6301766b7b20e272697e0b012a621230906944fdae62e8880bea21672c40c7", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r0-p1-dense-tokens.txt": "66a4cbd59120ab4ebc084cec015d9169567b98f55466834df7004d3c0c89a88d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r0-p1-quant-logits-f32.bin": "7a6301766b7b20e272697e0b012a621230906944fdae62e8880bea21672c40c7", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r0-p1-quant-tokens.txt": "66a4cbd59120ab4ebc084cec015d9169567b98f55466834df7004d3c0c89a88d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r1-p0-dense-logits-f32.bin": "753f7878a49cef082ff4b1077f944f345e1b7bf1c15e78e83f48ed2897f5b17e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r1-p0-dense-tokens.txt": "c4f67126f67de6cdba3146cbbeef84e1038d5a67ec2f89d10e1f45872723ec09", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r1-p0-quant-logits-f32.bin": "753f7878a49cef082ff4b1077f944f345e1b7bf1c15e78e83f48ed2897f5b17e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r1-p0-quant-tokens.txt": "c4f67126f67de6cdba3146cbbeef84e1038d5a67ec2f89d10e1f45872723ec09", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r1-p1-dense-logits-f32.bin": "7a6301766b7b20e272697e0b012a621230906944fdae62e8880bea21672c40c7", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r1-p1-dense-tokens.txt": "66a4cbd59120ab4ebc084cec015d9169567b98f55466834df7004d3c0c89a88d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r1-p1-quant-logits-f32.bin": "7a6301766b7b20e272697e0b012a621230906944fdae62e8880bea21672c40c7", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r1-p1-quant-tokens.txt": "66a4cbd59120ab4ebc084cec015d9169567b98f55466834df7004d3c0c89a88d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r2-p0-dense-logits-f32.bin": "753f7878a49cef082ff4b1077f944f345e1b7bf1c15e78e83f48ed2897f5b17e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r2-p0-dense-tokens.txt": "c4f67126f67de6cdba3146cbbeef84e1038d5a67ec2f89d10e1f45872723ec09", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r2-p0-quant-logits-f32.bin": "753f7878a49cef082ff4b1077f944f345e1b7bf1c15e78e83f48ed2897f5b17e", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r2-p0-quant-tokens.txt": "c4f67126f67de6cdba3146cbbeef84e1038d5a67ec2f89d10e1f45872723ec09", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r2-p1-dense-logits-f32.bin": "7a6301766b7b20e272697e0b012a621230906944fdae62e8880bea21672c40c7", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r2-p1-dense-tokens.txt": "66a4cbd59120ab4ebc084cec015d9169567b98f55466834df7004d3c0c89a88d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r2-p1-quant-logits-f32.bin": "7a6301766b7b20e272697e0b012a621230906944fdae62e8880bea21672c40c7", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q6_K-r2-p1-quant-tokens.txt": "66a4cbd59120ab4ebc084cec015d9169567b98f55466834df7004d3c0c89a88d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r0-p0-dense-logits-f32.bin": "0a531dd1fa8b88198108431c2b5b18b716c54c3ca21009988fdf3b124f8c8b34", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r0-p0-dense-tokens.txt": "57e1f1162073a7d35395c3bae7aae54353fcc138556583b8d13fb58eecab874d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r0-p0-quant-logits-f32.bin": "0a531dd1fa8b88198108431c2b5b18b716c54c3ca21009988fdf3b124f8c8b34", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r0-p0-quant-tokens.txt": "57e1f1162073a7d35395c3bae7aae54353fcc138556583b8d13fb58eecab874d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r0-p1-dense-logits-f32.bin": "66dc92bde7f36bfe38e063e65cb6839de5f8c6bc68fb8bb1b917a4973eaceb89", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r0-p1-dense-tokens.txt": "aa2f972d1e3e49df1d62c1d7826445b1e903c676cf99ba5ceb09260d73c0c06a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r0-p1-quant-logits-f32.bin": "66dc92bde7f36bfe38e063e65cb6839de5f8c6bc68fb8bb1b917a4973eaceb89", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r0-p1-quant-tokens.txt": "aa2f972d1e3e49df1d62c1d7826445b1e903c676cf99ba5ceb09260d73c0c06a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r1-p0-dense-logits-f32.bin": "0a531dd1fa8b88198108431c2b5b18b716c54c3ca21009988fdf3b124f8c8b34", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r1-p0-dense-tokens.txt": "57e1f1162073a7d35395c3bae7aae54353fcc138556583b8d13fb58eecab874d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r1-p0-quant-logits-f32.bin": "0a531dd1fa8b88198108431c2b5b18b716c54c3ca21009988fdf3b124f8c8b34", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r1-p0-quant-tokens.txt": "57e1f1162073a7d35395c3bae7aae54353fcc138556583b8d13fb58eecab874d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r1-p1-dense-logits-f32.bin": "66dc92bde7f36bfe38e063e65cb6839de5f8c6bc68fb8bb1b917a4973eaceb89", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r1-p1-dense-tokens.txt": "aa2f972d1e3e49df1d62c1d7826445b1e903c676cf99ba5ceb09260d73c0c06a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r1-p1-quant-logits-f32.bin": "66dc92bde7f36bfe38e063e65cb6839de5f8c6bc68fb8bb1b917a4973eaceb89", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r1-p1-quant-tokens.txt": "aa2f972d1e3e49df1d62c1d7826445b1e903c676cf99ba5ceb09260d73c0c06a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r2-p0-dense-logits-f32.bin": "0a531dd1fa8b88198108431c2b5b18b716c54c3ca21009988fdf3b124f8c8b34", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r2-p0-dense-tokens.txt": "57e1f1162073a7d35395c3bae7aae54353fcc138556583b8d13fb58eecab874d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r2-p0-quant-logits-f32.bin": "0a531dd1fa8b88198108431c2b5b18b716c54c3ca21009988fdf3b124f8c8b34", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r2-p0-quant-tokens.txt": "57e1f1162073a7d35395c3bae7aae54353fcc138556583b8d13fb58eecab874d", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r2-p1-dense-logits-f32.bin": "66dc92bde7f36bfe38e063e65cb6839de5f8c6bc68fb8bb1b917a4973eaceb89", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r2-p1-dense-tokens.txt": "aa2f972d1e3e49df1d62c1d7826445b1e903c676cf99ba5ceb09260d73c0c06a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r2-p1-quant-logits-f32.bin": "66dc92bde7f36bfe38e063e65cb6839de5f8c6bc68fb8bb1b917a4973eaceb89", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_0-r2-p1-quant-tokens.txt": "aa2f972d1e3e49df1d62c1d7826445b1e903c676cf99ba5ceb09260d73c0c06a", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r0-p0-dense-logits-f32.bin": "68d9adf067366233488d694005a9a12d4dc24f1cf7f8d2e2d99037836a7623c2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r0-p0-dense-tokens.txt": "0e6d7a84c0e87f20a39e21f1e53934d4f181853528a5790bf913310a04f867b1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r0-p0-quant-logits-f32.bin": "68d9adf067366233488d694005a9a12d4dc24f1cf7f8d2e2d99037836a7623c2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r0-p0-quant-tokens.txt": "0e6d7a84c0e87f20a39e21f1e53934d4f181853528a5790bf913310a04f867b1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r0-p1-dense-logits-f32.bin": "f529263c252e85898137bc6bd682e77a0f8c17e35f051d81b6234537a3ab63c8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r0-p1-dense-tokens.txt": "aad9614465f58ebdd11b2a41a463dfcdba65061f548a10f6d97f2d72d60dc49c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r0-p1-quant-logits-f32.bin": "f529263c252e85898137bc6bd682e77a0f8c17e35f051d81b6234537a3ab63c8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r0-p1-quant-tokens.txt": "aad9614465f58ebdd11b2a41a463dfcdba65061f548a10f6d97f2d72d60dc49c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r1-p0-dense-logits-f32.bin": "68d9adf067366233488d694005a9a12d4dc24f1cf7f8d2e2d99037836a7623c2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r1-p0-dense-tokens.txt": "0e6d7a84c0e87f20a39e21f1e53934d4f181853528a5790bf913310a04f867b1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r1-p0-quant-logits-f32.bin": "68d9adf067366233488d694005a9a12d4dc24f1cf7f8d2e2d99037836a7623c2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r1-p0-quant-tokens.txt": "0e6d7a84c0e87f20a39e21f1e53934d4f181853528a5790bf913310a04f867b1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r1-p1-dense-logits-f32.bin": "f529263c252e85898137bc6bd682e77a0f8c17e35f051d81b6234537a3ab63c8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r1-p1-dense-tokens.txt": "aad9614465f58ebdd11b2a41a463dfcdba65061f548a10f6d97f2d72d60dc49c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r1-p1-quant-logits-f32.bin": "f529263c252e85898137bc6bd682e77a0f8c17e35f051d81b6234537a3ab63c8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r1-p1-quant-tokens.txt": "aad9614465f58ebdd11b2a41a463dfcdba65061f548a10f6d97f2d72d60dc49c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r2-p0-dense-logits-f32.bin": "68d9adf067366233488d694005a9a12d4dc24f1cf7f8d2e2d99037836a7623c2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r2-p0-dense-tokens.txt": "0e6d7a84c0e87f20a39e21f1e53934d4f181853528a5790bf913310a04f867b1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r2-p0-quant-logits-f32.bin": "68d9adf067366233488d694005a9a12d4dc24f1cf7f8d2e2d99037836a7623c2", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r2-p0-quant-tokens.txt": "0e6d7a84c0e87f20a39e21f1e53934d4f181853528a5790bf913310a04f867b1", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r2-p1-dense-logits-f32.bin": "f529263c252e85898137bc6bd682e77a0f8c17e35f051d81b6234537a3ab63c8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r2-p1-dense-tokens.txt": "aad9614465f58ebdd11b2a41a463dfcdba65061f548a10f6d97f2d72d60dc49c", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r2-p1-quant-logits-f32.bin": "f529263c252e85898137bc6bd682e77a0f8c17e35f051d81b6234537a3ab63c8", + "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures/Q8_K-r2-p1-quant-tokens.txt": "aad9614465f58ebdd11b2a41a463dfcdba65061f548a10f6d97f2d72d60dc49c" + }, + "focused_log_sha256": "655a9a16c07f8c9300e36fff4482106d91868935952efe2cc9dc5ef53ba7816f", + "ambient_log_sha256": "38fec7edbc44a0e557538088a130e98da012892fdec43f29234989d35718209e" +} diff --git a/docs/bench-evidence/rocm-quant-gather/native-final-v4-operator-results.json b/docs/bench-evidence/rocm-quant-gather/native-final-v4-operator-results.json new file mode 100644 index 000000000..63c0b4d53 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/native-final-v4-operator-results.json @@ -0,0 +1,53 @@ +[ + { + "name": "focused-and-rocm-regressions", + "argv": [ + "flock", + "-n", + "-F", + "/home/vikash/gpu.lock", + "ctest", + "--test-dir", + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather", + "--output-on-failure", + "--verbose", + "-R", + "^(test_rocm_embedding_quant|test_capi_rocm_embedding_quant|test_gguf_keep_quant|test_ops_embedding_quant|test_gguf_dequant|test_backend_cross_device|test_gguf|test_rocm_arch|test_rocm_backend|test_rocm_fp8_kv_cache|test_ops_rocm_silu_rounding|test_exl3_rocm|test_gemma4_rocm_fp8_seams|test_backend_multidevice|test_runner)$" + ], + "env": { + "HIP_VISIBLE_DEVICES": "0", + "ROCR_VISIBLE_DEVICES": "0", + "TMPDIR": "/home/vikash/.cache/rdna3-gather-impl/tmp", + "VT_ROCM_GATHER_PUBLIC_EVIDENCE": "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/public-captures", + "VT_ROCM_GATHER_TEST_CORPUS": "/home/vikash/.cache/rdna3-gather-impl/native-final-v4/random-corpus" + }, + "cwd": "/home/vikash/vllm.cpp-rdna3-gather-impl", + "exit": 0, + "seconds": 25.545061588287354, + "log_sha256": "655a9a16c07f8c9300e36fff4482106d91868935952efe2cc9dc5ef53ba7816f", + "inputs_unchanged": true + }, + { + "name": "required-ambient-device", + "argv": [ + "flock", + "-n", + "-F", + "/home/vikash/gpu.lock", + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant", + "--test-case=ROCm gather follows the queue device when the ambient device differs", + "--abort-after=1" + ], + "env": { + "HIP_VISIBLE_DEVICES": "0,1", + "ROCR_VISIBLE_DEVICES": "0,1", + "TMPDIR": "/home/vikash/.cache/rdna3-gather-impl/tmp", + "VT_ROCM_GATHER_REQUIRE_TWO_DEVICES": "1" + }, + "cwd": "/home/vikash/vllm.cpp-rdna3-gather-impl", + "exit": 0, + "seconds": 0.7371315956115723, + "log_sha256": "38fec7edbc44a0e557538088a130e98da012892fdec43f29234989d35718209e", + "inputs_unchanged": true + } +] diff --git a/docs/bench-evidence/rocm-quant-gather/native-focused-v1.json b/docs/bench-evidence/rocm-quant-gather/native-focused-v1.json new file mode 100644 index 000000000..7b2451913 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/native-focused-v1.json @@ -0,0 +1,101 @@ +{ + "version": 1, + "row": "BACKEND-ROCM-QUANT-GATHER", + "base_head": "4fc300f93cfb075c0afddccdd476a552fa900cdb", + "uncommitted_native_implementation": true, + "files": { + "/home/vikash/vllm.cpp-rdna3-gather-impl/CMakeLists.txt": { + "bytes": 175502, + "sha256": "e5bea1baa842ac0257fb29d61cb6ef37977d975d6ac0478f81d6e677fe85ce32" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/CMakeLists.txt": { + "bytes": 275052, + "sha256": "efb00054342fdaec87e9181495ffdf5abd55257d8545b829b69f13ff8dbc93dc" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/libvllm.a": { + "bytes": 95078500, + "sha256": "acbf7ceb5c2efa04ff56189e04de549ebe760ba70f3d7967f684f2e7709431cb" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_embedding_quant.hip": { + "bytes": 7556, + "sha256": "5934d1727c96ec8e76f4e7dc3805e15d271fb528b7c0ad6c3a5d2863a179686b" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_quant_iq_tables.h": { + "bytes": 110865, + "sha256": "d267d25ff1dd3f67749c251f87047f4b70c9650a99d04b524ff6c3313596a349" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_embedding_quant.h": { + "bytes": 554, + "sha256": "1b2b31617d660b64f622e692089423ce1657df102322558a4ab731f521952bc5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_quant_dequant.h": { + "bytes": 25507, + "sha256": "413dc138254cc72f8dccbc87268581217c93dec8f8acaea159f3f39569c37e62" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_ops.hip": { + "bytes": 22703, + "sha256": "650a7d033b3ce3fc7a6c9a2e6bcfa80963c172ad5ef58421e2956892aac80935" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/capi/rocm_quant_gather_fixture.h": { + "bytes": 8283, + "sha256": "339414f93e59e6be9a4ca545d5e762bb2816714343f466e218dbc2b69483bdfd" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/capi/test_rocm_embedding_quant.cpp": { + "bytes": 6592, + "sha256": "334164dbb5c767dd0c67fa554931b41465385f41ab3c522f21f669b34a4884aa" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vt/test_rocm_embedding_quant.cpp": { + "bytes": 14781, + "sha256": "cb8bad70113bc1730ae1f9aafba4fd26b84601ff28f3c33f979be2d9d964b367" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vllm/test_gguf_keep_quant.cpp": { + "bytes": 132629, + "sha256": "5168816c430f1a07dcf7e0790dc5b6ab2cf4a1498c61383b6b693411578bc5f7" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant": { + "bytes": 30942784, + "sha256": "76420ee7836c7265d2709ab7910c1ed3b4abf94f44c28b3a1da747caf39f9134" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_capi_rocm_embedding_quant": { + "bytes": 30929264, + "sha256": "49e47dae389dc4b3f150837ab743eea3c8e74d815dfaf341e43ec083ae0a2ce4" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf_keep_quant": { + "bytes": 31321648, + "sha256": "cc70d1a966c32d6127c043e5cb2417c4852b4c5197399e75edf80339ea6921d6" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_ops_embedding_quant": { + "bytes": 30845880, + "sha256": "550044a9cd421c872770e6fd84b44d0fb9b749297a58baf5c598d7f244642585" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf_dequant": { + "bytes": 30962624, + "sha256": "7fc76b76f5984314b707fa9256b4cfba82bab3bc0473d3df052734597cc09bd1" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_backend_cross_device": { + "bytes": 31469712, + "sha256": "c6b1500af691d1c021ea7a642df838c03b03cc1da2c7bbb0a0f393ea74b64615" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/rocm_quant_gather_capture": { + "bytes": 30693800, + "sha256": "af71f0a1583a1e970f6a9c5b6ff39e1c2d39424770dd8700911a9ff00b48d411" + } + }, + "cwd": "/home/vikash/vllm.cpp-rdna3-gather-impl", + "env": { + "HIP_VISIBLE_DEVICES": "0", + "ROCR_VISIBLE_DEVICES": "0", + "TMPDIR": "/home/vikash/.cache/rdna3-gather-impl/tmp" + }, + "argv": [ + "ctest", + "--test-dir", + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather", + "--output-on-failure", + "-R", + "^(test_rocm_embedding_quant|test_capi_rocm_embedding_quant|test_gguf_keep_quant|test_ops_embedding_quant|test_gguf_dequant|test_backend_cross_device)$" + ], + "log": "/home/vikash/.cache/rdna3-gather-impl/evidence/native-focused-v1.log", + "authority": "Operator alone executes under the recorded GPU 0 mutex", + "expected": "All six targets execute and pass. No exit-77 skip satisfies the native acceptance run." +} diff --git a/docs/bench-evidence/rocm-quant-gather/native-focused-v2-operator-results.json b/docs/bench-evidence/rocm-quant-gather/native-focused-v2-operator-results.json new file mode 100644 index 000000000..749a3bbde --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/native-focused-v2-operator-results.json @@ -0,0 +1,88 @@ +[ + { + "name": "focused-v2", + "argv": [ + "flock", + "-n", + "-F", + "/home/vikash/gpu.lock", + "env", + "HIP_VISIBLE_DEVICES=0", + "ROCR_VISIBLE_DEVICES=0", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "VT_ROCM_GATHER_TEST_CORPUS=/home/vikash/.cache/rdna3-gather-impl/random-corpus-v2", + "timeout", + "180s", + "ctest", + "--test-dir", + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather", + "--output-on-failure", + "-R", + "^(test_rocm_embedding_quant|test_capi_rocm_embedding_quant|test_gguf_keep_quant|test_ops_embedding_quant|test_gguf_dequant|test_backend_cross_device|test_gguf)$" + ], + "exit_code": 0, + "elapsed_seconds": 21.807591438293457, + "manifest_sha256": "2928aa6cbc417a3993c86481cbdd6c3ba4e35072bbf703212976344bda57fed0", + "log_sha256": "90498bb132e941140e153a2634e8247c46faebad08172205cfed52806d612ca1", + "all_101_manifest_inputs_verified_before_after": true, + "core_dumps_disabled": true, + "summary": [ + "100% tests passed, 0 tests failed out of 7" + ] + }, + { + "name": "ambient-device-v2", + "argv": [ + "flock", + "-n", + "-F", + "/home/vikash/gpu.lock", + "env", + "HIP_VISIBLE_DEVICES=0,1", + "ROCR_VISIBLE_DEVICES=0,1", + "VT_ROCM_GATHER_REQUIRE_TWO_DEVICES=1", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "timeout", + "180s", + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant", + "--test-case=ROCm gather follows the queue device when the ambient device differs", + "--abort-after=1" + ], + "exit_code": 0, + "elapsed_seconds": 0.5165746212005615, + "manifest_sha256": "2928aa6cbc417a3993c86481cbdd6c3ba4e35072bbf703212976344bda57fed0", + "log_sha256": "38fec7edbc44a0e557538088a130e98da012892fdec43f29234989d35718209e", + "all_101_manifest_inputs_verified_before_after": true, + "core_dumps_disabled": true, + "summary": [ + "[doctest] test cases: 1 | 1 passed | 0 failed | 8 skipped", + "[doctest] assertions: 16 | 16 passed | 0 failed |" + ] + }, + { + "name": "native-corpus-v2", + "argv": [ + "flock", + "-n", + "-F", + "/home/vikash/gpu.lock", + "env", + "HIP_VISIBLE_DEVICES=0", + "ROCR_VISIBLE_DEVICES=0", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "timeout", + "180s", + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/rocm_quant_gather_capture", + "capture", + "/home/vikash/.cache/rdna3-gather-impl/corpus/manifest.json", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2" + ], + "exit_code": 0, + "elapsed_seconds": 0.853466272354126, + "manifest_sha256": "2928aa6cbc417a3993c86481cbdd6c3ba4e35072bbf703212976344bda57fed0", + "log_sha256": "d28f0be34a2c630d52fc5096a805c200d04397f36517e47d186c0cfbfe2a604f", + "all_101_manifest_inputs_verified_before_after": true, + "core_dumps_disabled": true, + "summary": [] + } +] diff --git a/docs/bench-evidence/rocm-quant-gather/native-focused-v2.json b/docs/bench-evidence/rocm-quant-gather/native-focused-v2.json new file mode 100644 index 000000000..7fd790dc2 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/native-focused-v2.json @@ -0,0 +1,464 @@ +{ + "version": 2, + "row": "BACKEND-ROCM-QUANT-GATHER", + "base_head": "2e5adfb85a255528bffa5d3cdb016efb2bab70d8", + "uncommitted_native_implementation": true, + "files": { + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_S-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_S-1024.packed": { + "bytes": 25600, + "sha256": "6bf00a4b02da43e5505823b12d9e368aa1ded7f87427eea02ec03ebc68288c33" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_S-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_S-256.packed": { + "bytes": 6400, + "sha256": "754f0d0b9e7d3656a1f669cf756779352cccb246bf6aa0b25e7f362180cf0882" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_XXXS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_XXXS-1024.packed": { + "bytes": 19456, + "sha256": "ae8e061519977e2ba7a77ae9d30e21193b1a009b5ed38739974e945de09b94c6" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_XXXS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_XXXS-256.packed": { + "bytes": 4864, + "sha256": "af0b5e336987746fd49cd33c790b99eb1479c26f64b6679fa6c685e5934ba0c4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_S-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_S-1024.packed": { + "bytes": 41984, + "sha256": "2cc5c79aef24da7bb363c72b7ac91f05c38b87fdc96627253203926f4465d73e" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_S-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_S-256.packed": { + "bytes": 10496, + "sha256": "6eb1966662d9e424fefc5c3625282e7f33fdfab3af9cb4c0cbac6bdc593711ea" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XS-1024.packed": { + "bytes": 37888, + "sha256": "8fbc716e220d386b0c27f1cca003384091cd0e522c1442656677af4ac780de5f" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XS-256.packed": { + "bytes": 9472, + "sha256": "3281c7397dde054ea6c9c8a661cab43dbd0c982eb23b9a31523a616565c827e7" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XXS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XXS-1024.packed": { + "bytes": 33792, + "sha256": "2fbe6e6ffcbc32fda24c5d63d4a4b678283e2bd571f491210097a27b88cc1fd4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XXS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XXS-256.packed": { + "bytes": 8448, + "sha256": "4a3c10afb47315763ce507edcb5814e06d1be93a21b178cf73183302a3f1ceb9" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_S-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_S-1024.packed": { + "bytes": 56320, + "sha256": "a94d30560f904618cead2f0618aea6455d5183eb3ed443ca5c12e48fe5b31b34" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_S-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_S-256.packed": { + "bytes": 14080, + "sha256": "d4eebe1369e21b0efd6ec5c89f54c785849c02edde957ebd302dad376f63c14c" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_XXS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_XXS-1024.packed": { + "bytes": 50176, + "sha256": "2d3a0d835fe7a47d802b59e8e412e4084de78faa2aaca59d1ce565fad11ac34a" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_XXS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_XXS-256.packed": { + "bytes": 12544, + "sha256": "d0f775f8e88d87ae542de6d16122a7a1cea09ebba91203f6513b74727082b6db" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_NL-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_NL-1024.packed": { + "bytes": 73728, + "sha256": "4e50d50e97e08c448cfff4fbed121ef24d657cfd30c2e09f66e70c647ce545b1" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_NL-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_NL-256.packed": { + "bytes": 18432, + "sha256": "cd292582c61c4b4b89606c85a80a6bb6ed8af98503a4d2f3737e02ae4e711d19" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_XS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_XS-1024.packed": { + "bytes": 69632, + "sha256": "189f75d03197100afafd3fe92183e47a2d73665d64f89b36d8b10daa05adf2c4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_XS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_XS-256.packed": { + "bytes": 17408, + "sha256": "35b2a41e738a6cb0a86deb4fd366f71ae2dc2a6fad7169f5a9afb53f523e919c" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/MXFP4-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/MXFP4-1024.packed": { + "bytes": 69632, + "sha256": "929ef7d789f210f60cede40156f689734aaf36519cd1f43a82d44d17ae0adfb4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/MXFP4-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/MXFP4-256.packed": { + "bytes": 17408, + "sha256": "baa828a753cc6f496f356271dad644976cd57d1218517e3f641fe56b7ec8db4a" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q2_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q2_K-1024.packed": { + "bytes": 43008, + "sha256": "58cb93e09423c7151fac47084de7e38bff98f51e5f304de243b41a17c47ac4af" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q2_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q2_K-256.packed": { + "bytes": 10752, + "sha256": "655f77ebb32d974da7907da4a217c45bbbcd0b127df73a731f85afe427bb7dcc" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q3_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q3_K-1024.packed": { + "bytes": 56320, + "sha256": "6118b4b2f10678fb09a2cb3324d69443ff3b33805f403b79ed3432d5bc1b2732" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q3_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q3_K-256.packed": { + "bytes": 14080, + "sha256": "e4c3a11c1bbff806ae2729033910b7db606452d1b9aa499aa2ced46740ad85d4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_0-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_0-1024.packed": { + "bytes": 73728, + "sha256": "4e50d50e97e08c448cfff4fbed121ef24d657cfd30c2e09f66e70c647ce545b1" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_0-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_0-256.packed": { + "bytes": 18432, + "sha256": "cd292582c61c4b4b89606c85a80a6bb6ed8af98503a4d2f3737e02ae4e711d19" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_K-1024.packed": { + "bytes": 73728, + "sha256": "d15d1bb953010f1ecdac424a54c365308e3b058a1b818bafb89cfc9b9b1678cc" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_K-256.packed": { + "bytes": 18432, + "sha256": "b0c107c4b353e2a169247e0406c1eb015d7a6d97edd5906f710868b8c2cecce1" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_0-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_0-1024.packed": { + "bytes": 90112, + "sha256": "b1d241ee00677d6d55a5e774916608aa4479e6c549d8ed1e4803c0938cd6a855" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_0-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_0-256.packed": { + "bytes": 22528, + "sha256": "b3531b1abd263bc4c6a3174b22fa1fd54a4b89b66e737f2eb3ba36be771d7528" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_K-1024.packed": { + "bytes": 90112, + "sha256": "6dd54fbc62a9818334e50347fe185247156ecc833a5655ce1920651a4dc537b5" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_K-256.packed": { + "bytes": 22528, + "sha256": "5e63d961f36486c9636dd2657e9069bd83ece65e466c56c657265fbd97353b07" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q6_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q6_K-1024.packed": { + "bytes": 107520, + "sha256": "2487007668582b61b3c59fdbaf0e92c2f5c74a61781daba95c13704983643ab1" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q6_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q6_K-256.packed": { + "bytes": 26880, + "sha256": "134bba0f8076d43d31fcbbaeb37c3d8191b0d383e6595f787d3387e2e016738a" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_0-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_0-1024.packed": { + "bytes": 139264, + "sha256": "c4435564bf5fd2dc23e0c78107f28ebd033ec741c417d41fa9dcbd89dd2909ba" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_0-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_0-256.packed": { + "bytes": 34816, + "sha256": "8be599e194405f9b5429e578a03a5717e4d78f53ab4c9c11a52659495ce805ee" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_K-1024.packed": { + "bytes": 149504, + "sha256": "78e39e7ef7317d842a6fd965b356ceb1959a5ce03da824fbc699689ea2ef4877" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_K-256.packed": { + "bytes": 37376, + "sha256": "bcf6f6691a787fe3f2a9bcc3d7923eeb4953862c30f904a6b10fc07410f8d657" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/manifest.json": { + "bytes": 6329, + "sha256": "78bc808e19b40ea745f5e767b72618dbd8087bb685333345826257dd4371ccfd" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/CMakeLists.txt": { + "bytes": 175502, + "sha256": "e5bea1baa842ac0257fb29d61cb6ef37977d975d6ac0478f81d6e677fe85ce32" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/libvllm.a": { + "bytes": 95078032, + "sha256": "e1e56ec9535a7501a8313986861dfa7bed3fde35f50dbdbc3ba05c4aac7b1afa" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/rocm_quant_gather_capture": { + "bytes": 30691544, + "sha256": "a61c8cce44145aa40245d32165810fbeebb5dd9e5e21a3cf65ea4c37957ed9d5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_backend_cross_device": { + "bytes": 31467496, + "sha256": "4a03440c90f387a391ca312b769f0e3cf949909598575ff902c0f67b4fdc756f" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_capi_rocm_embedding_quant": { + "bytes": 30928032, + "sha256": "91fa1d6dea40262aa1170faa4bc9ea7dab4d01cf0ec7ea9a8ef7f020da583223" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf": { + "bytes": 31012152, + "sha256": "e6e2e2caee1e8ef17cbcd4dca5dca578c3c1e8cdb35c4cbad9bf259646eee9d1" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf_dequant": { + "bytes": 30960400, + "sha256": "0c6f4d003de2ec308fbef18d661843dfc21c59f9d31b27a9a0c8eda1f42f9fa3" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_gguf_keep_quant": { + "bytes": 31352656, + "sha256": "28e3502d940688a0a2b795e93f0456595e55b13e4508a8e0d7b448f8a3b977b2" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_ops_embedding_quant": { + "bytes": 30843664, + "sha256": "adf3962f3f99c7e28cd2cbded31e36b8a324908fa6a6fa610d354b5b4de29b4a" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant": { + "bytes": 30951776, + "sha256": "85bdf30e85e8d025bb7cfb2bb44f4d717bc0797edae59c2a79cb37b2192556ec" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/include/vllm/model_executor/models/qwen3_5_gguf_weights.h": { + "bytes": 18080, + "sha256": "ed37c245f574d2f42df14b40261a8ecb6ae56c159588a82e1550fc49ccaf4655" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vllm/model_executor/model_loader/gguf_reader.cpp": { + "bytes": 29998, + "sha256": "2901344cb8252ac3c66cacd9b2ae137a814217425df28c387bbdade83d9c12e5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vllm/model_executor/models/qwen3_5_gguf_weights.cpp": { + "bytes": 90683, + "sha256": "685ca1623c336876768038a8aa28260694cd4207a1ac1e2d488bc81e451be4fb" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_embedding_quant.h": { + "bytes": 554, + "sha256": "1b2b31617d660b64f622e692089423ce1657df102322558a4ab731f521952bc5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_embedding_quant.hip": { + "bytes": 7777, + "sha256": "d3989353ece6a0c09e1f68ac16c5dbe8c949cd32c3831f41d4c2af835a3512e5" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_ops.hip": { + "bytes": 22703, + "sha256": "650a7d033b3ce3fc7a6c9a2e6bcfa80963c172ad5ef58421e2956892aac80935" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_quant_dequant.h": { + "bytes": 25507, + "sha256": "413dc138254cc72f8dccbc87268581217c93dec8f8acaea159f3f39569c37e62" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/src/vt/rocm/rocm_quant_iq_tables.h": { + "bytes": 110865, + "sha256": "d267d25ff1dd3f67749c251f87047f4b70c9650a99d04b524ff6c3313596a349" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/CMakeLists.txt": { + "bytes": 275318, + "sha256": "45ee683859f89aa7c4c8d5ec253e46a0cf4d8de5eb33ac5f196c8fd413d3cba1" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/capi/rocm_quant_gather_fixture.h": { + "bytes": 8283, + "sha256": "339414f93e59e6be9a4ca545d5e762bb2816714343f466e218dbc2b69483bdfd" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/capi/test_rocm_embedding_quant.cpp": { + "bytes": 6787, + "sha256": "5b46a2001b3c987fe3e23e836bd25f9cdc9ff7886422cbe2ffe0909781543bd2" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vllm/test_gguf_keep_quant.cpp": { + "bytes": 135199, + "sha256": "636d70c30cf28d7d3564874ac8195fda694da597998f44d53fee2df28f67820c" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tests/vt/test_rocm_embedding_quant.cpp": { + "bytes": 17542, + "sha256": "7026334d9ab70b3fa56cf0c4af4012f054e539ba37a48c586732742d7278a927" + }, + "/home/vikash/vllm.cpp-rdna3-gather-impl/tools/rocm_quant_gather/capture.cpp": { + "bytes": 7540, + "sha256": "2443dd0cc7b59c32479ff68b4f09e8e857ca9c4962a79684e3cb93a7dc44f03d" + } + }, + "cwd": "/home/vikash/vllm.cpp-rdna3-gather-impl", + "env": { + "HIP_VISIBLE_DEVICES": "0", + "ROCR_VISIBLE_DEVICES": "0", + "TMPDIR": "/home/vikash/.cache/rdna3-gather-impl/tmp", + "VT_ROCM_GATHER_TEST_CORPUS": "/home/vikash/.cache/rdna3-gather-impl/random-corpus-v2" + }, + "argv": [ + "ctest", + "--test-dir", + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather", + "--output-on-failure", + "-R", + "^(test_rocm_embedding_quant|test_capi_rocm_embedding_quant|test_gguf_keep_quant|test_ops_embedding_quant|test_gguf_dequant|test_backend_cross_device|test_gguf)$" + ], + "log": "/home/vikash/.cache/rdna3-gather-impl/evidence/native-focused-v2.log", + "authority": "Operator alone executes under the recorded GPU mutex", + "expected": "All seven focused targets execute and pass. The ambient-device case reports its separate resource requirement in this one-device lane; the required two-device run below covers it.", + "additional_runs": [ + { + "name": "ambient-device-v2", + "env": { + "HIP_VISIBLE_DEVICES": "0,1", + "ROCR_VISIBLE_DEVICES": "0,1", + "VT_ROCM_GATHER_REQUIRE_TWO_DEVICES": "1", + "TMPDIR": "/home/vikash/.cache/rdna3-gather-impl/tmp" + }, + "argv": [ + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/test_rocm_embedding_quant", + "--test-case=ROCm gather follows the queue device when the ambient device differs", + "--abort-after=1" + ], + "log": "/home/vikash/.cache/rdna3-gather-impl/evidence/ambient-device-witness-v2.log", + "expected": "rows, bounds error, recovery all pass on queue0 after ambient1 switches" + }, + { + "name": "native-corpus-v2", + "env": { + "HIP_VISIBLE_DEVICES": "0", + "ROCR_VISIBLE_DEVICES": "0", + "TMPDIR": "/home/vikash/.cache/rdna3-gather-impl/tmp" + }, + "argv": [ + "/home/vikash/vllm.cpp-rdna3-gather-impl/build-rocm-quant-gather/tests/rocm_quant_gather_capture", + "capture", + "/home/vikash/.cache/rdna3-gather-impl/corpus/manifest.json", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2" + ], + "log": "/home/vikash/.cache/rdna3-gather-impl/evidence/native-corpus-v2.log", + "expected": "76 outputs:19codecs,2widths,2dtypes; exactly one native gather per output" + } + ] +} diff --git a/docs/bench-evidence/rocm-quant-gather/native-operation-captures.tar.gz b/docs/bench-evidence/rocm-quant-gather/native-operation-captures.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..6f7e3d0a66062d55c620210389e40256dde8dc36 GIT binary patch literal 162780 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 z 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 literal 0 HcmV?d00001 diff --git a/docs/bench-evidence/rocm-quant-gather/native-v2-oracle-comparison-operator.json b/docs/bench-evidence/rocm-quant-gather/native-v2-oracle-comparison-operator.json new file mode 100644 index 000000000..df1ab757c --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/native-v2-oracle-comparison-operator.json @@ -0,0 +1,1843 @@ +{ + "scope": "Synthetic operation outputs only; model gate and original upstream fixtures remain separate", + "primary_tolerance": { + "atol": 0.01, + "rtol": 0.04 + }, + "secondary_bf16_adaptation": "Round the independently executed upstream F32 output once to BF16 with round-to-nearest-even", + "inputs": { + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/report.json": "867aaf215887b2c18f46b20b9211592550274099f721b4fff73cefb2f171dd38", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/report.json": "ffdf6a1c73cefd9362ba5fc135ede2c932c08b7386bd67309b75085582048b81", + "/home/vikash/.cache/rdna3-gather-impl/evidence/secondary-operator-v1/results.json": "2dc72bc0e153e382da980470675702f78cd22e208378ef0cf76388434d4d1be5", + "/home/vikash/.cache/rdna3-gather-impl/evidence/native-focused-v2.json": "2928aa6cbc417a3993c86481cbdd6c3ba4e35072bbf703212976344bda57fed0", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q4_0-256-f32.bin": "9966480cdeef7ea0007e83a432b0003915042615cec988bdc78aa81a9e05c4d4", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q4_0-256-f32.bin": "9966480cdeef7ea0007e83a432b0003915042615cec988bdc78aa81a9e05c4d4", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q4_0-256-bf16.bin": "634ad1adfae1205b50995644230abe47d006f04afa3de126a908edc6d52a41c7", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q4_0-256-bf16.bin": "634ad1adfae1205b50995644230abe47d006f04afa3de126a908edc6d52a41c7", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q4_0-1024-f32.bin": "73d07ea6da5385e2701b402832ecb32426cc902eabfa489644cc5b6b0a458e32", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q4_0-1024-f32.bin": "73d07ea6da5385e2701b402832ecb32426cc902eabfa489644cc5b6b0a458e32", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q4_0-1024-bf16.bin": "1cad407983d06f622ef3f0448bdfdde5e11aa2c816a1ecb1ee8f6cfbd717b2ca", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q4_0-1024-bf16.bin": "1cad407983d06f622ef3f0448bdfdde5e11aa2c816a1ecb1ee8f6cfbd717b2ca", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q5_0-256-f32.bin": "cddca55a921b2cc41118c57912cf30b394138a33e6d59bfbb24e5c7351f9b50d", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q5_0-256-f32.bin": "cddca55a921b2cc41118c57912cf30b394138a33e6d59bfbb24e5c7351f9b50d", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q5_0-256-bf16.bin": "6eab30eecc3c325dd86839aba260930ca8bf7d38710e5f1b51591f1a0b4af63b", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q5_0-256-bf16.bin": "6eab30eecc3c325dd86839aba260930ca8bf7d38710e5f1b51591f1a0b4af63b", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q5_0-1024-f32.bin": "495d23a83140b03ada09177c6f4b9bc31faadb610b1098e7687af410404acdf3", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q5_0-1024-f32.bin": "495d23a83140b03ada09177c6f4b9bc31faadb610b1098e7687af410404acdf3", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q5_0-1024-bf16.bin": "92b78a76767ce3cfe53b5aa42b23120dffd9ca588f4f7637e9b93717ff72e9ed", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q5_0-1024-bf16.bin": "92b78a76767ce3cfe53b5aa42b23120dffd9ca588f4f7637e9b93717ff72e9ed", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q8_0-256-f32.bin": "1c8493a1edd90c3a205727544e432228f90487b57d836e04aa2c70dbde2b18dc", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q8_0-256-f32.bin": "1c8493a1edd90c3a205727544e432228f90487b57d836e04aa2c70dbde2b18dc", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q8_0-256-bf16.bin": "cf1659dbd4ec5c173833e93ed5ce6ef4f5267a5f9946e2fd2ddc5b735ad1dabb", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q8_0-256-bf16.bin": "cf1659dbd4ec5c173833e93ed5ce6ef4f5267a5f9946e2fd2ddc5b735ad1dabb", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q8_0-1024-f32.bin": "834f8078f7ac197ee65dba962fcdf461ae7df8b2a4f5d32e4e84e9bd4be1fedc", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q8_0-1024-f32.bin": "834f8078f7ac197ee65dba962fcdf461ae7df8b2a4f5d32e4e84e9bd4be1fedc", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q8_0-1024-bf16.bin": "5c6c831f0038680adcbc353b74b9a7f2ccb61c2a8c08f2aa65800fee663a882f", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q8_0-1024-bf16.bin": "5c6c831f0038680adcbc353b74b9a7f2ccb61c2a8c08f2aa65800fee663a882f", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q2_K-256-f32.bin": "e24b791187d6821a4c2a75c762dbdfe17964a3290ad6ebe409102b98f42301a4", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q2_K-256-f32.bin": "e24b791187d6821a4c2a75c762dbdfe17964a3290ad6ebe409102b98f42301a4", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q2_K-256-bf16.bin": "bc5d0b2852039a8f373b4c77d3c6e37a64f89b38850aaba1291396beb404ac4e", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q2_K-256-bf16.bin": "bc5d0b2852039a8f373b4c77d3c6e37a64f89b38850aaba1291396beb404ac4e", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q2_K-1024-f32.bin": "55a37b1031ff271501b735e019d48c5b16651a28d096abc9cf66ae9b7e13032b", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q2_K-1024-f32.bin": "55a37b1031ff271501b735e019d48c5b16651a28d096abc9cf66ae9b7e13032b", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q2_K-1024-bf16.bin": "355660442b0a1b33e66868cd480fe19ad3cbef94d291cf96a0ba3a846b7bfff1", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q2_K-1024-bf16.bin": "355660442b0a1b33e66868cd480fe19ad3cbef94d291cf96a0ba3a846b7bfff1", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q3_K-256-f32.bin": "8abfd966f1a8d1cfe3a56ffe70951cf74861cec4937fe6cec311955c3bb8097c", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q3_K-256-f32.bin": "8abfd966f1a8d1cfe3a56ffe70951cf74861cec4937fe6cec311955c3bb8097c", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q3_K-256-bf16.bin": "cdf4fecc71e5f51885720bdba5f669eac9f5526ce37d21cc0e4983943398219d", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q3_K-256-bf16.bin": "cdf4fecc71e5f51885720bdba5f669eac9f5526ce37d21cc0e4983943398219d", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q3_K-1024-f32.bin": "c5db632dc69564c309db1e55800627d303353b322039d70bc64ad60a65e4544d", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q3_K-1024-f32.bin": "c5db632dc69564c309db1e55800627d303353b322039d70bc64ad60a65e4544d", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q3_K-1024-bf16.bin": "3c2a56e17bcd792a99c1d429d04872d530e3f35e5e59a40f0a2cb733e3c5881e", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q3_K-1024-bf16.bin": "3c2a56e17bcd792a99c1d429d04872d530e3f35e5e59a40f0a2cb733e3c5881e", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q4_K-256-f32.bin": "828bc6bd954f80b2bd5e90c4dead3785cc3f619a3e0cf85bbdd8977889e93780", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q4_K-256-f32.bin": "828bc6bd954f80b2bd5e90c4dead3785cc3f619a3e0cf85bbdd8977889e93780", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q4_K-256-bf16.bin": "1183adfc4a8cf6fbdeed1a024991b6b703d67e9254f2547f8be74070ba311023", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q4_K-256-bf16.bin": "1183adfc4a8cf6fbdeed1a024991b6b703d67e9254f2547f8be74070ba311023", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q4_K-1024-f32.bin": "818de25fdc842d287a28a404fe68291bed1a4f6f92d692be1697b63942d5de76", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q4_K-1024-f32.bin": "818de25fdc842d287a28a404fe68291bed1a4f6f92d692be1697b63942d5de76", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q4_K-1024-bf16.bin": "edb9258354cc7e85a80f0ac0f4d2372b7586152ea51ac9b7a5d05c1ddd5e7370", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q4_K-1024-bf16.bin": "edb9258354cc7e85a80f0ac0f4d2372b7586152ea51ac9b7a5d05c1ddd5e7370", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q5_K-256-f32.bin": "cccaa4367b4a06faba242e84ef5aef302d58ce73c58c51415337ca33058b7dbb", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q5_K-256-f32.bin": "cccaa4367b4a06faba242e84ef5aef302d58ce73c58c51415337ca33058b7dbb", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q5_K-256-bf16.bin": "fa74aaf35aaea5781445d59d0d0dada1584a47fa079a374fb60a0d00dc52751a", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q5_K-256-bf16.bin": "fa74aaf35aaea5781445d59d0d0dada1584a47fa079a374fb60a0d00dc52751a", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q5_K-1024-f32.bin": "8abdaf31ff6e869553fd22f6f57b15dd5699ac83921422291c22fb5979734c14", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q5_K-1024-f32.bin": "8abdaf31ff6e869553fd22f6f57b15dd5699ac83921422291c22fb5979734c14", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q5_K-1024-bf16.bin": "d448a2b8bf36fe9817b6ab4447bab0b32cf052268cdbe5d4a0b1166cb93dabab", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q5_K-1024-bf16.bin": "d448a2b8bf36fe9817b6ab4447bab0b32cf052268cdbe5d4a0b1166cb93dabab", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q6_K-256-f32.bin": "3e1665a3167a552c47493bdc538166acfa6cbd43a1e7dd30230c40e3c5b11207", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q6_K-256-f32.bin": "955ba972e48a303803cdacca928e7f60176dfaa1b7f8590038bdb91830658428", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q6_K-256-bf16.bin": "242d1b322588618517ee3d4d62e393d08b2faca2262414ab00d89d092598e8ee", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q6_K-256-bf16.bin": "c65412c7615787b9103207f55776d49dfda767740f4d6e1106cb711a99404bc6", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q6_K-1024-f32.bin": "158400e054e65af2adad3e7d348b2fc3e082fcfc065706db200704d3c86a2581", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q6_K-1024-f32.bin": "5a0f2bb0da03f1eb5c689c6f95be636890aec44873bffe77dd039c2b5bc6c20a", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q6_K-1024-bf16.bin": "54c4ea60561a742634c5fdf24c4dd372f0e101a48bf29b53d53a0b7e88f31aea", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/Q6_K-1024-bf16.bin": "5955c913676e2e5003f84ad0dca7062d3f7106188a13e4844b13774a2764c238", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q8_K-256-f32.bin": "42d365370201b210a4c646cc5718a3bf7becff7ef20bb5f381a1736ba22850e6", + "/home/vikash/.cache/rdna3-gather-impl/evidence/secondary-operator-v1/Q8_K-256-f32.bin": "42d365370201b210a4c646cc5718a3bf7becff7ef20bb5f381a1736ba22850e6", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q8_K-256-bf16.bin": "f5da512dcaf2f4165abd5b4b1377d275a5945d2ab8946d2d8266600c5b03d31f", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q8_K-1024-f32.bin": "bc4c56d33b3d53d928f21b39953ba08f191aec465ead263abb832820f6ccd29c", + "/home/vikash/.cache/rdna3-gather-impl/evidence/secondary-operator-v1/Q8_K-1024-f32.bin": "bc4c56d33b3d53d928f21b39953ba08f191aec465ead263abb832820f6ccd29c", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/Q8_K-1024-bf16.bin": "6a1aa0cd72dca3f6ae3f6b835eeba50a87bf7b143ad607baa30482f0835f8c22", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_XXS-256-f32.bin": "2d205710a3efc0745c45410d91ff4e86d43f486a8366714b93586957c69c1432", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_XXS-256-f32.bin": "2d205710a3efc0745c45410d91ff4e86d43f486a8366714b93586957c69c1432", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_XXS-256-bf16.bin": "7cfe27efb61e2bacbb37365e0375af69a42afacb9ad6bd20ed8a5732b710204b", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_XXS-256-bf16.bin": "7cfe27efb61e2bacbb37365e0375af69a42afacb9ad6bd20ed8a5732b710204b", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_XXS-1024-f32.bin": "7e5ac721517328088f4c4ff43e30aec9413c5e18047d91b3651b486d33ca45e2", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_XXS-1024-f32.bin": "7e5ac721517328088f4c4ff43e30aec9413c5e18047d91b3651b486d33ca45e2", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_XXS-1024-bf16.bin": "d94a7d1d127389dccf61f4d39c484e8a38c6c6b8eb5cf1f2a2e1c2a5b0c5240c", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_XXS-1024-bf16.bin": "d94a7d1d127389dccf61f4d39c484e8a38c6c6b8eb5cf1f2a2e1c2a5b0c5240c", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_XS-256-f32.bin": "81f10e413631a1188b1b74dabba22f95812c2d7c8d5b34b2276cf69bf30b92aa", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_XS-256-f32.bin": "81f10e413631a1188b1b74dabba22f95812c2d7c8d5b34b2276cf69bf30b92aa", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_XS-256-bf16.bin": "5d1ebc762d9b8c8160b7246ad2701e404d04fccac8a42fb8e1d12739fc7023db", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_XS-256-bf16.bin": "5d1ebc762d9b8c8160b7246ad2701e404d04fccac8a42fb8e1d12739fc7023db", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_XS-1024-f32.bin": "74837cd35b8970c160e6785ca19ad9163178e039b3f63d280be46003710430bd", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_XS-1024-f32.bin": "74837cd35b8970c160e6785ca19ad9163178e039b3f63d280be46003710430bd", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_XS-1024-bf16.bin": "ea2f9564900a1bb82888a86bd5e1605682e30e1cc33fa0453815dc30a22712a5", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_XS-1024-bf16.bin": "ea2f9564900a1bb82888a86bd5e1605682e30e1cc33fa0453815dc30a22712a5", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ3_XXS-256-f32.bin": "292689c91164b2c7dc6f225d06eacbbc19b005d40dd8992c19dbe8bd55b0fdda", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ3_XXS-256-f32.bin": "292689c91164b2c7dc6f225d06eacbbc19b005d40dd8992c19dbe8bd55b0fdda", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ3_XXS-256-bf16.bin": "92bc21816f28827df760ea52f25de72ee085b53c63b3d691e3d42a7c09496631", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ3_XXS-256-bf16.bin": "92bc21816f28827df760ea52f25de72ee085b53c63b3d691e3d42a7c09496631", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ3_XXS-1024-f32.bin": "7e044ef28ae859e13df96388c97c06f50e1df645cdf7eb9fec9a373a7b7745e1", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ3_XXS-1024-f32.bin": "7e044ef28ae859e13df96388c97c06f50e1df645cdf7eb9fec9a373a7b7745e1", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ3_XXS-1024-bf16.bin": "812efe38d269cceafbc23f54913b3d3e3ef2177730f0bfcf9915287bb804bf44", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ3_XXS-1024-bf16.bin": "812efe38d269cceafbc23f54913b3d3e3ef2177730f0bfcf9915287bb804bf44", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ1_S-256-f32.bin": "4e7645670f8d1e86c3aa84d9b63435bdbd241228eeea56cf39686a6280d3eaf1", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ1_S-256-f32.bin": "4e7645670f8d1e86c3aa84d9b63435bdbd241228eeea56cf39686a6280d3eaf1", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ1_S-256-bf16.bin": "f2a6a1a52667cf9cf4f822f9af52408880f21d9a1955d46e7704a3a21d191090", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ1_S-256-bf16.bin": "f2a6a1a52667cf9cf4f822f9af52408880f21d9a1955d46e7704a3a21d191090", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ1_S-1024-f32.bin": "7d93653c10b72ce36a7bc4a6a46ec21eefd3d4704128f0281b8eeb4b018f1a02", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ1_S-1024-f32.bin": "7d93653c10b72ce36a7bc4a6a46ec21eefd3d4704128f0281b8eeb4b018f1a02", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ1_S-1024-bf16.bin": "5972de407abdee675d416358801507600103e60c5518d5a7e3dc61362d3e4fe9", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ1_S-1024-bf16.bin": "5972de407abdee675d416358801507600103e60c5518d5a7e3dc61362d3e4fe9", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ4_NL-256-f32.bin": "16184a3758d6b6f361b16cf741d5fe0d05ff8f7d866050ebdc3354915c57ad9e", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ4_NL-256-f32.bin": "16184a3758d6b6f361b16cf741d5fe0d05ff8f7d866050ebdc3354915c57ad9e", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ4_NL-256-bf16.bin": "4f602b6088ab68c2631b7293a3e884785828a135de210d6fd8eb2b82b7bc69d9", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ4_NL-256-bf16.bin": "4f602b6088ab68c2631b7293a3e884785828a135de210d6fd8eb2b82b7bc69d9", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ4_NL-1024-f32.bin": "d7f5fb54d2e2c52429c669245858945ae1b0a6fcee09f24c8a21c7c7d71ab516", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ4_NL-1024-f32.bin": "d7f5fb54d2e2c52429c669245858945ae1b0a6fcee09f24c8a21c7c7d71ab516", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ4_NL-1024-bf16.bin": "2bf0d166828994d5497b4cb20400fbbc45c1fc0fd94a3380d525df16450b81a3", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ4_NL-1024-bf16.bin": "2bf0d166828994d5497b4cb20400fbbc45c1fc0fd94a3380d525df16450b81a3", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ3_S-256-f32.bin": "7843ff13e1c7f1475f949583ec0466b7cd3020723994d7c725e7c618c11c34f0", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ3_S-256-f32.bin": "8cad98f9fecbfcac883cb11a91df1ac703846dfe88bac12792ab3066420243ad", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ3_S-256-bf16.bin": "281888da0636914c257cd25407adc1465b2d40e96aa7694eb5c3bd0df4036b73", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ3_S-256-bf16.bin": "7f36f4a4ba9f0977f68d452e8ec1d26ea299ea9ddbc82fd0ede324abc94d6595", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ3_S-1024-f32.bin": "8932dbeb65d3716cfb60014ad471ab0fb5d2d2d4b037e8745464e65f77b936de", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ3_S-1024-f32.bin": "ebcadd200e64857ed483aa7176172dc94b966198fb81d2910ab723260fb46fdc", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ3_S-1024-bf16.bin": "11a954e23ccc31f98a3398902b7ce96ec39f0fc0119d41202732630299d9a623", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ3_S-1024-bf16.bin": "88e55dfa1c9378436bd431db09fca5bf5aad9910dc311b493d6f94d1ec98dc7c", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_S-256-f32.bin": "2c2908ecf0382e9e8d6414ca7bbacd8fe8ac95cc15dd5483d32293883801714f", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_S-256-f32.bin": "2c2908ecf0382e9e8d6414ca7bbacd8fe8ac95cc15dd5483d32293883801714f", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_S-256-bf16.bin": "22e25316adaf5931c49ef737972a2f1d612b90acb69a3ca76002effd2a43d195", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_S-256-bf16.bin": "22e25316adaf5931c49ef737972a2f1d612b90acb69a3ca76002effd2a43d195", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_S-1024-f32.bin": "90c3f52ffccbc2f83e5b66edaf5805f2e23967aea551d55d1216142a2e3cc9f4", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_S-1024-f32.bin": "90c3f52ffccbc2f83e5b66edaf5805f2e23967aea551d55d1216142a2e3cc9f4", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ2_S-1024-bf16.bin": "68f4582c895e47c648f5a3e3972d991d38a49404f5d3dd1434a2e27b90096907", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ2_S-1024-bf16.bin": "68f4582c895e47c648f5a3e3972d991d38a49404f5d3dd1434a2e27b90096907", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ4_XS-256-f32.bin": "bc2868543de19f14c38589e427629f77c0fd02a8a24d22d47570e7fa03250ae2", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ4_XS-256-f32.bin": "bc2868543de19f14c38589e427629f77c0fd02a8a24d22d47570e7fa03250ae2", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ4_XS-256-bf16.bin": "1d664b63884d614512b6544cb085eb91626e7e20ebd05d9afca3e662bcbdeccc", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ4_XS-256-bf16.bin": "1d664b63884d614512b6544cb085eb91626e7e20ebd05d9afca3e662bcbdeccc", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ4_XS-1024-f32.bin": "c5d5b46955ae2c26887b015601e67cdaa3c4712910e1d743f58a0910f2cef889", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ4_XS-1024-f32.bin": "c5d5b46955ae2c26887b015601e67cdaa3c4712910e1d743f58a0910f2cef889", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ4_XS-1024-bf16.bin": "b5d820d40868cc699f6d83fa2cc63f773b7c01c42af2fc961952261e4198a48d", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1/IQ4_XS-1024-bf16.bin": "b5d820d40868cc699f6d83fa2cc63f773b7c01c42af2fc961952261e4198a48d", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/MXFP4-256-f32.bin": "aca27b230e9675ea214c31723306036025295c570903f8804d4d767b4fb0bdb2", + "/home/vikash/.cache/rdna3-gather-impl/evidence/secondary-operator-v1/MXFP4-256-f32.bin": "aca27b230e9675ea214c31723306036025295c570903f8804d4d767b4fb0bdb2", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/MXFP4-256-bf16.bin": "4b66106696144b4970929d2f5734d3ddf8e6e4580a2fe8910b500ebaab5431a9", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/MXFP4-1024-f32.bin": "a2688e4f8d766f642b8fbdebcbfff7e4e2720ae9fc57409812eb0a21f4bb6fec", + "/home/vikash/.cache/rdna3-gather-impl/evidence/secondary-operator-v1/MXFP4-1024-f32.bin": "a2688e4f8d766f642b8fbdebcbfff7e4e2720ae9fc57409812eb0a21f4bb6fec", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/MXFP4-1024-bf16.bin": "cdd6e95bc3bc3e18bc014dee2cdb125cb179b670256896536b0e3822b0adfa83", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ1_XXXS-256-f32.bin": "b4707ef68fb11c9d3720db82722924de4004e75c97d07cdbd0b24c08f3677fce", + "/home/vikash/.cache/rdna3-gather-impl/evidence/secondary-operator-v1/IQ1_XXXS-256-f32.bin": "b4707ef68fb11c9d3720db82722924de4004e75c97d07cdbd0b24c08f3677fce", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ1_XXXS-256-bf16.bin": "9de69ca2d01fda18f05e9ee7ac531f3cb806d39a3af8d10e64ba0c53dab1b08a", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ1_XXXS-1024-f32.bin": "10b121b53bde30b8e24ea1fb6ef8bb4f3123952900c2c66886d2e09b40ee62c0", + "/home/vikash/.cache/rdna3-gather-impl/evidence/secondary-operator-v1/IQ1_XXXS-1024-f32.bin": "10b121b53bde30b8e24ea1fb6ef8bb4f3123952900c2c66886d2e09b40ee62c0", + "/home/vikash/.cache/rdna3-gather-impl/native-synthetic-v2/IQ1_XXXS-1024-bf16.bin": "14e07510990f222b0656fdbacd1a3d6271c28e00526587b67c4a1b399674c3d5" + }, + "cases": [ + { + "name": "Q4_0-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "9966480cdeef7ea0007e83a432b0003915042615cec988bdc78aa81a9e05c4d4", + "oracle_file_sha256": "9966480cdeef7ea0007e83a432b0003915042615cec988bdc78aa81a9e05c4d4", + "compared_oracle_sha256": "9966480cdeef7ea0007e83a432b0003915042615cec988bdc78aa81a9e05c4d4", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 18432, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q4_0-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "634ad1adfae1205b50995644230abe47d006f04afa3de126a908edc6d52a41c7", + "oracle_file_sha256": "634ad1adfae1205b50995644230abe47d006f04afa3de126a908edc6d52a41c7", + "compared_oracle_sha256": "634ad1adfae1205b50995644230abe47d006f04afa3de126a908edc6d52a41c7", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 18432, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q4_0-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "73d07ea6da5385e2701b402832ecb32426cc902eabfa489644cc5b6b0a458e32", + "oracle_file_sha256": "73d07ea6da5385e2701b402832ecb32426cc902eabfa489644cc5b6b0a458e32", + "compared_oracle_sha256": "73d07ea6da5385e2701b402832ecb32426cc902eabfa489644cc5b6b0a458e32", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 73728, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q4_0-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "1cad407983d06f622ef3f0448bdfdde5e11aa2c816a1ecb1ee8f6cfbd717b2ca", + "oracle_file_sha256": "1cad407983d06f622ef3f0448bdfdde5e11aa2c816a1ecb1ee8f6cfbd717b2ca", + "compared_oracle_sha256": "1cad407983d06f622ef3f0448bdfdde5e11aa2c816a1ecb1ee8f6cfbd717b2ca", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 73728, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q5_0-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "cddca55a921b2cc41118c57912cf30b394138a33e6d59bfbb24e5c7351f9b50d", + "oracle_file_sha256": "cddca55a921b2cc41118c57912cf30b394138a33e6d59bfbb24e5c7351f9b50d", + "compared_oracle_sha256": "cddca55a921b2cc41118c57912cf30b394138a33e6d59bfbb24e5c7351f9b50d", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 22528, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q5_0-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "6eab30eecc3c325dd86839aba260930ca8bf7d38710e5f1b51591f1a0b4af63b", + "oracle_file_sha256": "6eab30eecc3c325dd86839aba260930ca8bf7d38710e5f1b51591f1a0b4af63b", + "compared_oracle_sha256": "6eab30eecc3c325dd86839aba260930ca8bf7d38710e5f1b51591f1a0b4af63b", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 22528, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q5_0-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "495d23a83140b03ada09177c6f4b9bc31faadb610b1098e7687af410404acdf3", + "oracle_file_sha256": "495d23a83140b03ada09177c6f4b9bc31faadb610b1098e7687af410404acdf3", + "compared_oracle_sha256": "495d23a83140b03ada09177c6f4b9bc31faadb610b1098e7687af410404acdf3", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 90112, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q5_0-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "92b78a76767ce3cfe53b5aa42b23120dffd9ca588f4f7637e9b93717ff72e9ed", + "oracle_file_sha256": "92b78a76767ce3cfe53b5aa42b23120dffd9ca588f4f7637e9b93717ff72e9ed", + "compared_oracle_sha256": "92b78a76767ce3cfe53b5aa42b23120dffd9ca588f4f7637e9b93717ff72e9ed", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 90112, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q8_0-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "1c8493a1edd90c3a205727544e432228f90487b57d836e04aa2c70dbde2b18dc", + "oracle_file_sha256": "1c8493a1edd90c3a205727544e432228f90487b57d836e04aa2c70dbde2b18dc", + "compared_oracle_sha256": "1c8493a1edd90c3a205727544e432228f90487b57d836e04aa2c70dbde2b18dc", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 34816, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q8_0-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "cf1659dbd4ec5c173833e93ed5ce6ef4f5267a5f9946e2fd2ddc5b735ad1dabb", + "oracle_file_sha256": "cf1659dbd4ec5c173833e93ed5ce6ef4f5267a5f9946e2fd2ddc5b735ad1dabb", + "compared_oracle_sha256": "cf1659dbd4ec5c173833e93ed5ce6ef4f5267a5f9946e2fd2ddc5b735ad1dabb", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 34816, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q8_0-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "834f8078f7ac197ee65dba962fcdf461ae7df8b2a4f5d32e4e84e9bd4be1fedc", + "oracle_file_sha256": "834f8078f7ac197ee65dba962fcdf461ae7df8b2a4f5d32e4e84e9bd4be1fedc", + "compared_oracle_sha256": "834f8078f7ac197ee65dba962fcdf461ae7df8b2a4f5d32e4e84e9bd4be1fedc", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 139264, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q8_0-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "5c6c831f0038680adcbc353b74b9a7f2ccb61c2a8c08f2aa65800fee663a882f", + "oracle_file_sha256": "5c6c831f0038680adcbc353b74b9a7f2ccb61c2a8c08f2aa65800fee663a882f", + "compared_oracle_sha256": "5c6c831f0038680adcbc353b74b9a7f2ccb61c2a8c08f2aa65800fee663a882f", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 139264, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q2_K-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "e24b791187d6821a4c2a75c762dbdfe17964a3290ad6ebe409102b98f42301a4", + "oracle_file_sha256": "e24b791187d6821a4c2a75c762dbdfe17964a3290ad6ebe409102b98f42301a4", + "compared_oracle_sha256": "e24b791187d6821a4c2a75c762dbdfe17964a3290ad6ebe409102b98f42301a4", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 10752, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q2_K-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "bc5d0b2852039a8f373b4c77d3c6e37a64f89b38850aaba1291396beb404ac4e", + "oracle_file_sha256": "bc5d0b2852039a8f373b4c77d3c6e37a64f89b38850aaba1291396beb404ac4e", + "compared_oracle_sha256": "bc5d0b2852039a8f373b4c77d3c6e37a64f89b38850aaba1291396beb404ac4e", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 10752, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q2_K-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "55a37b1031ff271501b735e019d48c5b16651a28d096abc9cf66ae9b7e13032b", + "oracle_file_sha256": "55a37b1031ff271501b735e019d48c5b16651a28d096abc9cf66ae9b7e13032b", + "compared_oracle_sha256": "55a37b1031ff271501b735e019d48c5b16651a28d096abc9cf66ae9b7e13032b", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 43008, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q2_K-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "355660442b0a1b33e66868cd480fe19ad3cbef94d291cf96a0ba3a846b7bfff1", + "oracle_file_sha256": "355660442b0a1b33e66868cd480fe19ad3cbef94d291cf96a0ba3a846b7bfff1", + "compared_oracle_sha256": "355660442b0a1b33e66868cd480fe19ad3cbef94d291cf96a0ba3a846b7bfff1", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 43008, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q3_K-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "8abfd966f1a8d1cfe3a56ffe70951cf74861cec4937fe6cec311955c3bb8097c", + "oracle_file_sha256": "8abfd966f1a8d1cfe3a56ffe70951cf74861cec4937fe6cec311955c3bb8097c", + "compared_oracle_sha256": "8abfd966f1a8d1cfe3a56ffe70951cf74861cec4937fe6cec311955c3bb8097c", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 14080, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q3_K-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "cdf4fecc71e5f51885720bdba5f669eac9f5526ce37d21cc0e4983943398219d", + "oracle_file_sha256": "cdf4fecc71e5f51885720bdba5f669eac9f5526ce37d21cc0e4983943398219d", + "compared_oracle_sha256": "cdf4fecc71e5f51885720bdba5f669eac9f5526ce37d21cc0e4983943398219d", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 14080, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q3_K-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "c5db632dc69564c309db1e55800627d303353b322039d70bc64ad60a65e4544d", + "oracle_file_sha256": "c5db632dc69564c309db1e55800627d303353b322039d70bc64ad60a65e4544d", + "compared_oracle_sha256": "c5db632dc69564c309db1e55800627d303353b322039d70bc64ad60a65e4544d", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 56320, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q3_K-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "3c2a56e17bcd792a99c1d429d04872d530e3f35e5e59a40f0a2cb733e3c5881e", + "oracle_file_sha256": "3c2a56e17bcd792a99c1d429d04872d530e3f35e5e59a40f0a2cb733e3c5881e", + "compared_oracle_sha256": "3c2a56e17bcd792a99c1d429d04872d530e3f35e5e59a40f0a2cb733e3c5881e", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 56320, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q4_K-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "828bc6bd954f80b2bd5e90c4dead3785cc3f619a3e0cf85bbdd8977889e93780", + "oracle_file_sha256": "828bc6bd954f80b2bd5e90c4dead3785cc3f619a3e0cf85bbdd8977889e93780", + "compared_oracle_sha256": "828bc6bd954f80b2bd5e90c4dead3785cc3f619a3e0cf85bbdd8977889e93780", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 18432, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q4_K-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "1183adfc4a8cf6fbdeed1a024991b6b703d67e9254f2547f8be74070ba311023", + "oracle_file_sha256": "1183adfc4a8cf6fbdeed1a024991b6b703d67e9254f2547f8be74070ba311023", + "compared_oracle_sha256": "1183adfc4a8cf6fbdeed1a024991b6b703d67e9254f2547f8be74070ba311023", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 18432, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q4_K-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "818de25fdc842d287a28a404fe68291bed1a4f6f92d692be1697b63942d5de76", + "oracle_file_sha256": "818de25fdc842d287a28a404fe68291bed1a4f6f92d692be1697b63942d5de76", + "compared_oracle_sha256": "818de25fdc842d287a28a404fe68291bed1a4f6f92d692be1697b63942d5de76", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 73728, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q4_K-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "edb9258354cc7e85a80f0ac0f4d2372b7586152ea51ac9b7a5d05c1ddd5e7370", + "oracle_file_sha256": "edb9258354cc7e85a80f0ac0f4d2372b7586152ea51ac9b7a5d05c1ddd5e7370", + "compared_oracle_sha256": "edb9258354cc7e85a80f0ac0f4d2372b7586152ea51ac9b7a5d05c1ddd5e7370", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 73728, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q5_K-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "cccaa4367b4a06faba242e84ef5aef302d58ce73c58c51415337ca33058b7dbb", + "oracle_file_sha256": "cccaa4367b4a06faba242e84ef5aef302d58ce73c58c51415337ca33058b7dbb", + "compared_oracle_sha256": "cccaa4367b4a06faba242e84ef5aef302d58ce73c58c51415337ca33058b7dbb", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 22528, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q5_K-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "fa74aaf35aaea5781445d59d0d0dada1584a47fa079a374fb60a0d00dc52751a", + "oracle_file_sha256": "fa74aaf35aaea5781445d59d0d0dada1584a47fa079a374fb60a0d00dc52751a", + "compared_oracle_sha256": "fa74aaf35aaea5781445d59d0d0dada1584a47fa079a374fb60a0d00dc52751a", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 22528, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q5_K-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "8abdaf31ff6e869553fd22f6f57b15dd5699ac83921422291c22fb5979734c14", + "oracle_file_sha256": "8abdaf31ff6e869553fd22f6f57b15dd5699ac83921422291c22fb5979734c14", + "compared_oracle_sha256": "8abdaf31ff6e869553fd22f6f57b15dd5699ac83921422291c22fb5979734c14", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 90112, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q5_K-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "d448a2b8bf36fe9817b6ab4447bab0b32cf052268cdbe5d4a0b1166cb93dabab", + "oracle_file_sha256": "d448a2b8bf36fe9817b6ab4447bab0b32cf052268cdbe5d4a0b1166cb93dabab", + "compared_oracle_sha256": "d448a2b8bf36fe9817b6ab4447bab0b32cf052268cdbe5d4a0b1166cb93dabab", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 90112, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q6_K-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "3e1665a3167a552c47493bdc538166acfa6cbd43a1e7dd30230c40e3c5b11207", + "oracle_file_sha256": "955ba972e48a303803cdacca928e7f60176dfaa1b7f8590038bdb91830658428", + "compared_oracle_sha256": "955ba972e48a303803cdacca928e7f60176dfaa1b7f8590038bdb91830658428", + "byte_equal": false, + "max_abs_error": 0.00048828125, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 26880, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q6_K-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "242d1b322588618517ee3d4d62e393d08b2faca2262414ab00d89d092598e8ee", + "oracle_file_sha256": "c65412c7615787b9103207f55776d49dfda767740f4d6e1106cb711a99404bc6", + "compared_oracle_sha256": "c65412c7615787b9103207f55776d49dfda767740f4d6e1106cb711a99404bc6", + "byte_equal": false, + "max_abs_error": 0.0078125, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 26880, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q6_K-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "158400e054e65af2adad3e7d348b2fc3e082fcfc065706db200704d3c86a2581", + "oracle_file_sha256": "5a0f2bb0da03f1eb5c689c6f95be636890aec44873bffe77dd039c2b5bc6c20a", + "compared_oracle_sha256": "5a0f2bb0da03f1eb5c689c6f95be636890aec44873bffe77dd039c2b5bc6c20a", + "byte_equal": false, + "max_abs_error": 0.00048828125, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 107520, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q6_K-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "54c4ea60561a742634c5fdf24c4dd372f0e101a48bf29b53d53a0b7e88f31aea", + "oracle_file_sha256": "5955c913676e2e5003f84ad0dca7062d3f7106188a13e4844b13774a2764c238", + "compared_oracle_sha256": "5955c913676e2e5003f84ad0dca7062d3f7106188a13e4844b13774a2764c238", + "byte_equal": false, + "max_abs_error": 0.0078125, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 107520, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q8_K-256", + "dtype": "f32", + "oracle": "secondary", + "adaptation": null, + "elements": 1024, + "native_sha256": "42d365370201b210a4c646cc5718a3bf7becff7ef20bb5f381a1736ba22850e6", + "oracle_file_sha256": "42d365370201b210a4c646cc5718a3bf7becff7ef20bb5f381a1736ba22850e6", + "compared_oracle_sha256": "42d365370201b210a4c646cc5718a3bf7becff7ef20bb5f381a1736ba22850e6", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 37376, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q8_K-256", + "dtype": "bf16", + "oracle": "secondary", + "adaptation": "upstream F32 output rounded to BF16 RNE", + "elements": 1024, + "native_sha256": "f5da512dcaf2f4165abd5b4b1377d275a5945d2ab8946d2d8266600c5b03d31f", + "oracle_file_sha256": "42d365370201b210a4c646cc5718a3bf7becff7ef20bb5f381a1736ba22850e6", + "compared_oracle_sha256": "f5da512dcaf2f4165abd5b4b1377d275a5945d2ab8946d2d8266600c5b03d31f", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 37376, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q8_K-1024", + "dtype": "f32", + "oracle": "secondary", + "adaptation": null, + "elements": 4096, + "native_sha256": "bc4c56d33b3d53d928f21b39953ba08f191aec465ead263abb832820f6ccd29c", + "oracle_file_sha256": "bc4c56d33b3d53d928f21b39953ba08f191aec465ead263abb832820f6ccd29c", + "compared_oracle_sha256": "bc4c56d33b3d53d928f21b39953ba08f191aec465ead263abb832820f6ccd29c", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 149504, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "Q8_K-1024", + "dtype": "bf16", + "oracle": "secondary", + "adaptation": "upstream F32 output rounded to BF16 RNE", + "elements": 4096, + "native_sha256": "6a1aa0cd72dca3f6ae3f6b835eeba50a87bf7b143ad607baa30482f0835f8c22", + "oracle_file_sha256": "bc4c56d33b3d53d928f21b39953ba08f191aec465ead263abb832820f6ccd29c", + "compared_oracle_sha256": "6a1aa0cd72dca3f6ae3f6b835eeba50a87bf7b143ad607baa30482f0835f8c22", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 149504, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_XXS-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "2d205710a3efc0745c45410d91ff4e86d43f486a8366714b93586957c69c1432", + "oracle_file_sha256": "2d205710a3efc0745c45410d91ff4e86d43f486a8366714b93586957c69c1432", + "compared_oracle_sha256": "2d205710a3efc0745c45410d91ff4e86d43f486a8366714b93586957c69c1432", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 8448, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_XXS-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "7cfe27efb61e2bacbb37365e0375af69a42afacb9ad6bd20ed8a5732b710204b", + "oracle_file_sha256": "7cfe27efb61e2bacbb37365e0375af69a42afacb9ad6bd20ed8a5732b710204b", + "compared_oracle_sha256": "7cfe27efb61e2bacbb37365e0375af69a42afacb9ad6bd20ed8a5732b710204b", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 8448, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_XXS-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "7e5ac721517328088f4c4ff43e30aec9413c5e18047d91b3651b486d33ca45e2", + "oracle_file_sha256": "7e5ac721517328088f4c4ff43e30aec9413c5e18047d91b3651b486d33ca45e2", + "compared_oracle_sha256": "7e5ac721517328088f4c4ff43e30aec9413c5e18047d91b3651b486d33ca45e2", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 33792, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_XXS-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "d94a7d1d127389dccf61f4d39c484e8a38c6c6b8eb5cf1f2a2e1c2a5b0c5240c", + "oracle_file_sha256": "d94a7d1d127389dccf61f4d39c484e8a38c6c6b8eb5cf1f2a2e1c2a5b0c5240c", + "compared_oracle_sha256": "d94a7d1d127389dccf61f4d39c484e8a38c6c6b8eb5cf1f2a2e1c2a5b0c5240c", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 33792, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_XS-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "81f10e413631a1188b1b74dabba22f95812c2d7c8d5b34b2276cf69bf30b92aa", + "oracle_file_sha256": "81f10e413631a1188b1b74dabba22f95812c2d7c8d5b34b2276cf69bf30b92aa", + "compared_oracle_sha256": "81f10e413631a1188b1b74dabba22f95812c2d7c8d5b34b2276cf69bf30b92aa", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 9472, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_XS-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "5d1ebc762d9b8c8160b7246ad2701e404d04fccac8a42fb8e1d12739fc7023db", + "oracle_file_sha256": "5d1ebc762d9b8c8160b7246ad2701e404d04fccac8a42fb8e1d12739fc7023db", + "compared_oracle_sha256": "5d1ebc762d9b8c8160b7246ad2701e404d04fccac8a42fb8e1d12739fc7023db", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 9472, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_XS-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "74837cd35b8970c160e6785ca19ad9163178e039b3f63d280be46003710430bd", + "oracle_file_sha256": "74837cd35b8970c160e6785ca19ad9163178e039b3f63d280be46003710430bd", + "compared_oracle_sha256": "74837cd35b8970c160e6785ca19ad9163178e039b3f63d280be46003710430bd", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 37888, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_XS-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "ea2f9564900a1bb82888a86bd5e1605682e30e1cc33fa0453815dc30a22712a5", + "oracle_file_sha256": "ea2f9564900a1bb82888a86bd5e1605682e30e1cc33fa0453815dc30a22712a5", + "compared_oracle_sha256": "ea2f9564900a1bb82888a86bd5e1605682e30e1cc33fa0453815dc30a22712a5", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 37888, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ3_XXS-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "292689c91164b2c7dc6f225d06eacbbc19b005d40dd8992c19dbe8bd55b0fdda", + "oracle_file_sha256": "292689c91164b2c7dc6f225d06eacbbc19b005d40dd8992c19dbe8bd55b0fdda", + "compared_oracle_sha256": "292689c91164b2c7dc6f225d06eacbbc19b005d40dd8992c19dbe8bd55b0fdda", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 12544, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ3_XXS-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "92bc21816f28827df760ea52f25de72ee085b53c63b3d691e3d42a7c09496631", + "oracle_file_sha256": "92bc21816f28827df760ea52f25de72ee085b53c63b3d691e3d42a7c09496631", + "compared_oracle_sha256": "92bc21816f28827df760ea52f25de72ee085b53c63b3d691e3d42a7c09496631", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 12544, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ3_XXS-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "7e044ef28ae859e13df96388c97c06f50e1df645cdf7eb9fec9a373a7b7745e1", + "oracle_file_sha256": "7e044ef28ae859e13df96388c97c06f50e1df645cdf7eb9fec9a373a7b7745e1", + "compared_oracle_sha256": "7e044ef28ae859e13df96388c97c06f50e1df645cdf7eb9fec9a373a7b7745e1", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 50176, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ3_XXS-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "812efe38d269cceafbc23f54913b3d3e3ef2177730f0bfcf9915287bb804bf44", + "oracle_file_sha256": "812efe38d269cceafbc23f54913b3d3e3ef2177730f0bfcf9915287bb804bf44", + "compared_oracle_sha256": "812efe38d269cceafbc23f54913b3d3e3ef2177730f0bfcf9915287bb804bf44", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 50176, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ1_S-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "4e7645670f8d1e86c3aa84d9b63435bdbd241228eeea56cf39686a6280d3eaf1", + "oracle_file_sha256": "4e7645670f8d1e86c3aa84d9b63435bdbd241228eeea56cf39686a6280d3eaf1", + "compared_oracle_sha256": "4e7645670f8d1e86c3aa84d9b63435bdbd241228eeea56cf39686a6280d3eaf1", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 6400, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ1_S-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "f2a6a1a52667cf9cf4f822f9af52408880f21d9a1955d46e7704a3a21d191090", + "oracle_file_sha256": "f2a6a1a52667cf9cf4f822f9af52408880f21d9a1955d46e7704a3a21d191090", + "compared_oracle_sha256": "f2a6a1a52667cf9cf4f822f9af52408880f21d9a1955d46e7704a3a21d191090", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 6400, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ1_S-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "7d93653c10b72ce36a7bc4a6a46ec21eefd3d4704128f0281b8eeb4b018f1a02", + "oracle_file_sha256": "7d93653c10b72ce36a7bc4a6a46ec21eefd3d4704128f0281b8eeb4b018f1a02", + "compared_oracle_sha256": "7d93653c10b72ce36a7bc4a6a46ec21eefd3d4704128f0281b8eeb4b018f1a02", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 25600, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ1_S-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "5972de407abdee675d416358801507600103e60c5518d5a7e3dc61362d3e4fe9", + "oracle_file_sha256": "5972de407abdee675d416358801507600103e60c5518d5a7e3dc61362d3e4fe9", + "compared_oracle_sha256": "5972de407abdee675d416358801507600103e60c5518d5a7e3dc61362d3e4fe9", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 25600, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ4_NL-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "16184a3758d6b6f361b16cf741d5fe0d05ff8f7d866050ebdc3354915c57ad9e", + "oracle_file_sha256": "16184a3758d6b6f361b16cf741d5fe0d05ff8f7d866050ebdc3354915c57ad9e", + "compared_oracle_sha256": "16184a3758d6b6f361b16cf741d5fe0d05ff8f7d866050ebdc3354915c57ad9e", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 18432, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ4_NL-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "4f602b6088ab68c2631b7293a3e884785828a135de210d6fd8eb2b82b7bc69d9", + "oracle_file_sha256": "4f602b6088ab68c2631b7293a3e884785828a135de210d6fd8eb2b82b7bc69d9", + "compared_oracle_sha256": "4f602b6088ab68c2631b7293a3e884785828a135de210d6fd8eb2b82b7bc69d9", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 18432, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ4_NL-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "d7f5fb54d2e2c52429c669245858945ae1b0a6fcee09f24c8a21c7c7d71ab516", + "oracle_file_sha256": "d7f5fb54d2e2c52429c669245858945ae1b0a6fcee09f24c8a21c7c7d71ab516", + "compared_oracle_sha256": "d7f5fb54d2e2c52429c669245858945ae1b0a6fcee09f24c8a21c7c7d71ab516", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 73728, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ4_NL-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "2bf0d166828994d5497b4cb20400fbbc45c1fc0fd94a3380d525df16450b81a3", + "oracle_file_sha256": "2bf0d166828994d5497b4cb20400fbbc45c1fc0fd94a3380d525df16450b81a3", + "compared_oracle_sha256": "2bf0d166828994d5497b4cb20400fbbc45c1fc0fd94a3380d525df16450b81a3", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 73728, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ3_S-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "7843ff13e1c7f1475f949583ec0466b7cd3020723994d7c725e7c618c11c34f0", + "oracle_file_sha256": "8cad98f9fecbfcac883cb11a91df1ac703846dfe88bac12792ab3066420243ad", + "compared_oracle_sha256": "8cad98f9fecbfcac883cb11a91df1ac703846dfe88bac12792ab3066420243ad", + "byte_equal": false, + "max_abs_error": 0.12109375, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 14080, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ3_S-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "281888da0636914c257cd25407adc1465b2d40e96aa7694eb5c3bd0df4036b73", + "oracle_file_sha256": "7f36f4a4ba9f0977f68d452e8ec1d26ea299ea9ddbc82fd0ede324abc94d6595", + "compared_oracle_sha256": "7f36f4a4ba9f0977f68d452e8ec1d26ea299ea9ddbc82fd0ede324abc94d6595", + "byte_equal": false, + "max_abs_error": 0.125, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 14080, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ3_S-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "8932dbeb65d3716cfb60014ad471ab0fb5d2d2d4b037e8745464e65f77b936de", + "oracle_file_sha256": "ebcadd200e64857ed483aa7176172dc94b966198fb81d2910ab723260fb46fdc", + "compared_oracle_sha256": "ebcadd200e64857ed483aa7176172dc94b966198fb81d2910ab723260fb46fdc", + "byte_equal": false, + "max_abs_error": 0.12109375, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 56320, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ3_S-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "11a954e23ccc31f98a3398902b7ce96ec39f0fc0119d41202732630299d9a623", + "oracle_file_sha256": "88e55dfa1c9378436bd431db09fca5bf5aad9910dc311b493d6f94d1ec98dc7c", + "compared_oracle_sha256": "88e55dfa1c9378436bd431db09fca5bf5aad9910dc311b493d6f94d1ec98dc7c", + "byte_equal": false, + "max_abs_error": 0.125, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 56320, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_S-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "2c2908ecf0382e9e8d6414ca7bbacd8fe8ac95cc15dd5483d32293883801714f", + "oracle_file_sha256": "2c2908ecf0382e9e8d6414ca7bbacd8fe8ac95cc15dd5483d32293883801714f", + "compared_oracle_sha256": "2c2908ecf0382e9e8d6414ca7bbacd8fe8ac95cc15dd5483d32293883801714f", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 10496, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_S-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "22e25316adaf5931c49ef737972a2f1d612b90acb69a3ca76002effd2a43d195", + "oracle_file_sha256": "22e25316adaf5931c49ef737972a2f1d612b90acb69a3ca76002effd2a43d195", + "compared_oracle_sha256": "22e25316adaf5931c49ef737972a2f1d612b90acb69a3ca76002effd2a43d195", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 10496, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_S-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "90c3f52ffccbc2f83e5b66edaf5805f2e23967aea551d55d1216142a2e3cc9f4", + "oracle_file_sha256": "90c3f52ffccbc2f83e5b66edaf5805f2e23967aea551d55d1216142a2e3cc9f4", + "compared_oracle_sha256": "90c3f52ffccbc2f83e5b66edaf5805f2e23967aea551d55d1216142a2e3cc9f4", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 41984, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ2_S-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "68f4582c895e47c648f5a3e3972d991d38a49404f5d3dd1434a2e27b90096907", + "oracle_file_sha256": "68f4582c895e47c648f5a3e3972d991d38a49404f5d3dd1434a2e27b90096907", + "compared_oracle_sha256": "68f4582c895e47c648f5a3e3972d991d38a49404f5d3dd1434a2e27b90096907", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 41984, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ4_XS-256", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "bc2868543de19f14c38589e427629f77c0fd02a8a24d22d47570e7fa03250ae2", + "oracle_file_sha256": "bc2868543de19f14c38589e427629f77c0fd02a8a24d22d47570e7fa03250ae2", + "compared_oracle_sha256": "bc2868543de19f14c38589e427629f77c0fd02a8a24d22d47570e7fa03250ae2", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 17408, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ4_XS-256", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 1024, + "native_sha256": "1d664b63884d614512b6544cb085eb91626e7e20ebd05d9afca3e662bcbdeccc", + "oracle_file_sha256": "1d664b63884d614512b6544cb085eb91626e7e20ebd05d9afca3e662bcbdeccc", + "compared_oracle_sha256": "1d664b63884d614512b6544cb085eb91626e7e20ebd05d9afca3e662bcbdeccc", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 17408, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ4_XS-1024", + "dtype": "f32", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "c5d5b46955ae2c26887b015601e67cdaa3c4712910e1d743f58a0910f2cef889", + "oracle_file_sha256": "c5d5b46955ae2c26887b015601e67cdaa3c4712910e1d743f58a0910f2cef889", + "compared_oracle_sha256": "c5d5b46955ae2c26887b015601e67cdaa3c4712910e1d743f58a0910f2cef889", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 69632, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ4_XS-1024", + "dtype": "bf16", + "oracle": "primary", + "adaptation": null, + "elements": 4096, + "native_sha256": "b5d820d40868cc699f6d83fa2cc63f773b7c01c42af2fc961952261e4198a48d", + "oracle_file_sha256": "b5d820d40868cc699f6d83fa2cc63f773b7c01c42af2fc961952261e4198a48d", + "compared_oracle_sha256": "b5d820d40868cc699f6d83fa2cc63f773b7c01c42af2fc961952261e4198a48d", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 69632, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "MXFP4-256", + "dtype": "f32", + "oracle": "secondary", + "adaptation": null, + "elements": 1024, + "native_sha256": "aca27b230e9675ea214c31723306036025295c570903f8804d4d767b4fb0bdb2", + "oracle_file_sha256": "aca27b230e9675ea214c31723306036025295c570903f8804d4d767b4fb0bdb2", + "compared_oracle_sha256": "aca27b230e9675ea214c31723306036025295c570903f8804d4d767b4fb0bdb2", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 17408, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "MXFP4-256", + "dtype": "bf16", + "oracle": "secondary", + "adaptation": "upstream F32 output rounded to BF16 RNE", + "elements": 1024, + "native_sha256": "4b66106696144b4970929d2f5734d3ddf8e6e4580a2fe8910b500ebaab5431a9", + "oracle_file_sha256": "aca27b230e9675ea214c31723306036025295c570903f8804d4d767b4fb0bdb2", + "compared_oracle_sha256": "4b66106696144b4970929d2f5734d3ddf8e6e4580a2fe8910b500ebaab5431a9", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 17408, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "MXFP4-1024", + "dtype": "f32", + "oracle": "secondary", + "adaptation": null, + "elements": 4096, + "native_sha256": "a2688e4f8d766f642b8fbdebcbfff7e4e2720ae9fc57409812eb0a21f4bb6fec", + "oracle_file_sha256": "a2688e4f8d766f642b8fbdebcbfff7e4e2720ae9fc57409812eb0a21f4bb6fec", + "compared_oracle_sha256": "a2688e4f8d766f642b8fbdebcbfff7e4e2720ae9fc57409812eb0a21f4bb6fec", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 69632, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "MXFP4-1024", + "dtype": "bf16", + "oracle": "secondary", + "adaptation": "upstream F32 output rounded to BF16 RNE", + "elements": 4096, + "native_sha256": "cdd6e95bc3bc3e18bc014dee2cdb125cb179b670256896536b0e3822b0adfa83", + "oracle_file_sha256": "a2688e4f8d766f642b8fbdebcbfff7e4e2720ae9fc57409812eb0a21f4bb6fec", + "compared_oracle_sha256": "cdd6e95bc3bc3e18bc014dee2cdb125cb179b670256896536b0e3822b0adfa83", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 69632, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ1_XXXS-256", + "dtype": "f32", + "oracle": "secondary", + "adaptation": null, + "elements": 1024, + "native_sha256": "b4707ef68fb11c9d3720db82722924de4004e75c97d07cdbd0b24c08f3677fce", + "oracle_file_sha256": "b4707ef68fb11c9d3720db82722924de4004e75c97d07cdbd0b24c08f3677fce", + "compared_oracle_sha256": "b4707ef68fb11c9d3720db82722924de4004e75c97d07cdbd0b24c08f3677fce", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 4864, + "output_bytes": 4096, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ1_XXXS-256", + "dtype": "bf16", + "oracle": "secondary", + "adaptation": "upstream F32 output rounded to BF16 RNE", + "elements": 1024, + "native_sha256": "9de69ca2d01fda18f05e9ee7ac531f3cb806d39a3af8d10e64ba0c53dab1b08a", + "oracle_file_sha256": "b4707ef68fb11c9d3720db82722924de4004e75c97d07cdbd0b24c08f3677fce", + "compared_oracle_sha256": "9de69ca2d01fda18f05e9ee7ac531f3cb806d39a3af8d10e64ba0c53dab1b08a", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 4864, + "output_bytes": 2048, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ1_XXXS-1024", + "dtype": "f32", + "oracle": "secondary", + "adaptation": null, + "elements": 4096, + "native_sha256": "10b121b53bde30b8e24ea1fb6ef8bb4f3123952900c2c66886d2e09b40ee62c0", + "oracle_file_sha256": "10b121b53bde30b8e24ea1fb6ef8bb4f3123952900c2c66886d2e09b40ee62c0", + "compared_oracle_sha256": "10b121b53bde30b8e24ea1fb6ef8bb4f3123952900c2c66886d2e09b40ee62c0", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 19456, + "output_bytes": 16384, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + }, + { + "name": "IQ1_XXXS-1024", + "dtype": "bf16", + "oracle": "secondary", + "adaptation": "upstream F32 output rounded to BF16 RNE", + "elements": 4096, + "native_sha256": "14e07510990f222b0656fdbacd1a3d6271c28e00526587b67c4a1b399674c3d5", + "oracle_file_sha256": "10b121b53bde30b8e24ea1fb6ef8bb4f3123952900c2c66886d2e09b40ee62c0", + "compared_oracle_sha256": "14e07510990f222b0656fdbacd1a3d6271c28e00526587b67c4a1b399674c3d5", + "byte_equal": true, + "max_abs_error": 0.0, + "tolerance_failures": 0, + "first_failures": [], + "finite": true, + "native_memory": { + "table_bytes": 19456, + "output_bytes": 8192, + "scratch_bytes": 16, + "selected_packed_bytes": 0, + "selections": 1 + } + } + ], + "summary": { + "cases": 76, + "primary_cases": 64, + "secondary_cases": 12, + "byte_equal_cases": 68, + "within_tolerance_cases": 76, + "max_abs_error": 0.125, + "inputs_reverified": true + } +} diff --git a/docs/bench-evidence/rocm-quant-gather/oracle-audit-arithmetic-explanation.json b/docs/bench-evidence/rocm-quant-gather/oracle-audit-arithmetic-explanation.json new file mode 100644 index 000000000..e3e167a67 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/oracle-audit-arithmetic-explanation.json @@ -0,0 +1,235 @@ +{ + "kind": "Diagnostic transcription of source expressions only. The actual GPU output files remain the evidence.", + "native_source_hashes": { + "rocm_quant_dequant.h": "56b14d63308a6c3d8c19a6619217470fac88dd58599f95b4d9bf919f854f732d", + "rocm_quant_iq_tables.h": "d267d25ff1dd3f67749c251f87047f4b70c9650a99d04b524ff6c3313596a349" + }, + "source_provenance": "Current source snapshot after author comment corrections, not the native-v2 source seal. Comparison uses frozen native-v2 runtime outputs.", + "iq3_s_table_entries_with_difference": 146, + "iq3_s_table_byte_differences": 150, + "iq3_s_only_difference": { + "plugin_raw": 62, + "plugin_effective": 15.5, + "native": 15 + }, + "cases": [ + { + "name": "Q6_K-256", + "elements": 1024, + "arms": { + "native": { + "f32_source_expression_byte_exact": true, + "bf16_source_expression_byte_exact": true + }, + "primary": { + "f32_source_expression_byte_exact": true, + "bf16_source_expression_byte_exact": true + } + }, + "f32_difference_examples": [ + { + "row": 0, + "col": 36, + "d": 0.00048828125, + "scale": 115, + "q": -19, + "integer_product": -2185, + "rounded_half_integer_product": -2184.0, + "native": -1.06689453125, + "primary": -1.06640625, + "absolute_difference": 0.00048828125 + }, + { + "row": 0, + "col": 38, + "d": 0.00048828125, + "scale": 115, + "q": -19, + "integer_product": -2185, + "rounded_half_integer_product": -2184.0, + "native": -1.06689453125, + "primary": -1.06640625, + "absolute_difference": 0.00048828125 + }, + { + "row": 0, + "col": 46, + "d": 0.00048828125, + "scale": 115, + "q": 23, + "integer_product": 2645, + "rounded_half_integer_product": 2644.0, + "native": 1.29150390625, + "primary": 1.291015625, + "absolute_difference": 0.00048828125 + } + ], + "f32_different_elements": 34 + }, + { + "name": "Q6_K-1024", + "elements": 4096, + "arms": { + "native": { + "f32_source_expression_byte_exact": true, + "bf16_source_expression_byte_exact": true + }, + "primary": { + "f32_source_expression_byte_exact": true, + "bf16_source_expression_byte_exact": true + } + }, + "f32_difference_examples": [ + { + "row": 0, + "col": 36, + "d": 0.00048828125, + "scale": 115, + "q": -19, + "integer_product": -2185, + "rounded_half_integer_product": -2184.0, + "native": -1.06689453125, + "primary": -1.06640625, + "absolute_difference": 0.00048828125 + }, + { + "row": 0, + "col": 38, + "d": 0.00048828125, + "scale": 115, + "q": -19, + "integer_product": -2185, + "rounded_half_integer_product": -2184.0, + "native": -1.06689453125, + "primary": -1.06640625, + "absolute_difference": 0.00048828125 + }, + { + "row": 0, + "col": 46, + "d": 0.00048828125, + "scale": 115, + "q": 23, + "integer_product": 2645, + "rounded_half_integer_product": 2644.0, + "native": 1.29150390625, + "primary": 1.291015625, + "absolute_difference": 0.00048828125 + } + ], + "f32_different_elements": 153 + }, + { + "name": "IQ3_S-256", + "elements": 1024, + "arms": { + "native": { + "f32_source_expression_byte_exact": true, + "bf16_source_expression_byte_exact": true + }, + "primary": { + "f32_source_expression_byte_exact": true, + "bf16_source_expression_byte_exact": true + } + }, + "f32_difference_examples": [ + { + "row": 0, + "col": 6, + "d": 0.0078125, + "scale_nibble": 1, + "index": 101, + "grid_byte": 2, + "plugin_grid_value": 62, + "native_grid_value": 15, + "native": -0.3515625, + "primary": -0.36328125, + "absolute_difference": 0.01171875 + }, + { + "row": 0, + "col": 28, + "d": 0.0078125, + "scale_nibble": 1, + "index": 265, + "grid_byte": 0, + "plugin_grid_value": 62, + "native_grid_value": 15, + "native": 0.3515625, + "primary": 0.36328125, + "absolute_difference": 0.01171875 + }, + { + "row": 0, + "col": 39, + "d": 0.0078125, + "scale_nibble": 6, + "index": 509, + "grid_byte": 3, + "plugin_grid_value": 62, + "native_grid_value": 15, + "native": -1.5234375, + "primary": -1.57421875, + "absolute_difference": 0.05078125 + } + ], + "f32_different_elements": 62 + }, + { + "name": "IQ3_S-1024", + "elements": 4096, + "arms": { + "native": { + "f32_source_expression_byte_exact": true, + "bf16_source_expression_byte_exact": true + }, + "primary": { + "f32_source_expression_byte_exact": true, + "bf16_source_expression_byte_exact": true + } + }, + "f32_difference_examples": [ + { + "row": 0, + "col": 6, + "d": 0.0078125, + "scale_nibble": 1, + "index": 101, + "grid_byte": 2, + "plugin_grid_value": 62, + "native_grid_value": 15, + "native": -0.3515625, + "primary": -0.36328125, + "absolute_difference": 0.01171875 + }, + { + "row": 0, + "col": 28, + "d": 0.0078125, + "scale_nibble": 1, + "index": 265, + "grid_byte": 0, + "plugin_grid_value": 62, + "native_grid_value": 15, + "native": 0.3515625, + "primary": 0.36328125, + "absolute_difference": 0.01171875 + }, + { + "row": 0, + "col": 39, + "d": 0.0078125, + "scale_nibble": 6, + "index": 509, + "grid_byte": 3, + "plugin_grid_value": 62, + "native_grid_value": 15, + "native": -1.5234375, + "primary": -1.57421875, + "absolute_difference": 0.05078125 + } + ], + "f32_different_elements": 303 + } + ] +} diff --git a/docs/bench-evidence/rocm-quant-gather/oracle-audit-artifact-manifest.json b/docs/bench-evidence/rocm-quant-gather/oracle-audit-artifact-manifest.json new file mode 100644 index 000000000..cef7ff562 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/oracle-audit-artifact-manifest.json @@ -0,0 +1,101 @@ +{ + "scope": "Read-only frozen operation-oracle audit", + "files": { + "arithmetic-explanation.json": { + "bytes": 6572, + "sha256": "c04d32e481ef747672ed1d257206ea36968109e7a8c64bb2c6361d6e301966b7" + }, + "audit_frozen.py": { + "bytes": 5841, + "sha256": "3f18f3da69fd097a993dbd7b9ae075de45ea032a723b81808fd485b72550cd6d" + }, + "executing-source-artifacts.json": { + "bytes": 1951, + "sha256": "4eab933a9e2e85cae2929cdf46e27a95ed0341193551a7db495cca2caec4794d" + }, + "explain_arithmetic-current-source.py": { + "bytes": 6191, + "sha256": "7b10ad36c9bbfa87fc1c274a6b17fcf4cec26fc0a915c69c1e457ddf1ff26f48" + }, + "explain_arithmetic-v2-source-guard.py": { + "bytes": 6008, + "sha256": "21d47f226d555e218dd6b98de89ae4ab01dfc075eadce25eef91da4137d23ba7" + }, + "explain_arithmetic.py": { + "bytes": 6008, + "sha256": "21d47f226d555e218dd6b98de89ae4ab01dfc075eadce25eef91da4137d23ba7" + }, + "fork-binary-symbols.txt": { + "bytes": 240, + "sha256": "26109dc2d2ef7ed403d7fc7cbca45096377de93503ae113c4ffd4c4a0c32443c" + }, + "generated-primary/dequantize_hip.cuh": { + "bytes": 22787, + "sha256": "497842aca4744b903c7fd19b6069be33fa50da9d4bb893634eda46ab9cb35ddd" + }, + "generated-primary/dispatch_utils.h": { + "bytes": 483, + "sha256": "7a17e8ac27b25426fbfd2921d2ebcad6410b703736204e55e832037fd9f250cc" + }, + "generated-primary/ggml-common_hip.h": { + "bytes": 85590, + "sha256": "b7d415d0cb626afb330cc67867418943b1ebe39eb648988f637b4f29af8e8a41" + }, + "generated-primary/gguf_kernel.hip": { + "bytes": 22272, + "sha256": "f714989ddbd4c97bdcd924d5ca3316c60efdebcdffa5c9c818a93579023e4d72" + }, + "generated-primary/torch_bindings.cpp": { + "bytes": 2363, + "sha256": "4fb80d903a1e860a080a04033b6a41eeb840b2bc68220fc509a0db5a5f1cafa7" + }, + "hash-audit.json": { + "bytes": 15914, + "sha256": "86d02da770d682fe11e3360c760c5d27096d5180a17114c2f46f6b2ae04a1341" + }, + "independent-audit.json": { + "bytes": 1591, + "sha256": "747faf446d92f45c645948c7fbda87552ed996736a29eee55069c6893716c26b" + }, + "isolated-agent-onboard-result.json": { + "bytes": 362, + "sha256": "75a643bf8395e6b5f52e9230d50f49f8574e1d1ea3959be697633dd84720608e" + }, + "isolated-agent-onboard.log": { + "bytes": 138, + "sha256": "0fd19afd79de4dc7e059bf9415f7cced93739f51df61127a5ab09c88e92a74ff" + }, + "native-expression-source/rocm_quant_dequant.h": { + "bytes": 24598, + "sha256": "56b14d63308a6c3d8c19a6619217470fac88dd58599f95b4d9bf919f854f732d" + }, + "native-expression-source/rocm_quant_iq_tables.h": { + "bytes": 110865, + "sha256": "d267d25ff1dd3f67749c251f87047f4b70c9650a99d04b524ff6c3313596a349" + }, + "plugin-source-audit.json": { + "bytes": 323, + "sha256": "35b3cd72b0a1fe6c91c641ed169a19326fc052a6354d0c74f2549806a24979ef" + }, + "primary-output-stats.json": { + "bytes": 12439, + "sha256": "88dc6f64749d5d8152b4d128f63e59323e2aa77d51961588cb846e7836e83652" + }, + "report.md": { + "bytes": 9252, + "sha256": "ca646cdd818958214927f5cb5751efc3a111f29a64007432a4506f417bab956a" + }, + "runtime-source-checks.json": { + "bytes": 358, + "sha256": "23e7fd990779705883e0be0da456e9fe22b8c41f45bc5e20906f58861b5f695a" + }, + "secondary-git-identity.json": { + "bytes": 298, + "sha256": "3fd31d2cd85e273181b1dcf97eec92dcf4e43da564fc959b7220cb6b479444af" + }, + "stock-binary-symbols.txt": { + "bytes": 197, + "sha256": "01bc5a8662f9c4a2164444ee140433681d489def952ce6795572becd05c7eab2" + } + } +} diff --git a/docs/bench-evidence/rocm-quant-gather/oracle-audit-executing-source-artifacts.json b/docs/bench-evidence/rocm-quant-gather/oracle-audit-executing-source-artifacts.json new file mode 100644 index 000000000..8d48104d1 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/oracle-audit-executing-source-artifacts.json @@ -0,0 +1,48 @@ +{ + "stock": { + "binary_sha256": "7b9a2e2d0dc95afbf592b5b1678bdc67e0fe2204529f1afe3b0b1f03566f28c2", + "symbols": [ + "00000000003b5a80 T dequantize_row_mxfp4", + "00000000003c3330 T dequantize_row_q8_K", + "000000000035e960 T ggml_get_rows", + "000000000035eaa0 T ggml_get_rows_back", + "000000000028b1c0 T ggml_graph_compute_with_ctx" + ] + }, + "fork": { + "binary_sha256": "cad537f239dc0c4ca70e5b80548f39f297117494269ca2b9b5de8191aa2f4bc1", + "symbols": [ + "00000000003b9d50 T dequantize_row_iq1_xxxs", + "00000000003aaf60 T dequantize_row_mxfp4", + "00000000003bbfe0 T dequantize_row_q8_K", + "000000000034e440 T ggml_get_rows", + "000000000034e580 T ggml_get_rows_back", + "000000000027a0e0 T ggml_graph_compute_with_ctx" + ] + }, + "gguf/gguf_kernel.hip": { + "sha256": "f714989ddbd4c97bdcd924d5ca3316c60efdebcdffa5c9c818a93579023e4d72", + "bytes": 22272, + "copy": "/home/vikash/.cache/rdna3-gather-oracle-review/generated-primary/gguf_kernel.hip" + }, + "gguf/dequantize_hip.cuh": { + "sha256": "497842aca4744b903c7fd19b6069be33fa50da9d4bb893634eda46ab9cb35ddd", + "bytes": 22787, + "copy": "/home/vikash/.cache/rdna3-gather-oracle-review/generated-primary/dequantize_hip.cuh" + }, + "gguf/ggml-common_hip.h": { + "sha256": "b7d415d0cb626afb330cc67867418943b1ebe39eb648988f637b4f29af8e8a41", + "bytes": 85590, + "copy": "/home/vikash/.cache/rdna3-gather-oracle-review/generated-primary/ggml-common_hip.h" + }, + "dispatch_utils.h": { + "sha256": "7a17e8ac27b25426fbfd2921d2ebcad6410b703736204e55e832037fd9f250cc", + "bytes": 483, + "copy": "/home/vikash/.cache/rdna3-gather-oracle-review/generated-primary/dispatch_utils.h" + }, + "torch_bindings.cpp": { + "sha256": "4fb80d903a1e860a080a04033b6a41eeb840b2bc68220fc509a0db5a5f1cafa7", + "bytes": 2363, + "copy": "/home/vikash/.cache/rdna3-gather-oracle-review/generated-primary/torch_bindings.cpp" + } +} diff --git a/docs/bench-evidence/rocm-quant-gather/oracle-audit-independent-audit.json b/docs/bench-evidence/rocm-quant-gather/oracle-audit-independent-audit.json new file mode 100644 index 000000000..cd634175c --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/oracle-audit-independent-audit.json @@ -0,0 +1,52 @@ +{ + "primary-synthetic-v1.json": { + "sha256": "6bc9501cf0abe9a8de36bcc652b636ff5a26df3dbb650ad38dcc0ab098fee9f8", + "verified_files": 80 + }, + "secondary-frozen-v1.json": { + "sha256": "4baa265386ee5d67a0dfb056b42a4650d65a29a8446e3df5a30a7778980b6f21", + "verified_files": 53 + }, + "plugin_artifact": { + "verified_files": 138 + }, + "stock_source": { + "pin": "10bf611e533d81f739128304991c5e133c6aebd8", + "archive": { + "bytes": 171663360, + "sha256": "0f43551d3da94ba0d2af80e202177008a91966de66dbabf87a2042377d16d133" + }, + "verified_git_blobs_and_exported_files": 3425, + "original_artifact_files": 0 + }, + "fork_source": { + "pin": "36fe8e1cc7f2b3b8c92fdda0ab07600141921786", + "archive": { + "bytes": 170752000, + "sha256": "be6761fc65927e10aa1cad664ca5a459fa0f3776c30230cd7acff564c981f93e" + }, + "verified_git_blobs_and_exported_files": 3317, + "original_artifact_files": 0 + }, + "plugin_source": { + "pin": "d4c1f0d082fc7cd4350da56689109a01c1f29d6c", + "archive": { + "bytes": 952320, + "sha256": "090d8fd5b6cc52404508fbd4d77f38c8f9d04696b98c778e9220447f3310df39" + }, + "verified_git_blobs_and_exported_files": 150, + "original_artifact_files": 122 + }, + "primary_outputs": { + "report": { + "bytes": 44161, + "sha256": "867aaf215887b2c18f46b20b9211592550274099f721b4fff73cefb2f171dd38" + }, + "verified_outputs": 64, + "finite_nontrivial_distinct_selected_rows_and_repeated_id_bytes": true + }, + "secondary_outputs": { + "verified_operations": 6, + "confirmed_model_exit_minus6": 2 + } +} diff --git a/docs/bench-evidence/rocm-quant-gather/oracle-audit-report.md b/docs/bench-evidence/rocm-quant-gather/oracle-audit-report.md new file mode 100644 index 000000000..0220243d1 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/oracle-audit-report.md @@ -0,0 +1,59 @@ +**PASS: frozen operation-oracle evidence.** No finding invalidates the 64 primary operation outputs or six secondary F32 operation outputs. This is a bounded source and evidence audit, not fresh review of the gather implementation. Model qualification, production reachability, mutation testing, original fixture coverage, and trace acceptance remain outside this PASS. + +The reviewed spec is `.agents/specs/rocm-quant-gather.md` at `2e5adfb85a255528bffa5d3cdb016efb2bab70d8`. The read-only review worktree is `/home/vikash/vllm.cpp-rdna3-gather-oracle-review`. It remains clean. The auditor performed no GPU run, dependency installation, download, tracked-file edit, publication, merge, or CI action. + +The independent identity audit verified: + +- All 80 files in primary freeze `6bc9501cf0abe9a8de36bcc652b636ff5a26df3dbb650ad38dcc0ab098fee9f8`. +- All 53 files in secondary freeze `4baa265386ee5d67a0dfb056b42a4650d65a29a8446e3df5a30a7778980b6f21`. +- All 138 plugin artifact files, including extension `592af79c210496e96eaa7bd409ae0a67e7de8c334aa9f782082c7639ba300138`. +- All 150 plugin archive files against Git blobs at `d4c1f0d082fc7cd4350da56689109a01c1f29d6c`, the extracted files, and 122 original installed source files. Archive SHA-256: `090d8fd5b6cc52404508fbd4d77f38c8f9d04696b98c778e9220447f3310df39`. +- All 3,425 stock archive files against Git blobs at `10bf611e533d81f739128304991c5e133c6aebd8` and the extracted files. +- All 3,317 fork archive files against Git blobs at `36fe8e1cc7f2b3b8c92fdda0ab07600141921786` and the extracted files. +- The active vLLM source HEAD is `e126687a9a828d513c01a07cd69f025f27d63280`, with no tracked changes. Executing runtime copies of `vllm/utils/torch_utils.py` and `vllm/platforms/rocm.py` equal that source byte-for-byte. + +The primary harness SHA-256 is `1ddd29da328db6817b5b15119c228cad55b1f2d4e5acc143c80d70966a5c2d75`. At `primary.py:88-102`, it loads original packed bytes as uint8, restores four i32 file IDs to a 2-by-2 torch.long tensor, and executes the registered plugin operation. The dense control calls upstream `gguf.dequantize`, converts the dense tensor to the requested output dtype, and calls `torch.embedding`. Its `atol=0.01`, `rtol=0.04`, ID arrangement, widths 256 and 1024, and dtype conversion agree with plugin `tests/test_kernels.py:102-124`. IQ1_M and F16 exclusions are explicit. + +All 64 output hashes match report `867aaf215887b2c18f46b20b9211592550274099f721b4fff73cefb2f171dd38`. Every output is finite and nontrivial. The three distinct selected rows differ, and repeated row 0 reproduces identical bytes. Every input ID vector is `[0,127,64,0]`. Output and selected-packed byte counts agree with the tensor geometry. These are generated 128-row tables. They do not preserve or replace the 32 original upstream GGUF fixtures. + +The actual primary call chain is supported by source and the operator's successful run: + +- Plugin `quantization/vocal_embeds.py:112-118` registers the operation through active vLLM `utils/torch_utils.py:1068-1079`. `platforms/rocm.py:502` supplies the CUDA dispatch key used for HIP tensors. +- Plugin `vocal_embeds.py:79-96` flattens IDs, selects packed rows with `torch.index_select`, dequantizes only those selected rows, and restores the output shape. +- Plugin `ops.py:93-101,181-186` uses exactly the predicate logged as `native_extension`. All 64 recorded values are true. The harness does not alter that predicate or dispatch. +- `csrc/torch_bindings.cpp:43-44` selects `ggml_dequantize`. Generated `csrc/gguf/gguf_kernel.hip:88-102` allocates the requested output dtype and dispatches `ggml_get_to_cuda`. +- Generated `dequantize_hip.cuh:530-569` selects the format decoder. Its launch wrappers are at lines 440-526. Generated source copies and hashes are retained in `generated-primary/` and `executing-source-artifacts.json`. + +This establishes the native HIP path by source-plus-run evidence. It is not a profiler trace. No Triton kernel execution or invocation-parity claim is made. The capture's dense control intentionally expands a full table; total-process memory cannot therefore be attributed entirely to the compressed plugin operation. + +The secondary harness SHA-256 is `09773359f3db39d5c759d03e37e42f4e466f6e33cb063cd2eb9bbf1353b04dbb`. Its CMake target links the exact private CPU oracle builds. No decoder is transcribed in the harness. + +- `secondary.cpp:55-61` calls stock `ggml/src/ggml-quants.c:2807-2815::dequantize_row_q8_K` directly for each selected row. Stock GET_ROWS excludes Q8_K at `ggml/src/ggml-cpu/ops.cpp:5023-5052`. This is the specified adaptation. +- `secondary.cpp:68-80` builds and computes an actual GET_ROWS graph for MXFP4 and IQ1_XXXS. Stock `ggml.c:3891-3909` creates the F32 output. `ggml-cpu.c:1864-1866,3432-3437` executes the CPU graph. +- Stock `ggml-cpu/ops.cpp:4850-4890,5032-5051` selects `to_float`. `ggml.c:751-756` routes MXFP4 to `ggml-quants.c:569-586`. +- Fork `ggml-cpu/ops.cpp:5063-5069` admits IQ1_XXXS. `ggml.c:871-876` routes it to `ggml-quants.c:2727-2751` and the fork's own codebook. + +All six operator output files match their recorded hashes and the author's prior outputs byte-for-byte. The stock binary hash is `7b9a2e2d0dc95afbf592b5b1678bdc67e0fe2204529f1afe3b0b1f03566f28c2`. The fork binary hash is `cad537f239dc0c4ca70e5b80548f39f297117494269ca2b9b5de8191aa2f4bc1`. This capture uses contiguous synthetic tables and IDs. It does not claim the complete upstream test parameter matrix or secondary BF16 execution. + +The operator requested an additional numerical explanation. `arithmetic-explanation.json` reproduces all elements of 16 captured files: Q6_K and IQ3_S, two widths, two output dtypes, and both native and primary arms. These CPU calculations are diagnostic transcriptions of source expressions. They are not replacement oracle results. + +Q6_K differs through intermediate precision. Plugin `dequantize_hip.cuh:248-257` rounds `scale * quant` to FP16 and multiplies in FP16 before output conversion. The local implementation uses F32 products. For example, `115 * -19 = -2185` becomes `-2184` in FP16. With delta `1/2048`, the outputs are `-1.06689453125` and `-1.06640625`. + +IQ3_S differs through its codebook, not rounding. Across 512 words, 150 byte positions in 146 words differ exclusively as plugin `62/4 = 15.5` versus local `15`. Plugin `ggml-common_hip.h:686` defines that table, and `dequantize_hip.cuh:347-353` applies its quarter-scale factor. The local codebook matches the stock representation. The 3.333% difference relative to local magnitude fits the original 4% relative tolerance. It is not byte equality or model token equality. + +The diagnostic initially rejected a changed native header hash. That failed guard remains in `explain_arithmetic-v2-source-guard.py`. The successful calculation uses a copied current header with SHA-256 `56b14d63308a6c3d8c19a6619217470fac88dd58599f95b4d9bf919f854f732d`, after the author's comment corrections, and table hash `d267d25ff1dd3f67749c251f87047f4b70c9650a99d04b524ff6c3313596a349`. Its comparison files are the frozen v2 runtime outputs. It makes no exact-v2 source-seal claim. The operator comparison report is `84bac44682927c28a9921e0dd464c1474039d53633fe53d008a14887cf807024`. + +One medium-severity qualification concern remains: secondary model cache geometry differs from the committed specification. `secondary.cpp:99-106` requests context 64 and BF16 KV. Both logs report 256 KV cells and approximately 0.06 MiB of KV payload. Stock `src/llama-context.cpp:288,294` explicitly pads context to 256. The spec requires 64 cells and 16,384 bytes. Record and resolve this upstream padding adaptation before claiming matched model memory. + +Both secondary bounded models abort on the first decode with SIGABRT. The observed stack includes `llm_graph_input_mem_hybrid::set_input` and `ggml-backend.cpp:194::GGML_ASSERT(buffer)`. Source `llama-graph.cpp:1078-1079` is consistent with an unallocated recurrent `s_copy` input. That object attribution remains an inference. Neither run emits tokens. Primary bounded-model qualification remains PENDING as separately recorded by the operator. The 32 original fixtures, model token equality, model cache adaptation, trace gate, and fork issue #933 remain PENDING under their existing ownership. + +Reproduction commands: + +```sh +python3 /home/vikash/.cache/rdna3-gather-oracle-review/audit_frozen.py +python3 /home/vikash/.cache/rdna3-gather-oracle-review/explain_arithmetic-current-source.py +``` + +Both commands exited 0. The first writes `independent-audit.json`; the second writes `arithmetic-explanation.json`. Neither command uses a GPU or changes tracked files. + +`REV-MUTATION` and product `REV-FULL-GATE` are N/A for this explicitly scoped read-only evidence audit. The startup `scripts/agent-preflight.sh` completed with exit 1: one `test_agent_onboard` failure and 12 skips. The failure expected scratch Git branch `master` but inherited `main`. Its isolated rerun passed all 39 tests with `GIT_CONFIG_GLOBAL=/dev/null`, an external `TMPDIR`, and matching `GIT_CEILING_DIRECTORIES`. Exact command, environment, and output are retained in the isolated-test artifacts. The startup preflight is not reported as green. No second full preflight ran. diff --git a/docs/bench-evidence/rocm-quant-gather/plugin-artifact-sha256.json b/docs/bench-evidence/rocm-quant-gather/plugin-artifact-sha256.json new file mode 100644 index 000000000..62a81fd61 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/plugin-artifact-sha256.json @@ -0,0 +1,140 @@ +{ + "vllm_gguf_plugin/_C_gguf.abi3.so": "592af79c210496e96eaa7bd409ae0a67e7de8c334aa9f782082c7639ba300138", + "vllm_gguf_plugin/__init__.py": "3e047fe518dc5b3f7ca2e2068cc6921b8b82c84cc87d23e79807a4cc6ccb0a04", + "vllm_gguf_plugin/config_parser.py": "a49b946f6374aa12a14a6517cd2f0140271818e59881a87f0238024b211f7984", + "vllm_gguf_plugin/csrc/cuda_compat.h": "959bc9e0e73e020d777530b18bf12160d35cc4eb976335955395729700b2f975", + "vllm_gguf_plugin/csrc/dispatch_utils.h": "7a17e8ac27b25426fbfd2921d2ebcad6410b703736204e55e832037fd9f250cc", + "vllm_gguf_plugin/csrc/gguf/dequantize.cuh": "96c25644ffba8ec6b9beffb7b1c30435e9b0e0466def1d4721f7f8aab401c7e5", + "vllm_gguf_plugin/csrc/gguf/dequantize_hip.cuh": "497842aca4744b903c7fd19b6069be33fa50da9d4bb893634eda46ab9cb35ddd", + "vllm_gguf_plugin/csrc/gguf/ggml-common.h": "990b6aca44615eaf39a3fa76b65992e1101cf1c4d27ec3a36070074f9f83136b", + "vllm_gguf_plugin/csrc/gguf/ggml-common_hip.h": "b7d415d0cb626afb330cc67867418943b1ebe39eb648988f637b4f29af8e8a41", + "vllm_gguf_plugin/csrc/gguf/gguf_kernel.cu": "4da2c6a6c0f9b0e60661f8334f2d356322f6f4f443b51dcfa570c4da57291e38", + "vllm_gguf_plugin/csrc/gguf/gguf_kernel.hip": "f714989ddbd4c97bdcd924d5ca3316c60efdebcdffa5c9c818a93579023e4d72", + "vllm_gguf_plugin/csrc/gguf/mmq.cuh": "1a3a8fb8cd9d1682a421bba53df92fdb323f7ba00956ab04bced4865cf9ad030", + "vllm_gguf_plugin/csrc/gguf/mmq_hip.cuh": "0e4a23bb4a8f2f9f7769ead653d9d2d72d16901ad9974d3aa3ba9972ee80ca34", + "vllm_gguf_plugin/csrc/gguf/mmvq.cuh": "f46667f8c09a7ca8b90fd4b7c89a5eca54cca99372762c3c2853870874d6e829", + "vllm_gguf_plugin/csrc/gguf/mmvq_hip.cuh": "38231c4faa337935c65562cf7f336761d13dd06bb19309e3e5a8f68a9f1ad448", + "vllm_gguf_plugin/csrc/gguf/moe.cuh": "9e7510e259ed6a4ce9ff18743628b16a9a10f1fcac44553c450bee1684f6bf25", + "vllm_gguf_plugin/csrc/gguf/moe_hip.cuh": "9e3358731eb607a97272f13a02314deb3db6f76026e77622570bfd2a2ae2b7bb", + "vllm_gguf_plugin/csrc/gguf/moe_vec.cuh": "dbe05b1a3515ebf3b2f3d07264f742566eb9f01bef769f46b2f90442a18633da", + "vllm_gguf_plugin/csrc/gguf/moe_vec_hip.cuh": "acbe6bf9625fe73ac96c0f87cdf43def66dc23643155977aedaafd84348192c9", + "vllm_gguf_plugin/csrc/gguf/vecdotq.cuh": "4972eddb514db4a12a996e667905a86fe8ce0f0f42e9839dd2db75774ad5d326", + "vllm_gguf_plugin/csrc/gguf/vecdotq_hip.cuh": "38caef027a395cf9d0285f67beb051e0432d74ef194a8d44b4cb820e927fa013", + "vllm_gguf_plugin/csrc/hip_compat.h": "25d7d6b1dab03d8d85a71976e5955dd6b91ea6ed6442713145770ebcc5d91abe", + "vllm_gguf_plugin/csrc/torch_bindings.cpp": "4fb80d903a1e860a080a04033b6a41eeb840b2bc68220fc509a0db5a5f1cafa7", + "vllm_gguf_plugin/gguf_files.py": "82e003351d59c7abd78477c6df244d1cd06cd8834c0a8db4a5fbf43144d57c3a", + "vllm_gguf_plugin/gguf_utils.py": "d790422af5161db802845cfdb3ff293bd34b9dab50461c0e477c1f1edea5ee8c", + "vllm_gguf_plugin/loader.py": "8c80ecb5fadecf60c603274ceeb3cd84500a8c6f915ea52b86d307e4775f2b2f", + "vllm_gguf_plugin/ops.py": "daac821e871ff73df30b1836c17a7ef9574f8be6e4bedd5f6456c442b69c90db", + "vllm_gguf_plugin/plugin.py": "f414bfc427b5e9142408bb1be23a71d23fb451327ff9182142f1aa5f91f05f1a", + "vllm_gguf_plugin/quantization/__init__.py": "b6755dbcdb6ec7aba9434271dc162d0d7c31e813d6b9e434699f21164ac18d1b", + "vllm_gguf_plugin/quantization/config.py": "18553e34317ffdab94b193439db428aec1af0d000444998c18eafb9397714370", + "vllm_gguf_plugin/quantization/diffusion_config.py": "6970775f14c91286d061fb63e4d8353713108de374782c8d51dfc7785e08b359", + "vllm_gguf_plugin/quantization/fused_moe.py": "bf195f8586bf6f0231e6b4e80c392fab1e39674590f89b482d6c8a279c4f80ab", + "vllm_gguf_plugin/quantization/layout.py": "6ffb4c25b6e862a3953ff8d00fba3c9a59febbafd791cb15ae0c44f0404ef799", + "vllm_gguf_plugin/quantization/linear.py": "b40556bc026632e610adaee2855d42ddc3d00d99ba07fdfee7cae171ec180efe", + "vllm_gguf_plugin/quantization/params.py": "18032548702812fe5180e2eefe7139a49ec990cf30159672021b36d8345e693b", + "vllm_gguf_plugin/quantization/utils.py": "9ffd3ca8f69d5fe0f5121576d4dfa1264c3d93bf277a8044a54e6c4471fbe9e5", + "vllm_gguf_plugin/quantization/vocal_embeds.py": "8312ad417b7d680d200f6f277011230ca7d2ea6f424c9aadab583b70ed032cb9", + "vllm_gguf_plugin/triton/__init__.py": "6c6ec57de9f82ef42d82760f144a4571cb16b3cd6de33aaa7aa9fd65e8ab1fa1", + "vllm_gguf_plugin/triton/dequantize/__init__.py": "249b99a046d4aa0d60a34b8dd2695ea64836d02e5c7cee2b2682b3578a0fd1fe", + "vllm_gguf_plugin/triton/dequantize/interface.py": "fa7f5cd35eae43068f798ba154c787e0719ca0401ace3af72754c3be0e7e4705", + "vllm_gguf_plugin/triton/dequantize/iq_quant/__init__.py": "484c1f66ed156f26dc558dee8111ec6aef969d0af6bed784193ceb148e1d01fd", + "vllm_gguf_plugin/triton/dequantize/iq_quant/iq1_m.py": "735412106ed9d36db56cf7394516ca2f56aae2f94d7ad9ee033f5552e65fc473", + "vllm_gguf_plugin/triton/dequantize/iq_quant/iq1_s.py": "e4619535a6776d8fbbf4ac1c451a7773b866d07f3c40a1231112bcc2c436a4c7", + "vllm_gguf_plugin/triton/dequantize/iq_quant/iq2_s.py": "2102e3f5293c3aefd0a0352e68ddccae9adc5e0d339e3d901629a6a3e3ed7b65", + "vllm_gguf_plugin/triton/dequantize/iq_quant/iq2_xs.py": "30cf8761d25401603849a71ca6f98467d418c4832e15fa485bde037ca96aea4e", + "vllm_gguf_plugin/triton/dequantize/iq_quant/iq2_xxs.py": "2cc8610c83de7087e8bf542dce2d47c2a89d9d88c7fbd9092a4b4753e57409c6", + "vllm_gguf_plugin/triton/dequantize/iq_quant/iq3_s.py": "841ab0215c7c61be31068f634b3c2d26903bbd9639438eaa9d0e4c6871e8a374", + "vllm_gguf_plugin/triton/dequantize/iq_quant/iq3_xxs.py": "414627369715ab31aec9ac5103b3ef18ecb8bfb45670af2e877418821ea62210", + "vllm_gguf_plugin/triton/dequantize/iq_quant/iq4_nl.py": "b8e640287eb0929f83dcdc3bf01d7bf8ac0ac2b63cadc5b7d17f83bb77daa4db", + "vllm_gguf_plugin/triton/dequantize/iq_quant/iq4_xs.py": "91529ddc95d9e7da4824364b4308d0aa8c5d9712ea3d7c4a644f5a396c7ff4f0", + "vllm_gguf_plugin/triton/dequantize/k_quant/__init__.py": "3c42c6eb160150dc781258ddf2103d7b0de03b674297646f42929f707694bb20", + "vllm_gguf_plugin/triton/dequantize/k_quant/q2_k.py": "4dff47db3970b03709b22ed67cb29fddfb99faec5fe26980f0683b3bd7759ef1", + "vllm_gguf_plugin/triton/dequantize/k_quant/q3_k.py": "e97247b9ead180afa31d896bcb72e2df8ef1ea5f326e9988d3d3c36a9caa58a1", + "vllm_gguf_plugin/triton/dequantize/k_quant/q4_k.py": "4a1d1323fab0a463fc33fa9abc32a8d2a43b30be9f3d24de95b4f008c3253811", + "vllm_gguf_plugin/triton/dequantize/k_quant/q5_k.py": "c74345d0972a37777f33c013758e868b2b835f5805b721a88c1ad40fd92e0238", + "vllm_gguf_plugin/triton/dequantize/k_quant/q6_k.py": "1c705c7052286cd179d4793d9fa08d57a20145bb24f7da49511503e5fe0eab04", + "vllm_gguf_plugin/triton/dequantize/standard_quant/__init__.py": "9727990b5e8d5f051f572cd8999c28f22b2be99c2babeb1dee17c081b1853ac9", + "vllm_gguf_plugin/triton/dequantize/standard_quant/q4_0.py": "4aab047fbf9abf6234ef6fd64f2a3aee4023cb91c850579997e9827d5b997643", + "vllm_gguf_plugin/triton/dequantize/standard_quant/q4_1.py": "5d0d85223f69082951a5301b87235e74c1c212e1c34f987871bbdf0a523e93c3", + "vllm_gguf_plugin/triton/dequantize/standard_quant/q5_0.py": "ae4e2c494b227a6d6534631b6ee2bdbc313c46ecd2a7e8af8a582575338c796e", + "vllm_gguf_plugin/triton/dequantize/standard_quant/q5_1.py": "d6d526993a0f26cb0da9030d24456cd6a163d13a66205c2f47f4557b9443daec", + "vllm_gguf_plugin/triton/dequantize/standard_quant/q8_0.py": "274008decd5ddf15fa6741d1422201d6831c59d439df0a7b44fe7939eaafbc8d", + "vllm_gguf_plugin/triton/dequantize/standard_quant/q8_1.py": "d2b56f6ba4b0018240b81bc354d805917a83f0f26838cd45021821e50b7b39fc", + "vllm_gguf_plugin/triton/dequantize/utils.py": "3b46512556ee6ef55d5c7acd32ce289f41640c022252ab0f65ec961e9a854750", + "vllm_gguf_plugin/triton/fused_moe/__init__.py": "b466c73479b97f45e40d1d50d7a534a8f6f05f5965a03e084a363f0773d0d73f", + "vllm_gguf_plugin/triton/fused_moe/interface.py": "5761acc437eb5f3f49b84d235ed45adcf5b1ae2b0a3650c3b7fe4b4e1430852d", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/__init__.py": "4c66e819f5765037507a598f69a0edc019dbc41ddd79fde78bfeb087878cc4e4", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/iq1_m.py": "ac3134f134f5f4f8cd667b407f5e9b126f1a72805d6e54a5b64fc711f76a6e75", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/iq1_s.py": "2245b0ee042fd2ebd9928f71e4b69b3c64a06d685030226b632038ca344a8a3a", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/iq2_s.py": "df9c1abca21fb85df4f28122521e0e62aa31fa7c7bd9eca9b58edec80e4c2f77", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/iq2_xs.py": "b064d651e2cf630b44d5c5231fa2dc9bc44a72dfc4b2497baaf670c87b610791", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/iq2_xxs.py": "72862bfa799739e40185fa7671fce86bbf176a28329a78973aa5e735d025bb63", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/iq3_s.py": "adf4ec93760bfb5b327310ac7c257c8091f522c30c56014c43fa743c42e1c2cb", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/iq3_xxs.py": "2471ca802e675a6d92e091f9970e3745ffcd64307a042a1e91af61e51834f5bf", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/iq4_nl.py": "78b14baaf6d976e72635bea06962eff3757b17d23d6d90c842399d6981dbc56d", + "vllm_gguf_plugin/triton/fused_moe/iq_quant/iq4_xs.py": "16d18b9fc71b70dfce2044d6938488ba83eed9daf7202c144da92cfa88cbbeda", + "vllm_gguf_plugin/triton/fused_moe/k_quant/__init__.py": "ac57f723d1726db7abb41898cb9e8bceaf50209510fcbda9ac50fa118c1fd8a2", + "vllm_gguf_plugin/triton/fused_moe/k_quant/q2_k.py": "96def7c24bb30de179ee1864b065be0e6fd1045f9bdab8ad391f1be28593d575", + "vllm_gguf_plugin/triton/fused_moe/k_quant/q3_k.py": "691e036c396c7125de73cbcd1993023a96cdc136e1ec1599f3d970430058b38d", + "vllm_gguf_plugin/triton/fused_moe/k_quant/q4_k.py": "0216c060cd8cd7a8668863417ec45b5ee9198c384402192cfa2537b078d45349", + "vllm_gguf_plugin/triton/fused_moe/k_quant/q5_k.py": "2298c8dac8434c4910c017ac1db2e631a38b33cd2c66a7c22893ab93ecc9a94f", + "vllm_gguf_plugin/triton/fused_moe/k_quant/q6_k.py": "7a3b30ddafda65e321c2b9091d1b2ac05c2ae9ec1cfb281672817bf2c23c7ee8", + "vllm_gguf_plugin/triton/fused_moe/standard_quant/__init__.py": "2e0626f087aaf64495beafa674ea9bb5c96ab4dca080e27ee1dec0f19ea7ea63", + "vllm_gguf_plugin/triton/fused_moe/standard_quant/q4_0.py": "981ca0dfb18e5afb6264b524a90bef6368648bcac359c83510ca17f7e3516e87", + "vllm_gguf_plugin/triton/fused_moe/standard_quant/q4_1.py": "7cfb86144a6a4d8e36b58ec036d5b2e7a41078f40cc8f856f27ca5d20fc42c7e", + "vllm_gguf_plugin/triton/fused_moe/standard_quant/q5_0.py": "109bc28e34be425884b038c1424a38b1529e1faabe1bcdfffb188eed70ad4313", + "vllm_gguf_plugin/triton/fused_moe/standard_quant/q5_1.py": "583b8d10f93c45530caef0be15b95faf8157746f5095fe066672f73d7260ad2c", + "vllm_gguf_plugin/triton/fused_moe/standard_quant/q8_0.py": "83d7255b105a94216d0f5d5d99116924de251bbc703b0d4a25b25e4aad77d004", + "vllm_gguf_plugin/triton/fused_moe/standard_quant/q8_1.py": "d15cf10adaa916f0ebe9ff3004bef2e12272e3c712436391867276b6ea5f28ad", + "vllm_gguf_plugin/triton/fused_moe/utils.py": "fc31d25eafd9c796a0df0c59e11cdd4e881efda7f9dec22bf7b79f09f2b7b79d", + "vllm_gguf_plugin/triton/gemm/__init__.py": "6c6ec57de9f82ef42d82760f144a4571cb16b3cd6de33aaa7aa9fd65e8ab1fa1", + "vllm_gguf_plugin/triton/gemm/interface.py": "4797dd1ead0968eed05a7a4d700288e9e9500a194719b9457e03287d4021b4b5", + "vllm_gguf_plugin/triton/gemm/iq_quant/__init__.py": "6c6ec57de9f82ef42d82760f144a4571cb16b3cd6de33aaa7aa9fd65e8ab1fa1", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq1_m.py": "a085d73390d934bb9a080d52e6240e00d78c9157853a852166fded297bb32610", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq1_s.py": "1fa2ac641d986803fc8f5dd8e3e81334580ddf287b106cb01bcb6fb10989936e", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq2_s.py": "3c0ffa66e08bf1e38f950be2e53f39303c8bb0e11087caf6ae639eea83e52838", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq2_xs.py": "a9259737326c7e4ed6559285355c822f972921d454e0cce3dd91a2d718dd218a", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq2_xxs.py": "f7b240c3d764b82805d68b6108d618dfa49594cddba4d0af11873e5fbeb4c061", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq3_s.py": "85b029e372f7c025320965cc98283f7556982bd0195b429173c094d4eb261d68", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq3_xxs.py": "cce28674e735a9ccec6a503604790e915e723783551c90fd80dcebce5535d4c0", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq4_nl.py": "8da067cc8a21a58bab73a7c5af4a7eaf293d7287033069e303d99511b0153fbf", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq4_xs.py": "b420a17e6ea301a3c0ef7e732c71b720cda92481aadc08d229505495a7566afe", + "vllm_gguf_plugin/triton/gemm/iq_quant/iq_tables.py": "237e8f35e00611aa5f1ae3c176a440fec6cd672aeb54b8ced4fc2aaad019e693", + "vllm_gguf_plugin/triton/gemm/k_quant/__init__.py": "6c6ec57de9f82ef42d82760f144a4571cb16b3cd6de33aaa7aa9fd65e8ab1fa1", + "vllm_gguf_plugin/triton/gemm/k_quant/q2_k.py": "0e3c07ca796f20ef2af8bb0c7f9675c9a56256a180731e92df9802fa157ea95b", + "vllm_gguf_plugin/triton/gemm/k_quant/q3_k.py": "9b08b1190036c3f6f9f76c5df47d651139de1cc275b4e0506924d58e45303fe9", + "vllm_gguf_plugin/triton/gemm/k_quant/q4_k.py": "8a3f708e6efb9351125ac4388c9b1cccc545a4e0b10929ec6d19e1178c99e96d", + "vllm_gguf_plugin/triton/gemm/k_quant/q5_k.py": "eb981367e11f71068ba16e6b42a39c49f272b01291b51dd1a2867f887b64a879", + "vllm_gguf_plugin/triton/gemm/k_quant/q6_k.py": "1f5eb00e017b24b8651cfe814856747a1b86e6b0e2b140d318c66fd48fd0a80c", + "vllm_gguf_plugin/triton/gemm/standard_quant/__init__.py": "6c6ec57de9f82ef42d82760f144a4571cb16b3cd6de33aaa7aa9fd65e8ab1fa1", + "vllm_gguf_plugin/triton/gemm/standard_quant/q4_0.py": "e3a80371bfbfd13946ff4ac0f5a0dcb10c780de40d76a3309246632c70c6c8c1", + "vllm_gguf_plugin/triton/gemm/standard_quant/q4_1.py": "7dc5dbb13ba58810129faf71f5dd4dd24ee2a0cd2bf633dc9d1dddf27fa355ba", + "vllm_gguf_plugin/triton/gemm/standard_quant/q5_0.py": "7966b6d565b7285e0268aa0c2fdef6cfb464234ca32d34481e80672cf906c26e", + "vllm_gguf_plugin/triton/gemm/standard_quant/q5_1.py": "c625c7bd20992b45c5c3f42d4be1f83b7d3d6843299aeaaa74417f858bc13ece", + "vllm_gguf_plugin/triton/gemm/standard_quant/q8_0.py": "75de808a1017fd6e4787086b9ffa42acfbc685e5ce1c8255a9d3e890ae61fa4e", + "vllm_gguf_plugin/triton/gemm/standard_quant/q8_1.py": "84dcf565d25c1190b6d8984810118a66049ac57d54aaf04920f0e1025b946885", + "vllm_gguf_plugin/triton/gemm/utils.py": "6ee2b74c572dafc1511d006e5a08cebae06138f6a2b51aa59939edd88ebf051f", + "vllm_gguf_plugin/weight_utils.py": "03cdf368cc6fc58b4751f7471dd1d89a27647b4266e8a5bda30ed857de61df9d", + "vllm_gguf_plugin/weights_adapter/__init__.py": "081d701f52e2388ae38efce6d24030298881c8b4065ac5df40f19fb216980ead", + "vllm_gguf_plugin/weights_adapter/base.py": "899b76daac1cd263e606b96474df53353da55101e3bb61edc12e66aacaf6923f", + "vllm_gguf_plugin/weights_adapter/diffusion/__init__.py": "1af8199a0e542315efc0b79fe741c9d32c103191c27a7562c0ca7d53909b2aed", + "vllm_gguf_plugin/weights_adapter/diffusion/base.py": "c2678ceae3e2296bd0b9f4fefc77374b464e687236ab65b0cc8055a981eeeda5", + "vllm_gguf_plugin/weights_adapter/diffusion/flux2_klein.py": "d5007751145b7a85c075486a704134ae1f11c569d2be78374f945737f2acb8a8", + "vllm_gguf_plugin/weights_adapter/diffusion/integration.py": "a1ee6919b529831fd44e608b71a674d6c13052970713c200cb4a8e3e9636d368", + "vllm_gguf_plugin/weights_adapter/diffusion/loader.py": "a7044349ea18645c6d3f4e36c9ea30e07b7e9c47aa3d38bc5b7fd716846d3a26", + "vllm_gguf_plugin/weights_adapter/diffusion/qwen_image.py": "6be01743e2c1a13008ca4e89b0a88784fd7eebc00c69583455099882cfccca8e", + "vllm_gguf_plugin/weights_adapter/diffusion/z_image.py": "5abbd262ab6b6f97b745e1534dc9f44ea4d0e75e2444d0b193f28ed8a89ab487", + "vllm_gguf_plugin/weights_adapter/gemma3.py": "2b5011dccbb976dd83d85ff9bdd358e5f17039c8543cfb592a47157f6ac74465", + "vllm_gguf_plugin/weights_adapter/gemma4.py": "dc89fff10a58bc9539e5ee201c5c231839965b8a04cb5e6f155a91f5875874da", + "vllm_gguf_plugin/weights_adapter/olmoe.py": "47a77b4ef1ed1fadcc5507f00a5eb1cc861b0a3111e7ead817d26a737ac7dc7c", + "vllm_gguf_plugin/weights_adapter/qwen3_5.py": "ed19007102c518a50e89a92fa2084c4034980f59aabd0881ce13df78df1fa2d5", + "vllm_gguf_plugin/weights_adapter/transformers.py": "f252fabd0e31f7e408b347fc686584c568dec840e7d17c9b7f729a7d0425342b", + "vllm_gguf_plugin.egg-info/PKG-INFO": "ac6e584fcd033f0578f2ded9f368ec1ca90d63c9268d3521901ae706a8537079", + "vllm_gguf_plugin.egg-info/SOURCES.txt": "1a897e9037ed45581c2d126d788e363b7e0041d4ec03edb1477c683fbf2f2605", + "vllm_gguf_plugin.egg-info/dependency_links.txt": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b", + "vllm_gguf_plugin.egg-info/entry_points.txt": "6087369aa91ab6f5c0bdc80a76daed8a92175bb0a1db7a03aa89a24cd89ff241", + "vllm_gguf_plugin.egg-info/requires.txt": "89642c00a45edc69b5157d59b942c030999737af3b590acaf2735bf4264a74d5", + "vllm_gguf_plugin.egg-info/top_level.txt": "6b3fa0d9d555c7095f09dfd0c51e4ab37aaf29e23b0fe783abd7e4dbd0357be3" +} diff --git a/docs/bench-evidence/rocm-quant-gather/plugin-build-command.json b/docs/bench-evidence/rocm-quant-gather/plugin-build-command.json new file mode 100644 index 000000000..24c594527 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/plugin-build-command.json @@ -0,0 +1,54 @@ +[ + "docker", + "run", + "--rm", + "--pull=never", + "--name", + "rdna3-gather-plugin-build", + "--network=none", + "--ipc=private", + "--shm-size=2g", + "--user", + "1000:1000", + "--group-add", + "44", + "--group-add", + "992", + "--entrypoint", + "/home/vikash/oracle/gfx1100-active-2773/runtime/bin/python", + "-v", + "/home/vikash/oracle/gfx1100-active-2773/runtime:/home/vikash/oracle/gfx1100-active-2773/runtime:ro", + "-v", + "/home/vikash/.cache/rdna3-gather-impl:/home/vikash/.cache/rdna3-gather-impl", + "-w", + "/home/vikash/.cache/rdna3-gather-impl/plugin-source", + "-e", + "PYTHONDONTWRITEBYTECODE=1", + "-e", + "PYTHONUNBUFFERED=1", + "-e", + "HIP_VISIBLE_DEVICES=", + "-e", + "ROCR_VISIBLE_DEVICES=", + "-e", + "PYTORCH_ROCM_ARCH=gfx1100", + "-e", + "MAX_JOBS=4", + "-e", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "-e", + "XDG_CACHE_HOME=/home/vikash/.cache/rdna3-gather-impl/plugin-cache", + "-e", + "USER=vikash", + "-e", + "LOGNAME=vikash", + "-e", + "VLLM_GGUF_PLUGIN_LOCAL_VERSION_SUFFIX=d4c1f0d.gfx1100", + "sha256:80aab4c182a1f3eeebe286173977e57fcaf10a049b41f475655b35d285de31dc", + "setup.py", + "build", + "--build-base", + "/home/vikash/.cache/rdna3-gather-impl/plugin-build", + "--build-lib", + "/home/vikash/.cache/rdna3-gather-impl/plugin-artifact" +] diff --git a/docs/bench-evidence/rocm-quant-gather/preflight-final-staged-result.json b/docs/bench-evidence/rocm-quant-gather/preflight-final-staged-result.json new file mode 100644 index 000000000..1ee3e689f --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/preflight-final-staged-result.json @@ -0,0 +1,48 @@ +{ + "worktree": "/home/vikash/vllm.cpp-rdna3-gather-impl", + "base_commit": "b46852d13f7c8776557dab170e02ebea50cdfdec", + "staged_tree": "57d80b867e348f6a61ecb3b369fae4430e175057", + "scope": "The final full preflight reads this staged source and record state. Subsequent result-only record edits require focused record checks; frozen product bytes remain identical.", + "argv": [ + "env", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "GIT_CEILING_DIRECTORIES=/home/vikash/.cache/rdna3-gather-impl/tmp", + "GIT_CONFIG_GLOBAL=/dev/null", + "PYTHONPATH=/home/vikash/.cache/hrx-evaluation-3080-preflight/python", + "bash", + "scripts/agent-preflight.sh", + "--staged", + "--quiet" + ], + "log": "/home/vikash/.cache/rdna3-gather-impl/evidence/preflight-final-staged.log", + "source_manifest": "/home/vikash/.cache/rdna3-gather-impl/evidence/fresh-review-source-manifest.json", + "source_manifest_sha256": "780329dbc81e8ba1eeef575e1f321e30c232e4109bf0718edeb94c9d6b25a2fa", + "exit_status": 0, + "log_sha256": "23e50cc8260928a06e42faa0d7f63ef0b27f5d9aa04883a50028ddf413441833", + "reported_ok_calls": 158, + "skipped_argument_dependent_gates": [ + "check-arm-isa-build.py", + "check-cpu-isa-build.py", + "check-cuda-fat-gencode.py", + "check-pr-size.py", + "check-triton-aot-multiarch.py" + ], + "all_green": false, + "explicit_cpu_isa": { + "argv": [ + "python3", + "scripts/check-cpu-isa-build.py", + "--compile-commands", + "build-cpu-rocm-quant-gather/compile_commands.json" + ], + "exit_status": 0, + "log_sha256": "4f54e0b5f7fb96d55768af81286498f80a23d0d70cae9b32e62cc2a8e6bcaf16" + }, + "scope_of_unsupplied_inputs": { + "check-arm-isa-build.py": "No ARM compilation in this x86_64 HIP build", + "check-cuda-fat-gencode.py": "VLLM_CPP_CUDA=OFF for this HIP build", + "check-triton-aot-multiarch.py": "CUDA AOT artifacts are disabled in this HIP build", + "check-pr-size.py": "Exact commit classification runs after committing; staged paths were independently classified" + }, + "combined_cuda_hip_execution": "PENDING: no combined build was available for this qualification" +} diff --git a/docs/bench-evidence/rocm-quant-gather/preflight-python-environment.json b/docs/bench-evidence/rocm-quant-gather/preflight-python-environment.json new file mode 100644 index 000000000..418552043 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/preflight-python-environment.json @@ -0,0 +1,9 @@ +{ + "python": "3.12.3 (main, Jul 15 2026, 23:46:41) [GCC 13.3.0]", + "platform": "Linux-7.0.0-28-generic-x86_64-with-glibc2.39", + "numpy": "2.4.6", + "numpy_path": "/home/vikash/.cache/hrx-evaluation-3080-preflight/python/numpy/__init__.py", + "msgspec": "0.21.1", + "msgspec_path": "/home/vikash/.cache/hrx-evaluation-3080-preflight/python/msgspec/__init__.py", + "purpose": "Existing task-local Python dependencies used by record mutation suites; no package installation or runtime modification in this row." +} diff --git a/docs/bench-evidence/rocm-quant-gather/primary-model-config.json b/docs/bench-evidence/rocm-quant-gather/primary-model-config.json new file mode 100644 index 000000000..006d7637c --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/primary-model-config.json @@ -0,0 +1,44 @@ +{ + "model_type": "qwen3_5_text", + "architectures": [ + "Qwen3_5ForCausalLM" + ], + "dtype": "bfloat16", + "hidden_size": 256, + "num_hidden_layers": 1, + "num_attention_heads": 4, + "num_key_value_heads": 1, + "head_dim": 64, + "intermediate_size": 256, + "vocab_size": 128, + "max_position_embeddings": 64, + "full_attention_interval": 1, + "layer_types": [ + "full_attention" + ], + "rms_norm_eps": 1e-06, + "attention_bias": false, + "attention_dropout": 0.0, + "attn_output_gate": true, + "hidden_act": "silu", + "tie_word_embeddings": false, + "bos_token_id": 1, + "eos_token_id": 2, + "unk_token_id": 0, + "linear_conv_kernel_dim": 4, + "linear_key_head_dim": 64, + "linear_value_head_dim": 64, + "linear_num_key_heads": 1, + "linear_num_value_heads": 1, + "rope_parameters": { + "rope_type": "default", + "rope_theta": 1000000.0, + "partial_rotary_factor": 1.0, + "mrope_section": [ + 16, + 8, + 8 + ], + "mrope_interleaved": true + } +} diff --git a/docs/bench-evidence/rocm-quant-gather/primary-model-v1-command.json b/docs/bench-evidence/rocm-quant-gather/primary-model-v1-command.json new file mode 100644 index 000000000..3a285b5d9 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/primary-model-v1-command.json @@ -0,0 +1,101 @@ +{ + "row": "BACKEND-ROCM-QUANT-GATHER", + "argv": [ + "docker", + "run", + "--rm", + "--device=/dev/kfd", + "--device=/dev/dri", + "--pull=never", + "--network=none", + "--ipc=private", + "--shm-size=2g", + "--user", + "1000:1000", + "--group-add", + "44", + "--group-add", + "992", + "--entrypoint", + "/home/vikash/oracle/gfx1100-active-2773/runtime/bin/python", + "-v", + "/home/vikash/oracle/gfx1100-active-2773:/home/vikash/oracle/gfx1100-active-2773:ro", + "-v", + "/home/vikash/.cache/rdna3-gather-impl:/home/vikash/.cache/rdna3-gather-impl", + "-e", + "PYTHONDONTWRITEBYTECODE=1", + "-e", + "PYTHONPATH=/home/vikash/.cache/rdna3-gather-impl/plugin-artifact:/home/vikash/.cache/rdna3-gather-impl/llama-stock-source/gguf-py", + "-e", + "HIP_VISIBLE_DEVICES=0", + "-e", + "ROCR_VISIBLE_DEVICES=0", + "-e", + "USER=vikash", + "-e", + "LOGNAME=vikash", + "-e", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "-e", + "XDG_CACHE_HOME=/home/vikash/.cache/rdna3-gather-impl/plugin-cache", + "-v", + "/home/vikash/vllm.cpp-rdna3-gather-impl:/home/vikash/vllm.cpp-rdna3-gather-impl:ro", + "-e", + "PYTHONUNBUFFERED=1", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "VLLM_NO_USAGE_STATS=1", + "--name", + "rdna3-gather-primary-model-v1", + "sha256:80aab4c182a1f3eeebe286173977e57fcaf10a049b41f475655b35d285de31dc", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary_model.py", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model/Q4_0.gguf", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/report-p0-r0.json", + "--prompt-index", + "0", + "--repeat", + "0" + ], + "env": {}, + "cwd": "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1", + "log": "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary-model-p0-r0.log", + "files": { + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model/config.json": { + "bytes": 974, + "sha256": "919812c5a2a3cfae586873cc965f0f4b33179a7ca96b8d8b1afcdac88afca71e" + }, + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model/Q4_0.gguf": { + "bytes": 944192, + "sha256": "663597e28852d64097f7a67542675e4575ee158d3c5e6e2143aadd1b4188f4af" + }, + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary.py": { + "bytes": 7227, + "sha256": "1ddd29da328db6817b5b15119c228cad55b1f2d4e5acc143c80d70966a5c2d75" + }, + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary_model.py": { + "bytes": 3998, + "sha256": "a8bd0a4c815fb0df6934f69b15bf54179c5204630e617a3cd000bda5100aed2b" + }, + "/home/vikash/.cache/rdna3-gather-impl/plugin-artifact/vllm_gguf_plugin/_C_gguf.abi3.so": { + "bytes": 5175208, + "sha256": "592af79c210496e96eaa7bd409ae0a67e7de8c334aa9f782082c7639ba300138" + }, + "/home/vikash/.cache/rdna3-gather-impl/evidence/plugin-artifact-sha256.json": { + "bytes": 16561, + "sha256": "b4def029f9693f89654fa2c60433c9a82dd9924909bced7b772ec609e648f5bf" + } + }, + "fixture": { + "origin": "Frozen generated fixture from public native gate", + "gguf_sha256": "663597e28852d64097f7a67542675e4575ee158d3c5e6e2143aadd1b4188f4af", + "table": "Q4_0", + "geometry": "one full-attention layer, H256,4Q/1KV heads,D64,I256,V128" + }, + "config_adaptation": "Explicit text-only HF config mirrors GGUF metadata; plugin resolves architecture using its unchanged pinned adapter. No vision weights/config invented.", + "authority": "Root only under GPU0 mutex; no oracle patch, pin change or eager override", + "acceptance": "This is first requestedp0r0. A load/refusal keeps model gatePENDING. On success compare exacttokens and schedule remaining5 fresh-engine requests." +} diff --git a/docs/bench-evidence/rocm-quant-gather/primary-model-v1-operator-receipt.json b/docs/bench-evidence/rocm-quant-gather/primary-model-v1-operator-receipt.json new file mode 100644 index 000000000..0be2f9bc3 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/primary-model-v1-operator-receipt.json @@ -0,0 +1,72 @@ +{ + "manifest_sha256": "adbd68d083f11d765fe6adca161acfcb7ebe968ca1bdfefd210ed4ef5abc5749", + "argv": [ + "flock", + "-n", + "-F", + "/home/vikash/gpu.lock", + "docker", + "run", + "--rm", + "--device=/dev/kfd", + "--device=/dev/dri", + "--pull=never", + "--network=none", + "--ipc=private", + "--shm-size=2g", + "--user", + "1000:1000", + "--group-add", + "44", + "--group-add", + "992", + "--entrypoint", + "/home/vikash/oracle/gfx1100-active-2773/runtime/bin/python", + "-v", + "/home/vikash/oracle/gfx1100-active-2773:/home/vikash/oracle/gfx1100-active-2773:ro", + "-v", + "/home/vikash/.cache/rdna3-gather-impl:/home/vikash/.cache/rdna3-gather-impl", + "-e", + "PYTHONDONTWRITEBYTECODE=1", + "-e", + "PYTHONPATH=/home/vikash/.cache/rdna3-gather-impl/plugin-artifact:/home/vikash/.cache/rdna3-gather-impl/llama-stock-source/gguf-py", + "-e", + "HIP_VISIBLE_DEVICES=0", + "-e", + "ROCR_VISIBLE_DEVICES=0", + "-e", + "USER=vikash", + "-e", + "LOGNAME=vikash", + "-e", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "-e", + "XDG_CACHE_HOME=/home/vikash/.cache/rdna3-gather-impl/plugin-cache", + "-v", + "/home/vikash/vllm.cpp-rdna3-gather-impl:/home/vikash/vllm.cpp-rdna3-gather-impl:ro", + "-e", + "PYTHONUNBUFFERED=1", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "VLLM_NO_USAGE_STATS=1", + "--name", + "rdna3-gather-primary-model-v1", + "sha256:80aab4c182a1f3eeebe286173977e57fcaf10a049b41f475655b35d285de31dc", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary_model.py", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model/Q4_0.gguf", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/report-p0-r0.json", + "--prompt-index", + "0", + "--repeat", + "0" + ], + "exit_code": 1, + "seconds": 24.120296001434326, + "log_sha256": "01b26816b2eb24fcd88eeab00c15ccd8643361dabfef8b6529aea42db6bd548b", + "input_count": 340, + "all_inputs_verified_before_after": true +} diff --git a/docs/bench-evidence/rocm-quant-gather/primary-model-v1-report-p0-r0.json b/docs/bench-evidence/rocm-quant-gather/primary-model-v1-report-p0-r0.json new file mode 100644 index 000000000..476622289 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/primary-model-v1-report-p0-r0.json @@ -0,0 +1,49 @@ +{ + "model": { + "bytes": 944192, + "sha256": "663597e28852d64097f7a67542675e4575ee158d3c5e6e2143aadd1b4188f4af" + }, + "config": { + "bytes": 974, + "sha256": "919812c5a2a3cfae586873cc965f0f4b33179a7ca96b8d8b1afcdac88afca71e" + }, + "primary_pin": "e126687a9a828d513c01a07cd69f025f27d63280", + "plugin_pin": "d4c1f0d082fc7cd4350da56689109a01c1f29d6c", + "prompt": [ + 1, + 0, + 63, + 127, + 63 + ], + "repeat": 0, + "tokens": [], + "requested": { + "model_dtype": "auto from bfloat16 config", + "block_size": 16, + "num_gpu_blocks_override": 4, + "max_model_len": 64, + "max_num_seqs": 1, + "kv_cache_dtype": "auto", + "seed": 1380926285, + "greedy": true, + "ignore_eos": true, + "max_tokens": 4, + "stop": [], + "stop_token_ids": [] + }, + "harness_adaptations": [ + "pre-tokenized IDs with skip_tokenizer_init=True", + "explicit local HF text config mirrors GGUF geometry", + "no oracle patch or eager-mode override" + ], + "status": "PENDING: primary model refused before qualification", + "torch": "2.12.0+git6bbd260", + "torch_git": "6bbd26020da1c6dc198625dfcdd968b1e4e6b1c5", + "hip": "7.2.53211", + "vllm": "0.28.1rc1.dev132+ge126687a9", + "plugin": "0.0.5+d4c1f0d.gfx1100", + "exception_type": "ValidationError", + "exception": "1 validation error for ModelConfig\n Value error, Model architectures ['Qwen3_5ForConditionalGeneration'] failed to be inspected. Please check the logs for more details. [type=value_error, input_value=ArgsKwargs((), {'model': ...nderer_num_workers': 1}), input_type=ArgsKwargs]\n For further information visit https://errors.pydantic.dev/2.13/v/value_error", + "traceback": "Traceback (most recent call last):\n File \"/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary_model.py\", line 52, in main\n model = LLM(model=str(args.model), hf_config_path=str(args.config),\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/entrypoints/llm.py\", line 343, in __init__\n self.llm_engine = LLMEngine.from_engine_args(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/v1/engine/llm_engine.py\", line 171, in from_engine_args\n vllm_config = engine_args.create_engine_config(usage_context)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/engine/arg_utils.py\", line 2001, in create_engine_config\n model_config = self.create_model_config()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/quark/online_quantization/vllm/plugin.py\", line 193, in patched_create_model_config\n return orig_create_model_config(self, *args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/.cache/rdna3-gather-impl/plugin-artifact/vllm_gguf_plugin/plugin.py\", line 76, in create_model_config\n return original_create_model_config(self, *args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/engine/arg_utils.py\", line 1757, in create_model_config\n return ModelConfig(\n ^^^^^^^^^^^^\n File \"/usr/local/lib/python3.12/dist-packages/pydantic/_internal/_dataclasses.py\", line 121, in __init__\n s.__pydantic_validator__.validate_python(ArgsKwargs(args, kwargs), self_instance=s)\npydantic_core._pydantic_core.ValidationError: 1 validation error for ModelConfig\n Value error, Model architectures ['Qwen3_5ForConditionalGeneration'] failed to be inspected. Please check the logs for more details. [type=value_error, input_value=ArgsKwargs((), {'model': ...nderer_num_workers': 1}), input_type=ArgsKwargs]\n For further information visit https://errors.pydantic.dev/2.13/v/value_error\n" +} diff --git a/docs/bench-evidence/rocm-quant-gather/primary-model-v2-command.json b/docs/bench-evidence/rocm-quant-gather/primary-model-v2-command.json new file mode 100644 index 000000000..44e9609a9 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/primary-model-v2-command.json @@ -0,0 +1,116 @@ +{ + "row": "BACKEND-ROCM-QUANT-GATHER", + "argv": [ + "docker", + "run", + "--rm", + "--device=/dev/kfd", + "--device=/dev/dri", + "--pull=never", + "--network=none", + "--ipc=private", + "--shm-size=2g", + "--user", + "1000:1000", + "--group-add", + "44", + "--group-add", + "992", + "--entrypoint", + "/home/vikash/oracle/gfx1100-active-2773/runtime/bin/python", + "-v", + "/home/vikash/oracle/gfx1100-active-2773:/home/vikash/oracle/gfx1100-active-2773:ro", + "-v", + "/home/vikash/.cache/rdna3-gather-impl:/home/vikash/.cache/rdna3-gather-impl", + "-e", + "PYTHONDONTWRITEBYTECODE=1", + "-e", + "PYTHONPATH=/home/vikash/.cache/rdna3-gather-impl/plugin-artifact:/home/vikash/.cache/rdna3-gather-impl/llama-stock-source/gguf-py", + "-e", + "HIP_VISIBLE_DEVICES=0", + "-e", + "ROCR_VISIBLE_DEVICES=0", + "-e", + "USER=vikash", + "-e", + "LOGNAME=vikash", + "-e", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "-e", + "XDG_CACHE_HOME=/home/vikash/.cache/rdna3-gather-impl/plugin-cache", + "-v", + "/home/vikash/vllm.cpp-rdna3-gather-impl:/home/vikash/vllm.cpp-rdna3-gather-impl:ro", + "-e", + "PYTHONUNBUFFERED=1", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "VLLM_NO_USAGE_STATS=1", + "--name", + "rdna3-gather-primary-model-v2", + "-e", + "TRITON_CACHE_DIR=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/triton", + "-e", + "VLLM_CACHE_ROOT=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/vllm", + "-e", + "TORCHINDUCTOR_CACHE_DIR=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/inductor", + "-e", + "HF_HOME=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/hf", + "-e", + "NUMBA_CACHE_DIR=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/numba", + "-e", + "MAX_JOBS=4", + "-e", + "TORCHINDUCTOR_COMPILE_THREADS=4", + "sha256:80aab4c182a1f3eeebe286173977e57fcaf10a049b41f475655b35d285de31dc", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary_model.py", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model/Q4_0.gguf", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/report-p0-r0.json", + "--prompt-index", + "0", + "--repeat", + "0" + ], + "env": {}, + "cwd": "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1", + "log": "/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/primary-model-p0-r0.log", + "files": { + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model/config.json": { + "bytes": 974, + "sha256": "919812c5a2a3cfae586873cc965f0f4b33179a7ca96b8d8b1afcdac88afca71e" + }, + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model/Q4_0.gguf": { + "bytes": 944192, + "sha256": "663597e28852d64097f7a67542675e4575ee158d3c5e6e2143aadd1b4188f4af" + }, + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary.py": { + "bytes": 7227, + "sha256": "1ddd29da328db6817b5b15119c228cad55b1f2d4e5acc143c80d70966a5c2d75" + }, + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary_model.py": { + "bytes": 3998, + "sha256": "a8bd0a4c815fb0df6934f69b15bf54179c5204630e617a3cd000bda5100aed2b" + }, + "/home/vikash/.cache/rdna3-gather-impl/plugin-artifact/vllm_gguf_plugin/_C_gguf.abi3.so": { + "bytes": 5175208, + "sha256": "592af79c210496e96eaa7bd409ae0a67e7de8c334aa9f782082c7639ba300138" + }, + "/home/vikash/.cache/rdna3-gather-impl/evidence/plugin-artifact-sha256.json": { + "bytes": 16561, + "sha256": "b4def029f9693f89654fa2c60433c9a82dd9924909bced7b772ec609e648f5bf" + } + }, + "fixture": { + "origin": "Frozen generated fixture from public native gate", + "gguf_sha256": "663597e28852d64097f7a67542675e4575ee158d3c5e6e2143aadd1b4188f4af", + "table": "Q4_0", + "geometry": "one full-attention layer, H256,4Q/1KV heads,D64,I256,V128" + }, + "config_adaptation": "Explicit text-only HF config mirrors GGUF metadata; plugin resolves architecture using its unchanged pinned adapter. No vision weights/config invented.", + "authority": "Root only under GPU0 mutex; no oracle patch, pin change or eager override", + "acceptance": "This is first requestedp0r0. A load/refusal keeps model gatePENDING. On success compare exacttokens and schedule remaining5 fresh-engine requests.", + "version_reason": "v1 failed during Triton cache initialization at unwritable /.triton; v2 sets explicit task cache directories and build parallelism without changing HOME, model, configuration, inputs, sampling or runtime" +} diff --git a/docs/bench-evidence/rocm-quant-gather/primary-model-v2-operator-receipt.json b/docs/bench-evidence/rocm-quant-gather/primary-model-v2-operator-receipt.json new file mode 100644 index 000000000..591e63f6a --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/primary-model-v2-operator-receipt.json @@ -0,0 +1,86 @@ +{ + "manifest_sha256": "d5a75fbbaa7bb03ca345b3ab66fd7d422ab6a497429851f82918c1d48fbb85e3", + "argv": [ + "flock", + "-n", + "-F", + "/home/vikash/gpu.lock", + "docker", + "run", + "--rm", + "--device=/dev/kfd", + "--device=/dev/dri", + "--pull=never", + "--network=none", + "--ipc=private", + "--shm-size=2g", + "--user", + "1000:1000", + "--group-add", + "44", + "--group-add", + "992", + "--entrypoint", + "/home/vikash/oracle/gfx1100-active-2773/runtime/bin/python", + "-v", + "/home/vikash/oracle/gfx1100-active-2773:/home/vikash/oracle/gfx1100-active-2773:ro", + "-v", + "/home/vikash/.cache/rdna3-gather-impl:/home/vikash/.cache/rdna3-gather-impl", + "-e", + "PYTHONDONTWRITEBYTECODE=1", + "-e", + "PYTHONPATH=/home/vikash/.cache/rdna3-gather-impl/plugin-artifact:/home/vikash/.cache/rdna3-gather-impl/llama-stock-source/gguf-py", + "-e", + "HIP_VISIBLE_DEVICES=0", + "-e", + "ROCR_VISIBLE_DEVICES=0", + "-e", + "USER=vikash", + "-e", + "LOGNAME=vikash", + "-e", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "-e", + "XDG_CACHE_HOME=/home/vikash/.cache/rdna3-gather-impl/plugin-cache", + "-v", + "/home/vikash/vllm.cpp-rdna3-gather-impl:/home/vikash/vllm.cpp-rdna3-gather-impl:ro", + "-e", + "PYTHONUNBUFFERED=1", + "-e", + "HF_HUB_OFFLINE=1", + "-e", + "TRANSFORMERS_OFFLINE=1", + "-e", + "VLLM_NO_USAGE_STATS=1", + "--name", + "rdna3-gather-primary-model-v2", + "-e", + "TRITON_CACHE_DIR=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/triton", + "-e", + "VLLM_CACHE_ROOT=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/vllm", + "-e", + "TORCHINDUCTOR_CACHE_DIR=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/inductor", + "-e", + "HF_HOME=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/hf", + "-e", + "NUMBA_CACHE_DIR=/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/cache/numba", + "-e", + "MAX_JOBS=4", + "-e", + "TORCHINDUCTOR_COMPILE_THREADS=4", + "sha256:80aab4c182a1f3eeebe286173977e57fcaf10a049b41f475655b35d285de31dc", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary_model.py", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model/Q4_0.gguf", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/model", + "/home/vikash/.cache/rdna3-gather-impl/primary-model-v2/report-p0-r0.json", + "--prompt-index", + "0", + "--repeat", + "0" + ], + "exit_code": 1, + "seconds": 25.378447771072388, + "log_sha256": "2e72479519ed22c90b7895aa3fe57b2cf6bbd5ea52108762390d21464b018945", + "input_count": 340, + "all_inputs_verified_before_after": true +} diff --git a/docs/bench-evidence/rocm-quant-gather/primary-model-v2-report-p0-r0.json b/docs/bench-evidence/rocm-quant-gather/primary-model-v2-report-p0-r0.json new file mode 100644 index 000000000..09d208445 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/primary-model-v2-report-p0-r0.json @@ -0,0 +1,49 @@ +{ + "model": { + "bytes": 944192, + "sha256": "663597e28852d64097f7a67542675e4575ee158d3c5e6e2143aadd1b4188f4af" + }, + "config": { + "bytes": 974, + "sha256": "919812c5a2a3cfae586873cc965f0f4b33179a7ca96b8d8b1afcdac88afca71e" + }, + "primary_pin": "e126687a9a828d513c01a07cd69f025f27d63280", + "plugin_pin": "d4c1f0d082fc7cd4350da56689109a01c1f29d6c", + "prompt": [ + 1, + 0, + 63, + 127, + 63 + ], + "repeat": 0, + "tokens": [], + "requested": { + "model_dtype": "auto from bfloat16 config", + "block_size": 16, + "num_gpu_blocks_override": 4, + "max_model_len": 64, + "max_num_seqs": 1, + "kv_cache_dtype": "auto", + "seed": 1380926285, + "greedy": true, + "ignore_eos": true, + "max_tokens": 4, + "stop": [], + "stop_token_ids": [] + }, + "harness_adaptations": [ + "pre-tokenized IDs with skip_tokenizer_init=True", + "explicit local HF text config mirrors GGUF geometry", + "no oracle patch or eager-mode override" + ], + "status": "PENDING: primary model refused before qualification", + "torch": "2.12.0+git6bbd260", + "torch_git": "6bbd26020da1c6dc198625dfcdd968b1e4e6b1c5", + "hip": "7.2.53211", + "vllm": "0.28.1rc1.dev132+ge126687a9", + "plugin": "0.0.5+d4c1f0d.gfx1100", + "exception_type": "TypeError", + "exception": "Invalid type of HuggingFace config. Expected type: , but found type: ", + "traceback": "Traceback (most recent call last):\n File \"/home/vikash/.cache/rdna3-gather-impl/primary-model-v1/primary_model.py\", line 52, in main\n model = LLM(model=str(args.model), hf_config_path=str(args.config),\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/entrypoints/llm.py\", line 343, in __init__\n self.llm_engine = LLMEngine.from_engine_args(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/v1/engine/llm_engine.py\", line 179, in from_engine_args\n return cls(\n ^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/v1/engine/llm_engine.py\", line 91, in __init__\n self.renderer = renderer = renderer_from_config(self.vllm_config)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/renderers/registry.py\", line 88, in renderer_from_config\n return RENDERER_REGISTRY.load_renderer(renderer_mode, config, tokenizer)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/renderers/registry.py\", line 70, in load_renderer\n return renderer_cls(config, tokenizer)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/renderers/hf.py\", line 916, in __init__\n super().__init__(config, tokenizer)\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/renderers/base.py\", line 127, in __init__\n self.mm_processor = mm_registry.create_processor(\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/multimodal/registry.py\", line 237, in create_processor\n return factories.build_processor(ctx, cache=cache)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/multimodal/registry.py\", line 95, in build_processor\n return self.processor(info, dummy_inputs_builder, cache=cache)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/multimodal/processing/processor.py\", line 1049, in __init__\n self.data_parser = self.info.get_data_parser()\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/model_executor/models/qwen3_vl.py\", line 929, in get_data_parser\n self.get_hf_config().vision_config.spatial_merge_size,\n ^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/model_executor/models/qwen3_5.py\", line 108, in get_hf_config\n return self.ctx.get_hf_config(Qwen3_5Config)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/home/vikash/oracle/gfx1100-active-2773/runtime/lib/python3.12/site-packages/vllm/multimodal/processing/context.py\", line 140, in get_hf_config\n raise TypeError(\nTypeError: Invalid type of HuggingFace config. Expected type: , but found type: \n" +} diff --git a/docs/bench-evidence/rocm-quant-gather/primary-operation-captures.tar.gz b/docs/bench-evidence/rocm-quant-gather/primary-operation-captures.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..0679c57e203af052933e572bb6ea2b42434dc736 GIT binary patch literal 146575 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

0tHqW2 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

U6t423JdDkJ>x!+c-Ci< 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�*WhQvce#Y8#`owoxjxO;-7&

p?da8wG}hC0{c~@*zCC?go@ju_c+M-9-tkEg;PIF8nPZuNA73IJ_+ZOGam>XB@nA z_+zjO>~CAx$rqaxL=y$P+SQ2hKVPcj83W!9=3_x*=jm_-b{SK z?Y1D0U-aVeXf`d!CNLD;rKE>HmBb{LiinD7Zg(JT3ES|wB zzUM?P%Kkg#w_y((a~saiiPDG!rWg)OR{?Ibp0GFZsWa<#U)ir;IQPXCI2+b1xjCJ- zjTqWZa_W_0Gqo5`VfUV8>mK8derp}8xPzeGZ*EMTBE8ZZquP3yRt`1YVQJS+P{?oM zs!?FPA(d3h1^5vaQZ|-l!?)|xZu%4FMi%=o@v=>TGTR2))*7E}0k}0G^qXxAyE3^J zxP=yNeKGxy)Qis|XIFUHRQK6#+Hh9n3VfVEyKk8Hy**Pe(|uJ&f@MzW<@-!VWBEk_ zZPn;~$?oyE=nyQMSJK{3MU{x<03`izpSD9{u5FiGlT}2BWTHEL2cFM(Gl7W|$)@*x z9(xxclUt|s#uuCHUi#YmP#fTFBCpu{qx!8)fQRxuk>*D^!BKEeL*=~BNlCVkD+ zY(5rF>Dk}KU3%$O?M@zxnb%AtSjb>u#nG?+Zbgw0e;_ss_x^?xGp>kmlaq@*61qwU&hEy2;3&cfT#)4H2RhBMNuc&Aa zaBn2A{6?fhC{H${zf1a4cT9Vi-!JOuO%x*E@slsZ;HCba<%|Ek)N5F_-_&X!;vxy? zEU7%X@^f(l+?NVAKMO-JsuZ(q@3U*_C%ADUR-^dwSmtibPDgFq8EOixX^mBtrm_SG zV5f$7YC+&UJTE``%x+@qcgP-Xge9K%p0710?XG-QcKEE;yYdJVA%-25KNBDN*|Zkj zt&|o-@*}MNi*2p5+GD+EU1$k6SJI1KpdTI;aew`G-={y(qH-~G*33Cb?U%LKB(ga7 zhv8-`!6xpv67EpuNp%?NvE~2!cwl|J_0i$|%f(4JqW$3T_{$>W%QwV1+QCAU& zyZ&z;|NbYgc@Yh({L+p9NZ6aC_hVb$*;*(5rfzqw*p%1HHS9+{rM&nL^l2JOHfgJh zLaJ#y(*f_s`AO|HL~|0GpXL0fX4`)MbPL+eP%?vH~3=8DQD!yE7`|P(sZoY5o zFFuO-HerITrVHx{7j%a14P!=3f8poJtrfCwB4FK38SMKB=N93Cc^Ik!JLvYR<^)9- z7B$@H8(=cs4AI_oZC4}IADSa$Mz+>B3J_dl-oIK+1?RPf0!tUGV(EXwG+5xwN(Td-!iLH9-i>1jkwff)$5$J4XIeFWh_GM!$sM zXg+z~MpJW{{4UQVZkB^RBO^9QU1-V`QSuJ24fm35N#$_Np7RDKdLdZ*U=t`w@pZ$+ zUE<=FGq;GE0T1B+raq_Uijf-EseI6F+;WRSJ|2gJ-VXSIv$kAz3@>FC7rgJQ9S7bI zuzsoWE!3_9b;e+zAc`eC_!1)D^^AKt*RpF{mc*ns$}^q1yrAu@Oq+^aMPdg?aheZq z4*@)v3e31AE*g;TXTv;@YCe9)0j0saqs&pDT%9QAqKQD`6tP*Dr#rr+!8>YVMkuPs zEPQ+yCvQ(U>ibOU)qGz~dKk?&E?O)V(^k5lPSsV6GA|jhI6E*3#ptF@0pGr6y%&8s z^l`|u!6%krku{X4x_dC4=uB_PS`-r|)}32UI3a}mB^iCw^+#ZmS27sIH7@<2zeO88 zRsO>&E|?BTbBKK{MVomj9K&AE{&B4D)p~F{8LQkPZeJ)|uUZ8O42`8n|9l{?%<7^-@9mBmcpVeq3-Y;a`35V;HRrUKI@SoP5rCMIUVS zi1~J1%Qu$(!^HF1?Ni-fNcfavGJpTe(YR_ObHc~?n(Ry*8*j3|rGu>m+qZx^sc_PwQaMP(;LgfdcOEAq zTubX-BLSn1!cwLbkV4J;zMN`O;NYI?!t>VE=ag~rIDFnzn@pcqL^i0TFk}Y_C#|J7 zP3{AuaDTI@r7i?Xdte4MQncW&Iw~>)rcL-HXtw0ubq`{F$tbqu>V6gfCyfvYzJT6z zVSnA6wZ|WHvCFiVCU^CFzF$%LX8}a}N4xHJGN|N7-$b_)&qX3qV5SSFf}~J)WQVlQ zV;5v}BDbjQX(me8=9oi;tGju={)34!GtmDgwvladsxdvTn=D<`jj>0gmf8Nhdarip z&l1~A3Jej@lrxGe$AD)@~w)-Q&BwTW15}@@xPsn>dGXoyCtT!&GW{#brL0 zLF2llc35dlCDV`y1ki9<$%aIGt{Se!$_ zm3_i*u;|Ij`0C}-7kUdR$9N|3!Pu1MT?8toREOsx7bou2=O)5Ua@T=VMK@i9wSiQ= z&5P}3lC@SZ2Q&UQF=tsi%Gq*kH8EE`GcIB?e3A2;UU!CGS*b%s(~kDLCkKGY$oEZo zjpLqAp?%XWliAR+<}6We&Du(6+i{Y3TFiUf#iTqmo&uk?*b3W?Ff&MO$ zaFwh7Jn>Fp3VOKJo71MlC2bZTNO0B{exil;y_(}1HSgY5=A_TzD(s(pMtlYXV(2WH zWrEtJ-dYLU9z6^1B-4UdRF8UMRRO~kZa8noZGC6UQ&*G{guvBSdzzATzYKpF#8xvN zf07NN_L3`BYbpso{wnWSAponRq`qT4yH{-rd?O3Fz0y0waREY_a)KC0*2YDk&)9PR zz{ir@rJXr&WC6LkMVPGPV-=V;SMW~<8WG!oMqK(~+{mt@=N{l|=#GoTD^wTSL8`l8&oQb1 zHhhHNsSopi-tmToYdGa(MsQm>XD%~5JJFZjYGFHiSZdkW&_mX5vH`Lx{|)StY@h%2 zXXU`9357WQLy}2bEEgW=;#J3E5;$IcSGbqF|C%NZ{fcM#J#Rc%N}FPIFhxlE+JZznCU0Mkeqb2(>mBsCgJY$Jhn z+lQLM&Q1N4R9;p>5np)F;ad`Ys&f|xu=8Tu>`fB6zk4Qro%FBkWz-SI?<()r!;B*k z6ff7JPRV$X`wD|8@iSbbNht&o?QfaWAe)~<6|15!~BY)S{n{*aCZkP4ZM!ihr`+kmKd9OfFb!Vi+?c zE;#xP)KHB}_5crk-_iShiFgLk_gJXnma|PvBs+e>>_E6D#TmPB7CH6!z_cR-2&^0| zv2-MSX!zZ(xb)H3k5DQhPkY&h&~|Ct*(m(ip+a7x1ih9tF(g2E8u5yny7|zWBEC}o zfg`!E-0R{$e(jY8@wHFw-rj4er`2JZVhT1Nkp-)JCyKDjsx4b1)a$2VmrP~7?UOk{tdLc7mz4j$#5_y6{x5v7 z$R^x$#haqiuHOEK3Ez~jk`0ZWFhKhZ#*-;V+lF%KIP2b_nT&6%kHIR@kpGK$Or6Ge z0jbV;>&@F9Y_kJGY$Wix086wt(I0u80dR-+9jN+jM1}nFuYnQt`){|P-!DcWmv`dI zEn};{n@{AM>CNd5-|h*s8FIkw9DaD*LBx#w2#4;|sxTv3wa}l#6dtS@ot zlaYHi*B7X%_aJFED+zm5NAC_>*B|osWPgp#+q;<5ap+ac5l*w`!0~9i>9BZKoWnrJ z;M5@JK-d`ucZpYNXP@xEtx>#9*yg%w<)b%IXDkjigR4X2@r+HsXPo+^IEwtMbtdvQ z!zvM+RSF98m;u^mgHN=UqY!SH;8z;|DQ(kp)#m^?S5(9Nb58~uqqh#3#?4 z#rqz#CpycjU^|2OWsYLr@|i2~)AZ^%qc1YvZBBR=B8VwV<8(bxeai;12 zmS~W}J+2Z+!wLAg&v7Pg$yub_x9qA`U#;U43CIXmf|F#|NW3y;Ns<#INC!S2VfVyI zemtHPkFaZ?b3__CRw^_SGd)h_uVF?AxiZY_06tXm=_V{t{($9B^KnfG(IR4GnJJ#F zbHeT$J~6K~^)!BpIuD$8b>y2npU8hW*|ME;G`r>hG$WPq$Pb)}6`8*{rT?dee@jUUxKM zu~O{hRn~Y}eooR!lGm_NMVqS~Fz}>kh|J!-HK#WICwcg_V`55@(5vPkh4#vhzOQ;5 zVnG{Nx7907gqUU9K*&NmIXY@JzD3*xc}we-bp<2EJ52mJA0>hQNi+5KrHwTv4PqM0TaSQIuBxfgO>=3Qxa?W{N3N9(q_jcr@+I9X$InU^I2+Yv53}| zLLXo21g}zcX$>}QRw!W1pJxG#-TRtp@<*2!egmiL5LzQRa;87{n2nIrFr$o=t@LQA z7}D|DzGBernt>a4p2l092jKHSbWj)4P+4BMl|$@|Y_s3#928dbDqY5r8~Yjq;-H+v z&|G6GPESGwLr=oj%Y1u6B>4{eB9+|LE4d_I)tCM(&JCZN%Q?S zH{#yaNNHkFTUK5NB5#`8py5BC^yR6R^dy|(Dvy8R6piebynMS8oAkqpn=D!Vg~7zV zbJ@A;9_C2l_M!c*w#T2qvKzPbCHy=WXH4*2NHI=0VtiIoM$X@HCIVtDMTmesw%3N| zvh+)5K13_TQiKTYQXh0Vp{C*-sQ16 z^(=d>04c~j%!d#s#`6Ift0IMA5l}Fb>-A>q3V9P)cW_QCJ7VCIE?~lU{%CNqLb^#q z+`n%>wu5)I(4)EH3s|cH7UGnKug;@%2yMk=HO+eli>T_W z_26j{9)jq2^GfL=Z2Yv+9MontEcNgUkadBnRfazIS`_eVL*&h9WA9UDGhbq7!z@J6 zI&B15EjjD_uanU_dWN=n&3@dx3$Q%+IO;CVc*<83uv*pJCrLXa2Em8!oRuGV{J2XC zhqX^IT|PB}eAGL0ujK_8HU!f1MUOp=wc8V+T$hh0I?Zmg^E>Tnb9kftBzDbOo0c{- zId`=1&-CK)L*^k*oTod|T#Mxa@ik~EtoD-wuR8LMy02P&^l{s24%+QJ(;z!@x!646 zo`m8TUuCEta^MkgBnJGc714Ss<5p?xQ!f%+ra9kZ($UPmy6O7t9cV!_21VWqi8zIs z@O?IPXjt-*Y3&62ip)$VoDa?h`=ob$uNZZFG^d<*f;>NOo}g+C=-Uh#jqsaYua;Xr zcDXF-P?%`a`i|~q{snJ0xeffdHHFH~9ksb)aMO1W=Sp*~nkmJ86oD;y=N;(35az${ z@R2e#LFB%2|1tAwxV0ghq2Ms*D=2-d&kDF(G`KWu(lgbZ`d z_K!1C+Q{`fx^0d~x!2@MZ^{Ae_IZR&kxuDt3XnRY3iqZCo8sqEDu*=JH)!v6r=R2T)jjXUJMcH{K=9gLa;7(55|q$4GP#OfybX(g`$S zIR2Whhg7u9f(bjt%p;~epTxxoIyL8C;#FMLUG!($wp<|nttuOdX(N*uvT*;*uL;C>#Q+)W+euztyoV((awhrG>m2_DgHcVjPjx5u%34r6j%M~l3LoM3vN zOBUL2*#Z@_dF*!Cti}uTdyD>oc)m;8G4T}@vP{9~vM`>V>T&Uk_woBlt zOKL}BG;#U1;`(pS#+K`x;MCCk-;-zyZM7L=+q{z*e*uxzkZvEq*tB$`mED2tc6}A( zh-bd63*zO$M+lYGbdVqBTU3ET`i+Z`&8kogJzc}%8=u-roG%Uc-z%CJCocchbufHg zmdP+^S3EeHM`f1_B0d@Gb{SnW8q zNoYSa5JAg0xSMWYD}SVvU6AdSL>sqS?OOedclw%R(X#ZBZ=cc?)N;q{0|Z-V0hR0w zNuD0Ev7E0@0K;PRGiu)2cxvc(wsTR*M-CtELh%y|3T&?jkHQ&d>;Mas3F%OOp~S%k z?}Q{5Bi37~6xk4~Vd@@hv55Dig&u+P`FBaIa39PvHy*)^D)e&Cr#sKp<=)#v!)8E` z={@DFC@YurdXhtG=|;pM+kNplBu$lzXD6`2LdCt}*L5zpCg^+C4-b_26U=Jbb)u=2 z`uM*R`MMRO5*T5rqX|wV=sm<5;%-rntx8z zkpGbLR4)MhJxjcMlA~U}8$`6R53MIIH!+)ggs0l&_VejvvU3nZQNk@(p_a*FK(!X9 z4XrSaQl23sRyG;k6^xpmc-|H`Es=fb+*gIq)*g4w+Z0hkhV~|&S(3l-7-%^;02I`; zMjRmSRIUE3!QFJ8no&W3zf)YTEuytj7Uk><{qjs0< zkajGec3WUZ9Akv8JKu_suSM5~S;Q8%iqll>pUl9vUb0!fUdeHTOQBhFE0SyM9V4sK zHM{JkMM`uiG-1BXF5z?W3n|IGXj1hh)#Liz@9 ztsUJDZK2zBJ#sn@`h40dscI*NJta|0qb`*sE{`9>;KGQRU&~rfMF(JoFvC~fBxOMJ z%BsQurZeLtnirjGzcKD?FmnJtAK(u0gBtVoBmz6Z*MDy${eOB;eZjp@z!H3*wd_)=GJnc5TBJ^Zl}A z^RGV})_XP_-?k`T!>cEn2aiY+{T;I0PvVYmU){*=qI}+-q=SIJO8gf|XG@Qe0r_gP zttIskQ1JE8X(mbh$ypp9OXKctk!|v0LWo6JiTUWPyXdZai#eEAB$h+U^KDvE{!S9s(^wGIJ z4Lw5w(F3=9uFuAL;9brxsQa|5>#ikuVCMupFb-D5cA;3DU8!hYG~nG3=^K6aVeFB# zm@;i3D2A!`$d;x{GWCFukTf-HmZF_vcs%ou{De$Z@qGYSEa<`ZfMA1 zr`uM)x4E~_eY-E0@P4ML;+;tZC>cC@{3jYcxTIgt09C%?7}M*CYXBDT3XQ1OB8bw| z61ATVF?kd{h*T68aQsS74{A_mc9)=+1zW1Jb%) zn~@KyXfEZ@sX-UBmf?O>l$R{M?iS?_TFOJ~i9yH*Q%{s{(^B z*ul;!fBTOA>{tfj{)C(!KF!HtSNr43$Y)vGNx!4`bS%Wa9-U3hAu$t|zv*7JJr`6H z&Hn_Bkt8V;UyfUt_qL<8ivG2x4*$=CQZX=T(+vg1xT2lC#oi*6Aw1l1`f^&D2jUbm ztNkiTNN^OhO8+6wE6a6E3Rh~TrI>Kfb;+jj*(2R7Lz)eq@5QsTOSO7%OzKIbbkG9r z?T^o)HyNI3i&%Q$QHL)#=<_9>qo(QWbSJ2G+&6ilG)Gv~K!psyDd7wQ1ut9>B>q=H|93?Y;v0Yyh0a#Kbe5BvDb4BP%IBZl8?dnA7!qFTChxk^M#zMU||$-akgUB5kl47%tDdcfMdBy%oR zu>5b$qEZMvPTyx$$}5;+GG;lpk2lUFQR3lcv|n*CA+XBMM?8@*qmu@MMr10P3#&I( zs~p)fNik63tFIZUubxT3mz*^RO_U)7Vz%tD+abMThu*VOdRdB9O!^L(KzZl&W+~XcU%s1 zdW$-_lzK#VRikfnK%#4lI& z_NyzEbN?U%eohEL(nz5DC~hM_+_@X&;C^=AACHLw>51Ewd4L0q#W-p1Qd}Q6_us85 zu+DwlDK)pD8>-wop*tngRpa=eu_lvVga|;WnK)@xlZ(%%jK~C3*lo6pWnAx{W-uT< z{I9H6>mawwmpK?FP03z|!#i{ph$e<9H*>(&w`Mh)2tsS=t8ob_}dzM)8sv} z^~2w5T-cmn_X$)NeD^vkfPpy8!S%$6%*VksGB=@iqyx@VO@UhtX}+sv?NVNzmox&d zG1I6Uw?x3Mc`0o4;8(2Chudy!W@96st5xkf(0>w630!HlZuN)!0}pDff$N?*cDnPd zcE{2TKIpH@ zE@ditmL8?tNoc@uI!Q&6&s;oK5r@6mbY$5Y=RvtLqHMAus%wAz-yz(5qUNB@VyiZv-nQ!jccLXhtEVZ(FIED7RzORq~GK7avk^$kp6qBB=!+Q)*Yz=(kBTk z#eOUaX{T+A_kdIA53d)FEF%;ksh$)ST47+_)NpL2G}VDmc=kNy6tnRSH4Ytjs;d{@%FqZ)8~;(0=yx%%^Ig0vvf=74d% zYxOa!?6D2$MXyj$@Y&|?r)bysxIT|w@4kC#IW1qIA0yG%Ta}gIVx##hbmy!4uC#l# zG}Pk^q6uS9_8M(+4}WqQFFiia1cHIgWtPfDqOs+vy-ShNte;-6DuahBGF`t4imaVT zet91t6s>CZsW?MK6^s9ut^VS>YoYs2U1qM#;!?)6u9sOwnyE!1-S44MQ=*?<=<{&p z*M~OV@}3W-ztgSd^!+@1gQ_K}Hxa!opSV`H-G3;jpbAiz_8Wxg$!XZxyy6(% z79M#mEo10ljq&i;?E9$q#E*CL-d?J-8D{hSKTjWg-l)8m=c)g!^p38QLTs``(l?>M zne_NIk?D$AjLIOed*E+=6{rjM&R9sA%^Np^@mN39AR(qY27ig$YL5b<9K$9by)wg^ z`3mYNzxw_ zCsME>`nBi8c_Yv-vytnpa(^iOUPRh~CxuPTXYA8Gh_Xsh_P6qP)z@P*aA*sO;OhqQ zNT1v&X+@4ZycLeq1pnS3wOEQIE!0WM*&r}YlV$lLLR6_;7 zF@0lxu~Mpy5%DMa^+O^{a8-?WgRF{UfONlBfR3*qsRFTIEMg9_M`@46&Sr692z)~_ zFx6EI+ksK*MCAnG=iG&GmyDB$E1y{^CtJbY7+H}X-5#t#NkG!e3M45@M)rYybKrfR zQdN|Ab&QKrY3fw7?BlR%aj_z^!_*9?Lmypj%6ds zR-t{TX?X%A)@+sdU-<#w0!~BOduZp10P#4-OzFnm4;ezwfT5yxy}z5A(jAKReTctx zY%ZGqt02&UYE})(s8f+cD3Cu{fArmdNQl8Sz=m@?{l*Jd;^P6zpvTiO;}YNzN%MUb-y&7Sox%a-=yK2UQT0_wT>DZShyg z@Y-yV0dt*Q&F-Iqf4-!P`f!I)2;>NwoXL2H``A-1Q_+wP0{X=JvJ>I?j@VKe{~~M$ zO@Sk_LQ7TP@*ka{5GDsbz?U7W&zP!Dn@e;C4}NlR@7DZlZL_e@P_~i#jyY4=hx*|B zTq{!|XEcS${I_4Bo;N<2B4LL^n?F~einbYm zNY*Y=f(yw>znEScZ6O|Ssn+~Lg>1+!-Ajl?C{;)%B(VBR|3WpPr(T4Wu*a>XwDvPF zQ>Ti~9<9L-=@Mj>K%m)vzqw`#-1$6s2&et!ktj}|KKWcf5UdAGKKoV?szLs}b4U=p zbJnbbji6emlp;-)@^;+&ua}G}T90c>BBh3mqgN7BR)dEZe=beo#n#kIn_#xhHKCLb zOhBJXW=CdAo)9GpmYTh1E($0@ljjS9U{^=A@85DHIO4-kt#>iihQ`D70y%4i`#|4> zrw~6j{1=})3OtmopnvR{mdE1jMrL@`^z%lgvN)^5HWFeodq-%m$sJ=8C7%}5QmcRY z)naolG(09^@rDve(;E^swjWFL@L`v-aH3u9h6ou`8|Ni=5gICxGBm0wJD6wzRBo<{ zVYrTR0qjT#dYSr1S$J#irK5&Ky3O@ul{1#~QD!lg50O3$OLS(m<`whG?{n=^H_E$) z_i^RRGg8tAGg|o*b>{J(MylhM^b3%=@N}ibKOGy{=SL-8VvBV36v@q_yJZ?`+mtZshAzNrHD z_0m=a@|3CBI=TJ{Tjd!w0T^_j&wZpdUsEWg3b2(*fg?nW#hOug8u^ogBV- zhBb|9^RtkJl4n%a5+^p7sAtH#{TqJ6wi3j#J}##6e$%c1IG2;kD?I!1NvzPipPS^8 z2#1Q(nq>tG)UXSxDdt>aH@byq#sTZb$V__3sZ^ZjU7ABn6FllT&CR~PamW#|Nqr;z zo;%C#N1;W{#Ddw&WfqUbdZs&&cK!U18T!+=++7PyrWJoVVP6y2Oh;G*IXv$qv_+6M zn=A>=Gs%}`^LLrjjiuQ=j1R80?c4@=3p6nl;T(Usr-@|Vm5n*vuJ!JJZwy-|O!-hk zM*nMc5mms2C67I%H?!%&j?_6FSbSCv6^!_z&zQ{P`?pSk%1uA;jZD@uS9Gy)qLq5K z8Y}bAyp>!7{YKDdM!R8qe4#5rXr%QWwvDfup?QOWTBO4;Rzz-j7N;j9R zfamxevYEggMcgB)+h;S`o1`c2(ipur{mQPJr9sfP*AAOm4?sCpO-uY!G@<%|EZSs% zQnugU)Zv4o>tA-?VrSe0Jp1J@f=aTzWP$;_&+mR#%AQMMu1bJqEsCyGeYg`t6(K4)!g&udLf0kc*Q=27qd zy1wZ@jL5Y&ohC2iKfD$0b)y_vR^WD^S_c1!h>f`=b;Bx#W$JOUoV|&RXXO0pF?h!U zR+z5Q~6Y`vYY*Q&uqMU~N%Nr5}ox#~Ng2sRh%d$!~7kzu`#!;W|{qp@0O$AT;Lka*A^Hx;^9(*CI9hoV`iZ_8j;-LQS5++-@A?DGTf%gXH0#A9fW_ z*)1yj)`%jU)L<>%`t9EcdkkKpbQkhA{?;W*$R-{f)|>`0Hk#9|^SGVll&JXX3B{QU zvHXmezxa~SE-%s}JD)UAHDdl!?892EJxA%d!K)J%q;O4;{wPgELOItN?VFsg_rlQy zAARXfcN@2CzNx88XPX@js_L-(F3*f%!#7g*=EI4p|D1AZqBGmPL`DeogQR#= z|H4l-y+pWMV=NLWyuB=5d7^rju9SdHHg}NTNXfkNTmYi{A+v^ccwSbeFY`u-v_>GC zeEW(!_TsSxx}jX{RB-Eu#_(iwPfp=yUhFF$1&=&mEQ)BhdOvAbxe6SVCK`Y!1K zNTHS?-GZ9FdaM$geXN3>;B25lXx-~P|EEmk_{oc|r2BS=c3%HMCZ*FwvV6M!WzOrC zz<0t!-?WTJHqUT8sf#f!t{>Oygp}16*IQeLpU6RJtwDRaIp4}$S8c7NAeYKSTQ4xY z*?U^htHP%30POiN-x@a0Sy*N`9e}bryZ(pcpevZRKIt@Ziv-iG`Sn+4ykJQR^lK`G z`|36X=;RGuvrIQ;^(?s1SafJ8pYWY%?fcu>5TDGq8MmhI!1U)Ev+f8Lj^wxHovVIa z{T3;aKMZq$Mgg?vAPMNf>XE0pVi_>Jroh}l#W?RZ+IVwzfHVh{nagJawcVhg^0?@`jUGZU$!AJcXSnW5^|z9#0mT?a+8P1ih{)zwDqb z#r6JjZLt^(>MC_J{%piyhd%hkaG4L>ydEdb>9d>+3^@J=&|Q?xyIO~}!o?b%L1fUS zIQI<$B+^yLb=ApEl*FgndwpqH&P?fJm#Tla3OU+6H6hAi_dla1@z;n@f>VAG-J!Il6xQ&WixD$9p#+#2c+mA~G|>QWj(;MfFQf_lJa zvQ;LJ^U~@*0SP`NVO)H^CNR|R`U4;RBFM@ToD9!F(WfiZWH;kogn-0qs(X7_6Lxzq zG9r8gUR_|m{M>m4to;PB#enecA^mcG7Yk?5hK7uDGc31Ge@)!+zpU33l{oU&HzfM* zVf?g-)I59lDAl7=CXN+@;mYj|PV+Bz)tPNj^Y3QkbN)M{T)Z!;0KVSkhh|Q?SxkMc zXrznX4QkNGPa)~L2U+8rir|lAco7%~Da0~Bf_jjhwQD6s9{(hp8g9C+KF%7FZz;-v zcj6gz1eHK>|GoqACBBHdq6pL=QJyegJW@Z`!!{4QfsRfDkta#H^nYv0|Kp>~| zdF_tcW3IX62mZOc2oon=3B9SBOG*Flt^nh!^ZHEhhF`zz&3H-^BdOmwOni?EXpr!&|39 z3U)6mJnH`omZku{=g(V%Zn{)bEvVD;{p$gRUWE*$8DxX!ExY?VjJKDo2A&j(xHp^r zEaz!Ecezb<@5SStQi7m&0bwtp#v}HQnv~`mm;8o~?)H0Rb0kA>%c!d&D?8o~REaC9B{HkCWpr{b z>M3w)(XjNwpO&7ju>B-=O`6Yff8L`QvTPIS4SGH-+F` zlifKwHTy6A;pW!wt;>e)C%468e_*bXA36z&8l}DljiGGivnFR6ntD3W3OB_g4~7YG zIs#yezfi=#H4Vx=Yfbj$j#$TYKkw{|Mt^WP_2>i7TAD7t^&Ckp5FtMH=sW;bJh@-^pK8@xlAZGyn*LoeR)PdE+qFj@z)TZ9lOb( zH?7JRXaW?l^Plky;>u*+PihcSQBr3Rq`S6To@u0kY~J>_Tnp6vVqk}T72>pxs%$sj z^+@z>-i7%$e^SxZgV6p}@@~Cu^>;m83ZHgVaU$C71sA>lkD{aV;Nd@Iai~qDJgT-J z%_Z1z!y@40`WmbKzFjc-AN}1lmc;CHZ*^;+Sl_L%M4pD~M3xN0If5{kjT}p=f_&j* zO=<4={qu2WnYWV|g~C8)q-gUs>_*Z=)VE824%yG0h7q6!K`iWaEo4W3)Bd^JHus~(lZd(qOsX1>Lo{FNiONbesj<*Ev zGs4#ten8;N_ML~!n@?(B!I0 zaGof>JK%)$A9ldb4~bv#K6!CN5w#k4_bf(ur;i3z^7P+yu?5?9NQj^cGLUiC&i#kQ z&cL1S5@Uj034G`XW;W6;FDwKkgF`p;sd|uh;5M@w-eCf*3`4N9LeZb}I{~Y`E!@B) zd)ofCte!h{l?f{e$i;m@Dt!?{S*{+zVBzb%#LJKy1DR6>h2Z1dqF|ZS9m$lEi1*cN z#)LPP%zAwnc6z@b=W7KpbEN7K(ZTCwf6zrOj{3y+-LdZ=XX5&V_b=BVbI<)JgLAk2 z**9BN-fV;HOBTETz9c9`OQp82~#lQj{{EHI)z_M5RdzI%_>#<~NpuPV>vZv(q9n@--<=Z7t3 z8``IyRxC!~Pi|eNV5K*3K(u9Z_^+ME@=w+3ySK&ydVCiEl<$9m)II;h*m*@Y^+kVP zI*NculP>TRM7s2rP?RD~KtZG`9i;bO1(gyMq*v)m?>!(*YUmJJ=%I&D5=clg%zw?A zhk2T{_QN?Z_vM~-?%jKT_vf3HfQGa<3XLu>-7Hx$OqxlY^7BVlAp#@Iv>;S$L|j#$ z@!zj{eBU9cDoDG%VJ)gX^oNBAnGx6gdHgTsiD0v-8k+#NI)=p?%e7e9gX`~Q9PS;G z#6j-lm>}*&UOFjLE8{HK6@mJo=PxAD>2O7(O2vG zTZ0RdGov2*Z{pf69+JuK@ILs;WTn~61H?zr0jW(s;@oPrIWuh-7!5Vz*{=lI* zYe04+VIC29-dXryUDah(YF(HcTtjx~^HW*h*;Xzw0CU;y`!w!PAr_y9tm($3+Df(LM#C=4Y#NfLW@x%e6; zjIEp-n+o=>Y1foB z%||q>AQ;Xx5hiCoukWKxNCEL5t!IMSQSGiS`f6$CLSWH4hDzT+)3^6*jfH#A^Z1e; z8OwXSB@eEGJHw?KOI}5uY~yk)DQd`?)t>UE$if;{&H^cd-V2|CB#Bw+-UA(1x)MYM zJ6rBPqqsikTsc$Z>F2J2{}<`H8yXdM3|o$EvJSU@SZNc}{n&jWc+G@1bSd(vf@@n; zkksXIA+5x{?ax*=j>x<8rzakHnRsi1N(9aUdSiu z-AVZbjOax8cM@y-Hr9%{2~3#7<4v$PkOjhxK48dnBC2{spyiehm84H6G;B%;k>=0O zxpn%0uMUHxxf0KzBe!7p< z{Qo0in81eX=*3^&ad_4%f194Dflm$>x^KE!z`Jj#*Szm9+_>~&T{k$rz$bIUm~zyEe!{lV@uwFbahiJ*bTtt_jQ%A_f;n}07q;3$SIwIhVvY-b z9p(zWJF$)ouD=N;$(zXTRgmq@A6W0&`#3pt%2DRk^Jj#j%iS`bHiWs;iDre%oa(B5 zXu+!%B7b*+`s^@hL!rGX8dCe^95=mliu>?cIL0A~G&oCeql4dI&5b*tW-;GtD$Cn@ zy<>hOllP~!VpcDUNFLX9sL;=XM6YD4duW!=h?>FccKbsmtPrs1Uk!Yr&v)B8UrRh7 zu81jz*MNG>28DI%WUtB&A%t_Um~eEuOa&1HWK9YOD568H2G$khUY+Xwgz?W)qT&L> z-cVxRP)~euCJ+AHS^fGRbk{Nk))7g zXX9wh!D#G%A>q$@^FqPt!w3~2as*&5T1hVq78{P};5_a3I;~a~2!M2Pc2h8RQcc}o z+bJi7z&-m%J5Mb#e#xC$44hUz5G5Q^Yy?RJ0PDgg@sX+pMSPJ-CNwC|D}Ux+)<6i6 z!|M`?F7Nc+04rL|`@87pq==Q5y_S>&nsFj{J}KPtXZ`=Q>z6SEHj~?OTKF;^21FA4 z^z%aYQ}db$=)?^|*HS29|8n`xMLsrM6fc2?4O`!FB_P6wU{sPr?C#9dnJBXMOhfr4 zfL&7G<(uI0T$|=e&&K4SioQH&?3To_M1)+D@oUM&_!Upohl5hwg>-P05-h2CwOJ<) zn!XnhoS~FC;@P5-B*$W>Q2uFmswqNg%#G+~SaJ!qX_8daP}eoAJ|*fzhj%Z5EGc}a ze>qd1?ST_=m73Y38+}bn#M2c2398osT4eMST#X5Et?l!%$4vHOSNQ`@a^Y1 z8)q$9--7b*7i+m|ow-YKlmbtbuiwNVJAdRVed=~)p0bl1&ijC#VR;nozO2=}Y_4wA zLc6TLC}{g;e(9ctOYmtbBPIv;7$Y_ec&UUU!j=b$;&Pg&&S#nPb$JC;lw4Em0$FI_Z_QUuv1Lc2IjF+WKO7$5a!Z8 z%SruCc-|dLk2SrZBtT4O`ncZGM}W@g_EOJfdHPo zo5R*5iG|IeyI#!GKI=1-7xsoIwuBk?h(cauaFU)f?tObkTH&_Yh1SI;X@Xarg}Zvz z_vSQ!PRH2Rn{O0%=%!p6`-Q~R?775j)f9(?bR4p5x00PMlGIO%O6g_avao}?744eu z{E|rgF2jCaBN)ce##Q13mAZ)Hem2>cQRD=D7E^`X`y`O4KCFWg5-y?G&u&~)bZq9a z{9@HZ4|HV8jw8Aj-wsJ2-z+Kb8oFU*F;9P7sREIC04yrZcBI>E82i~c6%v~^^Q_^Y z5ZQ%cD$KTQ(apSUF;fzjRO%vzvPyQ5!8PUPju#8Qem*cEU9|spJE`8iSsU3gETT5- z+5B8~CWJOLTi?#7fDa&c^rZW!+-l7%2!~oT0Zw zSKPt=oAsFoUD2(u3ONc_2=^&fmh-co9q)3k0B;G7m-j;@lp@X;NR` zz@-G$pwhrzcDJ|(;Hc(Ov*dHKEDnfdt{;Onf%P@*i~;It@U6s*JeQ(-TI;Ykav_?0 z%`I+R%(d`CfBUd?9@FyMisX$PAltzF9Y;vK}Opb^pIeM7XPx@ zu~2a7j+aQVsQS6izt8cmw3nHH3rv8*_XB&0u4T)F00uDiB*aFsjOgTn;^_IhcQ##8 z%L4DE)@j6L&t}Oi(U)sUDt*gR?|pzg!`aS*^*PsdAO58lUND2Z?kxuGdl%>m!+5d% zdhD9pk8PT~0^DTK&RQ#YtcB`(R5rI>OQ6xQNVw5oroF?!q|T=K0ErH=wGQssV%)R}CCog3JE zV1;f32nrXxLi8mUY&HCGdUT^$FW8eC*Xy9)NY%sT-sekeLEQ<9T%7ZfFLw<=MF|wQ zEQS|a6_vz2aFYQRj2;6g69c-54Vkwv54@Nby^%3W(65h1m&e8Zcv{KNv24e#k`qFO z{zOIdB>6nS#m6#;U-;C$e8+z`^iQAFYd-+eR#X+_nc6c2j6K|@$s{PBFr3b1?@=Bk zz%!5S{enoBmT2%H&#w^P_9;&HtDiGR;$h!vS65t1U)y+)t~-<&CF_Y;QQph8>Hg?W z^ir=6L4&1FI5GaWJu0rI5GnBI`#H(>t@qYCh8RzfkUda;y~ZKEj|=`+3Ey+OA;elZ ziZq3KTHUx|-LNu#llVs!v^H-5_A=bfX?V^y|Dq!|EIRqjw}VM4-d@&q&<^Ea*5_2^ zZ#$nkkwjs=42tWXdI7zoTGx_uX4&^1;e#YkxOIt|2>2y12qLcGdI1K03k#!Oc(fB9 z-N~`;POECuO42Gzq_{2PLjm6)IDgzz_%v6_7poIU5jrX&t?l}wda!|mRtv}u1g*>^ zw~q>cs04n!3eYU0SsyEVkSCGf0?8a+KhLjEC!)>nVZd9Jpce%Su5I@J!_qdt3XhxK zM~NuwP;e>I+fnU3pWGu(b(gTias~@2eX!5K7P^Ebx)p!52e*C4C-K=^6)mj?olEUm za21M9w-gBKj@f5i@4j#@J@iycNh+q_=PftT6m;T8XeSo6=19*hSwC?tmZ(=X);-kJ zaMGBMx%o}4-u2VReE$0!)cyH8jjsQyN@bR~J92`;KQe^-A_SD56;y)w52vn|9izF`WjQEF`)0D?2ghBH6gT&V0I_jCRBmm$Co$ zCT;55A~NE0LXkcV_gxc){i4;}bqS0?_ClQ%j$xE|WI4{n<15-)nrc$OrZ`UwL9UNA z!Te`CO4}QrPJ)U&WR&c&&O8w`Ucp%S`Mo(w{3mHQac=(+}vI zrQ0*gqvS5qPuNd(giP_ZPaMUPH!hny@OX2bc-(94bJC>E)c-}%N9@UQH5NXZqM1vq z2h?HPlk|XdsqiXMqb6m~y{$JkP%n*i^^45L?$J}@IWtUjWwNJgy`{4cBcr#*?E6mR zmaU3*fxi@4&0Qgp3|SwGdMWlf{$|=|d5insZ9KA?GC~DEC8CCgt2!%|BjamzCdgJ4 zjzC97D8ysoq{ftb?mc|VB0||)l*iq$d2AwjjI)5cz-=!kSsxuGszk%$M>YNOCW&-K z(IY3b0BWSXRi?beb(aJ8YH~lQecDpfpW8pXO>dAlGVzvOTuSL8qLQ0^42kex9;@)H z$^6M-2VW+yl4#fxPumI}A5BhfsQ+UvWufA*+_Fg^-cyb%SW^xnvmmS5vSZbBu!Cf9 zMR`HgpGN!vHD6xQVPt~Xrl;1)lBH#)@1GlCgwI4izj!qMFzmEp672Ru9~>Ek^Xz@G z|F@BKVP@4yGQ)iB=LFHj+Q*>#Gmb>YR>WZw3Ljaj^Q42co${f%Zkj2h{%U$5_f|Ty z!Ui684I9ts8`y{Ij81M1i8+(llWk)N(N>HbQp#&_bnMi_m`9J9p8vP1Y}H^^pu|aL zal@*(s_Um99O<{p1u5DR`<>s+H9$DNa2i8C>~EP#kHA?)^L5{!U#GwDT-nm< zzbEGKjJ~F7r??$dnq)F#_(3)X`}<0`_-^fZy^A4YXTK1>%0=Pb=Lx&_W?mejC39nEEGXZuJ7&JKL?XgsN;CC3tb236 zPCv(y)>YV(IBt)kW@brpKaeEtax`xD+4&1 zk5?MH_G)2C;zL>f*EBQ{)r9hzU;E7b7lA#UJ!bflN#WgYQhexB%o%a(Im@~(d>MaL zbYZaVIn1#5leRAlz+kvxpe!V2-W=OJRaY>`dt?J!4Htx*d*u^)YbrUlNZ_G5T-o{b#Ft$P*~ zfNsxC6OCTmOwOnLlJ8K)g5JxBC8zmG9_wveRnX@Zfkrh_tvMN_qx5Nvg25(JCv; zzA*hA8n7p3AgQqX1M10t)^1Rfp*Qx+5p;cTaQ9t%B28~DO{B0CZQb&fGiGynFZ2y4 zoHFP}qn+X5A@3xS$p%63Wdn8aFbI2>8dGI6C{XRePR`X=p6=^IA#eAHQs9sjTc{%qKZvUgmb8AmDSh z;rE{uf53u>W;G=!GjAl`X(&Orq#F)nvK1pvNv~}52LbJdilbq7y95R*#X0rBQQJZ6 zZ%`39M(ZEFPj$%^8vYY5Zj#)$8y8`TVR~dD{+n^)t3reN`!7YktlQe+oN(*l_(}7F zeQ3ZETW<{^*R6>_b9nV>EFeyad|zY|o|tTeplH!7z$V1K^iVvLFF+^8ji1M~F`Ad< zBt`fFh#TLF)As7cz98Z?l;PI- z!*~5Mucd{4+u1WG#wbR9iql=zr{(c|SPVa(YzvRcNh!AtqiXdEdAO}rU&qxDKz>w< zzi@nSXI@F1>Bru9#QZq7x_JBSUS$OmI%==9SyUPAO6)}`r4h-m*I&c6vMHWLae_=; zy_>u9JWDO)m;z*-hop-6N@;cn8#*>P?ne{Kc!RTlJ>&d(n!)47t~Mf;TQ089ER^a& zIB0Pyqin8V`>j38Uoy?Am;26|yU>Ct==vR{tK+EoW(L+Xr`oc7vA25{>Cu8Gsx(8* zo2D&;aSw)K$95V=kEEyy5V_=*t&GNV%stePz%9{0$t}^x)PIJ3c-<9NV`@oPTv<+$ zQ^>bIYjqxHXG`zY*IfqN{Ah}-Y$Nll4hp+7Rb!1vXbhv|DiE=prXp}Q8URX<5k zTbHJ-qaQezM7aJRxz_(xZV}SET4-y2%c5h`zo?4Oy%XS3Uootu6Ch8Bu!W3O^CU7b z3Iy>`xV-t6`abK~+gEiWbY$Wm-@J(VVn&*%{A7v2seWPXH_xwMhBuCli*8D9iivFg)U zuhS+RQr+&ZE$-kEm*8gvC=N!)@4HICan0O`|7H5@TcpAknfwT~*blT)3~?Sf0q*dY zf#Vru%7E`x2a8j~OKeDU{O<=rtX7=DqnNNwSX|gU3UeEVCM~6y3y)M_jL(z5fYfmM z4t@$Y&3e;Qpr^SAfzY-q-o?+@H^8RYG1kqB~I#q+-8=7PxynZ4$Ut zkML>Jns*n!E{T{Zh#N^7cL>*ue%v0< zk*_ez`h$F|QT{h_mHhqU){gC9Qo?wgQ>24XjRpoax$D-S{uwE+Gyi;9U3dgu*X4dL zHezW|FG9q7#TLRv_gBNb>}dyQFV7LRm@WM#_ZMa++s;j60a4A``y<~c_$n}Y@6_6Axp*s>!e=~6=9{JN6R`> zoHSU)O3)XZ_n@%(XS5EXVSIw24NB(*C!Vy}8}0+4DL_(IJ%Gb|Y)!Sx`+;EK?h59r zyB06~IS{IU@PgTy7L>`Q`*L}Pu7w9La3BoNGBoUdfk7cM`2!xyLn%48C1$R4ksqV=uj zbDO}l9}O*RVDK{g@wn2igcy>9aH}`;KGe#=>Lr>jkCVyW?gm&3O&Zh(kuB!Y-r9+7;&g)t)BsfB2Lzn`uVh z!5YZZ>=#W1x!(dDPM$Re6JIRme$o1~1w|V?!PSXiZ?hf^idSRp;(HxmWLbU8+;Zs5 zqkJT_uHmhgs>cuei_^iN=bJ0M-_f1hFEgXujka4pTGi^^G$MW9aoQw7yIUy`S4wAu zgp3Qc^;acfMZn~{;0OO)F7BWATq22yk&A9&*=eEUm;Yp`A?EQUbd-Obn|g>&?{$NL zG4)E^0rDb(2s6IpElOA~jQEBf7UL;L29ps{OmR~UY&7)HajV`AZjI?|B?&CJYcwf= z9H1P^&|eClPV(V9w7nhM?55AqTbU zcZ2O?LZ-d5)yDi%)Sz~eG>&&`Gp@=U_DF2fEQP!|VF~bFO0;v~A=3x*_Pd=U76OtM zn7238b%wBWw#8tf^GLYAUTP3U#Op%D&e22GTUSo-EJ+4h}TXgrv5w;6bhu!v^e{(_ycsU zZ$CR(hU|mXQg_s&S^%19+Vz7zf&93p&%0>$0}BFOpUb5dbLB9&@F6So3UD1FJYq?E zZGPCI9R^nj2^4fh0C`r+W2CukLM&edpnSJMQ+YJHb%Y|(;hTB<^WrH!K8qf|f~gtf zqo(6MwhQ1PvwM1bfiw_*#P$t`upLq?5Ot{$cd_167RmG#ODa3uUMxOY2I`25z+ZK3Gb$oH z{0bz@NC7){)C|u`a`GE8O&(wZa+%n_$aZTST%!(SCag_wUi2sxzbyN;)@vB&8@f!Z zx|%}L^$PRT^l4y}bfIe;*$rX*K?A<(6~-YK zr%E_F-+s*rO8VBHY4$RY!GQBQ2aJ-P#Y9`vrsoIzL0W8(8mVQO26xz9-#pSJQ(<4l z>i8$1P$cvmc7$eDEh+`8U&~i$nE#mQJwIHE+cVZ;PWQCf3|4>iUE^`T0~?nY^Wz87 ziYy~Nz};5kJEPA*uPhS+t-+OtSVgmsyCv_~2H*)bw}g`pqGPh}CX%EIB(w7$E$^8x zDAD1+`sf4|MI@hHctORt;@~&$u<2T1Z(=X+tbN@<*7UvS zaqqjtcyDc`wqB|UXp0ZARA&-2u8{iE<4=JLS4|@hBdlI=BpO7JIw9QGMqO}XU56gV zTE6O~EMFsu&PR?-Kq(Xubnk*QEFHlXs=j<`Aw}sDWuDSG>)$j60X*3kyvosJ3HhvB*Z_*3Mi|OrKLfP*h(xLPM%WL~(HM-N+)^Yc6{ryv4=~!a=WV&uAecwBU zn4YjC9LImD15dZ?w4pqQdGW)9k*fz51HMIM8Uue@t{Q2ccWBcGQk+A9YXkTq?)U48 zXf2~;&r^lWFu?@wq0cwl1Cbi?FGs!eCq7Yp<(>QM^o1KhPWc0R#2#wcg9m>#R zp)e}g+31~Y0j?lJ4Eii!x~%x?q{(~dkWj)H8vo|Bn~)|!dV&Qc-F<$&_O%m)95@S` zcfe*`>9jx)&>364mAr+coJ_k$gOr8QS# zZ7LZ@X+kY|&k*iQM2XlbDo*sv5RWW-5st-x1_8t}?Pm6TN$sBaxW)A(_hrh*yx z?96PJj;4gFI45*)F@Ee^l5Qv1U~fzHJMOu~e@el3m!e~zt?@)UP^T`49q*{iXt7&8 z_6_ZE*Man6HO&&!Ga%xQjG%nEc^NX!hBwzCfBT-s!7W}bi7QzKG=8}Pfj|2w?c^+w z%fXAS^LN)CJ19M$q`|4l%|vvh2KR%pI$ZZ-hKt4XzCVZg8EG2DP6JOL>yxrL5j+4d z+V&A-OoQ7dFk@o(cL0mKxnn`$RAL~z?4LO-o)825Ft3Q{qj*SRI1HBmSAmQ2c*-R2 zhRBX>U2EDv9aFYKB|CZ^!xewS&B>19unw&r3utdenf8Ozq${(%j;nq?pZ@@3sf^!L z8*FjlKxLD_CYt+suLqUk)I{#?(JSHdOLz3=f5<#H1nm@Woc9#IJcSmAo`VX)J4OA~ zztE=R--({Lo_;ur-|6P!MV#RxC*mXXH^Vh#83J)nv9#hyVh^%&-pQl3Je6jZHsD_Q zW=Ms02$Sv)sR=*1O$d+z`h4j;R5APfIzV5Z(e+k0EVN{3$Kf5U!<^ z)DOzI{xARXDHS)z=3%~wgKjEG$)bdl-ZavehvF5Q3bDoMz%kEHPzk(uKB>`|Qp>l# zV)KMA1bIWdFzZ)YVa1&f^LbT1)W&x^(AV#1EZWpX@(GhFzS z913LUXq1xLroqT^c0&}9k{3!NS)Xn-anBu@GWZhv( zm8pg4lI{EZuk(x0Hp-zNI@xVsH;4d=D$}l5WCir`$m~aIlL<(Y!7WYEJ|b{l_$$>? z(~m&HUc)~L-s;|m8>Y~-&{>gG0Pgm^Y;nXanEi$RQ+dBvj(qN~GxP|yG@yQ9GxiR2 zmF$wF7%s0iT?x;x1DWPucMC&4s1T4!c%i#EF<3r7jxzYC*MLGy{+WZ(;m)W2Q979q zD|$2CE2F$8589M33@Q7;{*(!2_w!}b&TOp)yStzH)QR!}zpcY$HmY+@Akkk2f6b_ z{^f?mTToLe-(=PO6(gl5FCrMHc;9bM*IKR3{jk5$)J!L15edxA@*p1!neJH0?++hh zEi4&Tl^cp~JmOV}RgjKpTRMCg&^df{^*CPWEswSft>Pt8g}H$5Ul8QpF$HO+nS(hi z2CNt|vyz<0hCzAlRQ{_YaRbSaE@~_}yA=#K$9QA=Y-_H(2mVCgVD}zlPd;g{gm>a& zcE52^25zZYrGHuJ?*n%7E^q|<(GT8G4A#&NrV2~+Lmu!sa=}&91{hUk>N!cy6@^07 zZ7K0%2Xl|J!;CSBwf5IE`U^#&_?H`?n+`YXGYrv&kYD`Xqkuqrn_BN7#m%6Ruf6ox z28Ka4Vz*yOl#ts*GN1I!5MUqNXv3zjO`Y8QiC&5MY|xsZ$P>^%V*{ka#XLIiyHPxq z4m27>>K&geg#!&Y715B4?QrejtY{$_$B7lvm?AX*@ywZ!mqxgKx7h^vDLuN8d7tO+ z(*x1eZ{~CPo(9!M&VZ7E-_bhQ7su%KGS63P0HF#YRfiq*dlZj0}D&HZS*Px*mwN4`-Hf>R{# z9~#9nA=!7CHnh8Pp5411>yXZ2Bu=~P1d_>mxJGcL@|v?P@dC+LK#Bi?H#vXtZ(yl< zMFprmkeAs%L4hY5JInV|b#tBu=83kx84crl4Bt=izOhdbz!r{8FTe^v zr^A5M%VpmA@7vF{EMhEx&S>qNd;Of+hC*fj9X3= z?eupzaXJp}ucom1=2Msd2AK3b$V@GOTU2UJJ1DK|JXwXY~w zG(tpxyQN%T`jW@A&mQtn>%ON9t)tD4!(ZKkuO5b2?9#cj&MLgTNS-d*S(!Kl-tdK> z-CyKE8s3NV1qYRrw4PilR;PNMO-^aQI_Ub{b(Das*G~&njQ4`wUb5iClwc>#o8Mf6rCHF2z+fLwH$$A~xX7G^blW^Yl@= zq@!*!vP8up3d5Uv{90WX5Zl@VTfhIjce+5M_k0;;jZX9WTmLw21KfU8=9(cwefg{p z>qWMoO?b-NYC4}dG@7dAp90&q$9H};h=(Ws zi5hdVq#XL(Zl^+sbTEm34f6U6yyx2QJ0wAEH4#*7=f(te4Ki_5Tgz|U%~DP&aCK7} z33u2Ic_1mXECw50qZkdcm$Lx^W?cno&!*)s_XFlWBM(#m)N_u?o#^I&htyYc&mR8^ zdzNiyiiTYMK&&|(%3Tc9H}~+9Xk1Ge_B8rPgpoL&tVDaQ4JNPgd%9&$g76_9inoKi zIPs;Qc|bef)hgD$K9A?O4*z;zhau9WZ~x?9&+oYQHk0ALMfJo;?lJm}96bs)wKl#Y zcDDgH=ov2=s%u)Xoe4XwTXl-eI$*1QG^H~G_)FbJzDI(1gaV9$S!2ZQWV>_Z9aoAd z;?C%!^j7>yfG;ybqjFrXr4_>ga*YbNn&?i%KaUADD15! z;X1*Da@5Z02?4ksF?|x#QiwT*BiT;y2dBFY< zxsuShq_mOnZQtYt^Ymfw4?nQ#gcCFt<6)_P=CPrqq^mE7rr!`sziz~0(l%2 z7A&jb*mX-qzMME@$o{B`$-YFOqC{f4a}Cv=9n_t)>(zm5Ba7huSEZTM_c;!%2y_T#Q~C#p%-Vp`4M+8l>(2}-WA+Tmwon92n$hX7U*aqO9g zfBc2EJg>i6GFgF=(*ynd4LJ()@20}=RJrO*zw0W?GUENQ&E&XbtFQ7fwX4i+1C5lx zPx>5oNo>o{?ZbuQ7qrdhhv^;Wzpf;UJKcedN_0N7b=8i#-xe-=zQ%N9;*Ch4Y1|Yn z)N@!f&NShoSNGpF0LaMiZFO>8-1t#kuYOg5xP(sL4Sf}U59}XvuKBm_4@u1w-BFH7 zY>-0K#Bx#rdXc}<9};!Z@Bag{=_Tx)o>gY zR&?#o7{Q5Px2@%u~KOS*U5=aWIeE=q63w^M$0CC(#&gdYPz$!o=C zb8`RM9@v#Yr;o&R+0uS~OA~>pjDlvJ?4|5O^8kx05#S=E;3?JV9Q~O2`8`AWWP;7? zVr7jKe+F-|%p{NlRC67hS8O>2KRlEoRKExTs0UO5CURE*dbT#R~^J2ag*J zxNHG`m)3GEzJ|=R*`7$v(9y`uV_#-CNM{N@cvc@hCVgJsy)bJN!!?H}4<3Ik@gFoM z>*BXZYuh_ot*qK4{;b5W6`*? zMari>J(s6PhEiI&2R)WL4T+Y^-07~b6Mr-O=~kDjV0wQo()h>kMz_l$%P+jyw8*_* zC}EKOXs(G;BkN@ET8zF0P_b;#%v{LvBzoMfIDgjj(6X}K)S1ct+^4}@hQXO?;BUR^ zN_)lRn*tf;qvF5DHzlj5kM>)85b+^y-i1ZVKstfLrh%*Mnyk2~_r~Q0T*r;AUkq9Qv?`;=<*`<#mpk})7rH+u zfq)M8f4du2s~>t|OfY=gu##YIaGTh>^gmKTlFt8O{BZoZ-*}S8TVYM4pDbUkRaQHewPcd*- ztM7I#%0NJ0XA*9hZ(z0I&V+`K0nCI2J3@mtq3nMGem+Mi1WQdhKh@c#s%AeFED3W6-&bz4nNZjSkelyvTufj$@p<#S8+jPs!NZf~1rYG>;Iin4kT>t*))GjZdj|*@-zs zh8j8T?Z84bFXAIRyt6$ZVin zo+ZP?b{|X7?GCnO*2ki-?god-LkX!dx5!hS zT&CQ=kdRJUQnOl)vPfeii}lR+<_gH|UGgXc`H!H}-BD->S$_R*df=A3D3veECAx04 zdxBRt{C!GPD6~sq!=uiVzI~O2TyUH8;=;yFUHBTr{aJ`}Ha|7`swLJ39$F;3J@i?B zNED;9y6dq}K9i@s1hvX;9FA)e7p)ZT2CMokDcyv~E?zlPA9@>3!m^k@MeE-4A-g=_ zqz*D3jXM7QS!JR6?ZsMWHQnLc7%6#mYdK$yqW@On*w|0n0Q8^ePS++AUgHC53B8?X z9yK3wn3nI$e8%{bVb!$)IN3k3SKamJ;iR=|iLYwedwYzyYwwnh-OC{?1yTz4`YrAh zgfopw9De8fxXOMS=vKKG%79?b8a~vXHYPqOr7uYc&VaC!0I&+VEWI7qpU-I4?2uPK zWj{52#|HlS++3_nwU&8-zO(kz!96azG4Hz{(merEX7SivBgRimGv9T{zeY_b+oarN z<(c?-r^qPE1JoUlNBkmm>=8tt;b2b)$3F=8B0Qv=UQiFvrj5tGOeQ4lT@Ws=1@7R` zXRr;z3w-d$fm4xd1mPc;OsnL#){o+nltPP0= z(c5#jmWGA=w(iDCmv^vfS+5@zG@v4j1aerpkURj7N-4ylHa1)DrJ# z^QcwmVMnAr8LjkN5}x_#_FJw;Sej%^2NS4+>Bvz~A@nDB4Q=M)R`DmK!BHZfPj=s- z5!L-7QYKkjW7jA4GWw8)ar?Ymn{R3Qi}76nbcRBIYF0^e$NpAq>xO+-C~wb~2nRl^QTh_umtrN!#H3cyU2Ow|cZ!_2sHE7L~$i7~EOX`*WOXQ?3qp2JxdEbCyh zM0K3Lx}ZZVF^_vq7)a}QVqa&)Py@CBpovG&%A~*$(k){UXkw+xg|L1 zFE!Y#+*$6ct{=&DW!hVw4cl|@M)CV4u-VXhM~|&y#Jc263*xdlt2@XcTkXrjSK-ws zZi9T`jnNle$2Z%iX6~YOv{~2Hy<@&rG4#AxLL2WR0=d`RtS5YOapUZDt zjhqVAcYZWJORv(BFApyy-^;SCbk%yLqc)wK+V1O@@2q)h((+%)uz5#M^B!`S!9Pjv z-{m}b9-aZ*Lu4VcQY_pT6e>LUJLG3poBw#NYWv%wE82^Bp=HmIgXDAC=(>{ju{AqT zOYkXLs9}OeV>I&7T=eCeu0WA>97bNdX?5>%PFi`oFEc3! zv;0CB%v=O1^;g$szlrXG>CFr+UN@U~fjLS>IgIbBcd;Q#KIl+;YX&ZNB%zn)4oIJZ-Y`!?A9h*vd9+m_4ld9pNEXPpbYzK_7^U6OQ%iE^~7!RHLM-7h#sf)H?u<>+I};H2)sME~GRo(9?BWf}2qQD?7u z?2);|)a<5$i?0E*xIEiw32ux$p+`qzidw9Tx@umjxO-=!k)k#3sO`keE!FH}T&8x4 zcFMlAA&1ttIiq+end_&SPl>s%hhoho@^3FsD3vT>@Me~+YH1DYbj}aegCpSat`8uw z<%@?c1AhMLZ35Li6=IC2Pez3u%bm-=DB4u2RTmhWP2Mt0&zo~Qk29z<{`zfhX8u+$ zJKoj6#iCFJ?vqp8JUc#^#AU~0cKlmc4y9pb;v#V}y6f9SjCl8M|(Z8l+u&I?|yv@F5?T_FkiG8!#SKsi$u1TGRhPe=>m`z zfk7|5vRBO(T{ZrgT+CbqSZ6C z5G4S{ak{XNNxH1#u-X$n?~3IL%l>EV+x8?`(zkx*9`iYSetbes9ty{OZuh&LQlL)4 z^JlJpk##5hOIhOwZVg6OQApriXL+oGHQBA;W5|+%(kr54BEc_y?vuje@!Kjq>W#~D zw%T1WlTFKc2OEt} z$G^m7nTdgBj(J)X0>>50gFpV9XmtHuwwiWq>ZslP#C6ysG{(Zw;kSRrA>Wd2DcF)U zq;5$u$toZ#GsE1a+Bf^6>4e7r8x;1Fh>zhSPOH~Gat3oJZk(uF*c+R@aAa(j=o|PA z`rE1joBcM($*@YaF;yY8t?FXzBo^AzAa_)PXzM)*-ZizZi2LEa8V-#+x^q--oZXHc z`)`JWH&oE0=Re=ZJX_1x`mM%CE5_a>!grP-+I;`9rJP@?FK75PkSP>;0PxaFi3ghh z3zR@>zc&sewM6$YBV3KCvB#MND=o3_>Zbsi-?ew@2Eg-mfIf+r<+LYn=^3^ZC2!dV ztWLt}T}ipxmz3F|faBB%EVH?!Tz3?9c`57+V3kRFl06A4Yq`5!Ptw-`2iy z6UiSZ!+`_ms)?X5CfdU=&&#aRNz!B&>&tYtJZB8cY z<*J{atH!xg+}Un#Qs-W_UvtylQ}#UDs`jdS{Qe8g*?_-#d^wN zm*;c_YiNS{z}{>Raj#-zU$x`h4BgFa)DwU~%FF|Ldtnl==u%zn76Ix^av$nB)OEwt zDszIHV+*dz{nYHT_qZ}M+5E^=m^MAtH5$q-PQ$*t4>&QOY)zVgS9fEio0GaE()nyt zl0!TpsZ*QmMecpONndI<>Dat(-`C60`>AFVF#Y?OyYFE2-H)CQG>!VNz@STwGJmjt z(AT>^*n3PPW_`XJr$?B@*j?`?SGlL~cfMJr{%HSbZ@|9Y=-QJNpvMyXl&jGTZ0u^1 z_GE#r0p(JGc{|_UtPjENddzOb2sb7VU^FJ^x6~>-Lr*ANsaKn2Zkl<;ZZwaodQJImWnF1KQ7cgsv`K3G4Y|S2OTh!8|1gp3Q z=(kLg$sP&VTaDjNX>%@V$kt|O1Hbf4rmMJWl!^=0YJ0WV-6Vzdq?&((PZOQxgRXg5(tQYESdSP-kpzdH`#<#GlQ+v2u zq^Bgk>`t{aS!2&}rDkX09Fy8=y%qShL@xjZQ?D~>tI8+SbUo&*4$!v*kc7U`<7|Vf z1-6f~b-LCzBt7*golBb1aw~HE(QgA9`OBN?3HGVKF?ijeyCs8e@Rx`)%sM& zyJiEE1Hw{2V(DUcf<8s3rLq7 z={~d>VE=r9aPLsF6*L zewv#Mh&Ihm1Abfz+`q|gN=B&$q;JIf8lF6?eqs*P*Xu^}U8jIchpX=Zm(Kt$Szw-Z z-^H5yt~t|fG%vZI>kZBV2gu*q?vJ3Gm*`g00_r1m7r0jQ1J~OwG>gqx)ze&n|7$@L zykP&V7l2~Rf&#q2QCGR3n@zJBrB`QHCs*jz79km^9@MYfXH;ZH+0}&y?L~UNu1Nan zME?;es-hV;}YP(x6B?j!klI{+B@_{K-8Yt8GGzycCczo z=Ig8NtI14tHJ%nG?V|z|8 zy4#_)J!wixZ9}$PrGWnXlAOw^w5nYV0RCNPR^rRAwJXg!U|?%DxyM~8*3ph+9r(6A zcBL*?TkS+!uF3($dLoaQtVzGAC+fcLEw?90+<)Nj9e_Unft7HFy~FLn%0Aru-t}}> z*eg^&^QO51Q1<=g3c%Yd>~g!wZ3hkhj=9z4vEP9QbP0Et?&Icx&IV+{PV3>eCM|X% zc!xUIVt3d+dJW*+YnZJI`Bxw8mV##GWU{gRE^0^fbJjZS?(qMbGJ|*;oi^(I^HHe*=@6L*lp?va7G`4kKAL&Cm-7p z$sxexM_Ra#$>r|F<*C!-EMs_IKMNKey$&|;Bxz{`geCQ zu)1}r= zc*<5J&20_3-Rx&tOoLnF+FiS8GgW3gDBMS}g14J#7^^z@6n5~Zl?>60@r(5mbnsAQ3PPQL*Td9z)l7Xgy@ z(r4*=^wHqrKC<^aZSHpOo15Lw-QDJH?8A@D9{`&+y34>%jJ0d*TCDD7y~H-F%j{TP zQK-`3#dMYZSM$HhZdc8^3^?)u+YFlX5Z#RUIIg~IqnZb5?H$l(wb;`K=z3KSD5~@b zJqG*z0KFMlzmOelKCnN~H`y2P_XAr4_Dy26$tk`H?vT z^bP6gh3058BI#)t>KfC8b=BxnQwN@6k!#o80S~%kPdB+r)1k}seSn!S>6i3l7Abcs zIE%MHK{qCE*;936cAMGe9&&dXr^h>nfvyks&NlN9_T^I0RZaHWrU;&L44@L$pY3N3 zFvpk@T?-0!j4cQK->f(4vg9%F0nK`;eo8O3^FS3HVwdXUKVs z6wu*ss`Bh&{JmH2O75~#?H(QBt9t+@t+U75b>K~>s)4539PeUPRFPT+3bxtiKygjr zZ6N&3f$m;tW3@`1r5jXxvMO1id+2(57O4Fm*s)uZN>!^-FfBK>+j|r@w6W+QsHzbFdxlUR39ROUv86dNKIB zygkkxY#-B)={#s(%#NLD?$iBH^I*_dON_NIVYamXsfpX_vRexavl9v(*`{nhn=3SA zJAj|-vb&LA%x=L*jt!#+a1YYEUkN0XH&*YMaUClewnO%*DRxusN*0@xYvO zO_NEnE4V&aVXlXPvwRzS>mkhjtN7X_*jodT^E3CVSz$T~O-W6X!*6d=tALlA3cLx{ z04O;(S*4~XwS^{(MSFHxVRv>R#-k$}w?=LGwp>+dfo0z|6J0Ucr~x^XqCLiK1h-i% zl)EPIs^^(+o9~!zpgnHY-vMuYqS>X7cfZ6=nQOWw$Gi9Rt@Z`IP`#r!>&p*dhwfjJ&wWCg{drntcO4sV`DDzi+f;-lgsFEbL`@6sD zV_kpVFU0p?-dx^lGuW&EotOb$st4sT%?$?E+|5)Xe~>%MZAsp=BY;E4+CkXsgUo!Z z-6e>(sP0LZ{J%^7-zER=lK*$f|GVV>UGo1gp8UT{|Eo*?>mT*MMh+h}Y*d&2*B46v z>+`z+{NL+;RsPfazauKT^uPY6G{8i+n|E#!gq8y0V6!<1eua#b7`#~R|?yCs%(9a1$m;7eDvnRe|fEAn0 z6ADP38G+{HDdhM(7VEj&|WYk3xRViTz~y6d#G-c5JvGgtFZJEVEKx z;{1KN+_5f7Co^rMn0HsM6d%RW`N+H31s_W&!Mvz-Zhw@eH=fDI*%b7V#MC= z?N)qmd==j^1n(S9za>`2{wnM17wE~ z6Xk!6{%D_brxP2ph`k?VK0k~y`V)K`?(=gvGWzV{9iJXdqu;ymO&8iI zk8#L+E%@g;&B+~7tgGVJkxzTIr&%B8&O=#$wCRuE(LeY-`5~U~G*K<>{r0E7YE`EaY zF{nQV@nJ5i<-MJ|#g==tIq_}s!&u*mZ=Xhlk5RWf!WIcJZ6@>X%2?F@gZ1O<Brb@15|yw9Vd;NV+ooMt(Qz^s!>&xD4yQ(NfkM<@QKAPi`6C zo8h?O9Yw5j=EVog-RyWV%bbUsdFzYy(%7kS4i z>?iJ1#)Q4R|9gz=Tly{{oFM$*Juwd__>Xt#dW8LrxzBtJ=_b~39_BvZH>GwCi8S`?V^<~j9$e+(On@HX$?O~3<5{wVVEq5Kp=j-yE?QZ~a`aEXfUwhu z52p(;FLwlZ_8PwT((p`Q5(s(T+r^wQ&Rr_&$omSwI7Np#nU8stdLz(Z7ek)DWUcrd z&4+urHu!+zJ*R`M5Aj~>@6@N5_sn>F)825GZZXE|Zj2-ELSg-S|Mf?Q`*i!P_`{tj z_m?8z0Uz^@b`kS86VDsM-1iH2zqtnd9dRf340+f3%+TLMD$0Bd?>-anxHA*Hu&txRO3@5##sM@9j+(Z?2b%B(D~0IJNlg ztI+oMM&j48_pWrFhREED`qvOAA*R2obHY9B59E$$+GM2eT>|e(2l#uK(@{Pf`;

    dr(lQss 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 PZWVHG1{d!wkly=WK8N;2 literal 0 HcmV?d00001 diff --git a/docs/bench-evidence/rocm-quant-gather/primary-synthetic-v1.json b/docs/bench-evidence/rocm-quant-gather/primary-synthetic-v1.json new file mode 100644 index 000000000..b0ffb3c6e --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/primary-synthetic-v1.json @@ -0,0 +1,378 @@ +{ + "version": 1, + "row": "BACKEND-ROCM-QUANT-GATHER", + "argv": [ + "docker", + "run", + "--rm", + "--device=/dev/kfd", + "--device=/dev/dri", + "--pull=never", + "--network=none", + "--ipc=private", + "--shm-size=2g", + "--user", + "1000:1000", + "--group-add", + "44", + "--group-add", + "992", + "--entrypoint", + "/home/vikash/oracle/gfx1100-active-2773/runtime/bin/python", + "-v", + "/home/vikash/oracle/gfx1100-active-2773:/home/vikash/oracle/gfx1100-active-2773:ro", + "-v", + "/home/vikash/.cache/rdna3-gather-impl:/home/vikash/.cache/rdna3-gather-impl", + "-e", + "PYTHONDONTWRITEBYTECODE=1", + "-e", + "PYTHONPATH=/home/vikash/.cache/rdna3-gather-impl/plugin-artifact:/home/vikash/.cache/rdna3-gather-impl/llama-stock-source/gguf-py", + "-e", + "HIP_VISIBLE_DEVICES=0", + "-e", + "ROCR_VISIBLE_DEVICES=0", + "-e", + "USER=vikash", + "-e", + "LOGNAME=vikash", + "-e", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "-e", + "XDG_CACHE_HOME=/home/vikash/.cache/rdna3-gather-impl/plugin-cache", + "-v", + "/home/vikash/vllm.cpp-rdna3-gather-impl:/home/vikash/vllm.cpp-rdna3-gather-impl:ro", + "-e", + "PYTHONUNBUFFERED=1", + "sha256:80aab4c182a1f3eeebe286173977e57fcaf10a049b41f475655b35d285de31dc", + "/home/vikash/vllm.cpp-rdna3-gather-impl/tools/rocm_quant_gather/primary.py", + "capture", + "/home/vikash/.cache/rdna3-gather-impl/corpus/manifest.json", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1" + ], + "authority": "Operator executes under global GPU mutex; helper ran CPU-only imports with no GPU devices exposed", + "expected": "Capture 16 primary codecs, widths256/1024, f32/bf16:64 outputs. Preserve upstream embedding IDs and atol0.01/rtol0.04. Q8_K/MXFP4/IQ1_XXXS remain secondary.", + "gate_limit": "Synthetic operation evidence only. Primary bounded-model refusal and missing original32fixtures remain independently PENDING.", + "log": "/home/vikash/.cache/rdna3-gather-impl/evidence/primary-synthetic-v1.log", + "files": { + "/home/vikash/vllm.cpp-rdna3-gather-impl/tools/rocm_quant_gather/primary.py": { + "bytes": 7227, + "sha256": "1ddd29da328db6817b5b15119c228cad55b1f2d4e5acc143c80d70966a5c2d75" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/manifest.json": { + "bytes": 6329, + "sha256": "78bc808e19b40ea745f5e767b72618dbd8087bb685333345826257dd4371ccfd" + }, + "/home/vikash/.cache/rdna3-gather-impl/plugin-artifact/vllm_gguf_plugin/_C_gguf.abi3.so": { + "bytes": 5175208, + "sha256": "592af79c210496e96eaa7bd409ae0a67e7de8c334aa9f782082c7639ba300138" + }, + "/home/vikash/.cache/rdna3-gather-impl/evidence/plugin-artifact-sha256.json": { + "bytes": 16561, + "sha256": "b4def029f9693f89654fa2c60433c9a82dd9924909bced7b772ec609e648f5bf" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_0-1024.packed": { + "bytes": 73728, + "sha256": "4e50d50e97e08c448cfff4fbed121ef24d657cfd30c2e09f66e70c647ce545b1" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XS-256.packed": { + "bytes": 9472, + "sha256": "3281c7397dde054ea6c9c8a661cab43dbd0c982eb23b9a31523a616565c827e7" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_S-1024.packed": { + "bytes": 56320, + "sha256": "a94d30560f904618cead2f0618aea6455d5183eb3ed443ca5c12e48fe5b31b34" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_XXS-256.packed": { + "bytes": 12544, + "sha256": "d0f775f8e88d87ae542de6d16122a7a1cea09ebba91203f6513b74727082b6db" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_0-1024.packed": { + "bytes": 139264, + "sha256": "c4435564bf5fd2dc23e0c78107f28ebd033ec741c417d41fa9dcbd89dd2909ba" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_XXS-1024.packed": { + "bytes": 50176, + "sha256": "2d3a0d835fe7a47d802b59e8e412e4084de78faa2aaca59d1ce565fad11ac34a" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XS-1024.packed": { + "bytes": 37888, + "sha256": "8fbc716e220d386b0c27f1cca003384091cd0e522c1442656677af4ac780de5f" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q3_K-1024.packed": { + "bytes": 56320, + "sha256": "6118b4b2f10678fb09a2cb3324d69443ff3b33805f403b79ed3432d5bc1b2732" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_0-256.packed": { + "bytes": 18432, + "sha256": "cd292582c61c4b4b89606c85a80a6bb6ed8af98503a4d2f3737e02ae4e711d19" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XXS-1024.packed": { + "bytes": 33792, + "sha256": "2fbe6e6ffcbc32fda24c5d63d4a4b678283e2bd571f491210097a27b88cc1fd4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q6_K-1024.packed": { + "bytes": 107520, + "sha256": "2487007668582b61b3c59fdbaf0e92c2f5c74a61781daba95c13704983643ab1" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_XXXS-256.packed": { + "bytes": 4864, + "sha256": "af0b5e336987746fd49cd33c790b99eb1479c26f64b6679fa6c685e5934ba0c4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q3_K-256.packed": { + "bytes": 14080, + "sha256": "e4c3a11c1bbff806ae2729033910b7db606452d1b9aa499aa2ced46740ad85d4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_S-256.packed": { + "bytes": 14080, + "sha256": "d4eebe1369e21b0efd6ec5c89f54c785849c02edde957ebd302dad376f63c14c" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/MXFP4-256.packed": { + "bytes": 17408, + "sha256": "baa828a753cc6f496f356271dad644976cd57d1218517e3f641fe56b7ec8db4a" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_K-1024.packed": { + "bytes": 73728, + "sha256": "d15d1bb953010f1ecdac424a54c365308e3b058a1b818bafb89cfc9b9b1678cc" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_K-256.packed": { + "bytes": 37376, + "sha256": "bcf6f6691a787fe3f2a9bcc3d7923eeb4953862c30f904a6b10fc07410f8d657" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_K-256.packed": { + "bytes": 18432, + "sha256": "b0c107c4b353e2a169247e0406c1eb015d7a6d97edd5906f710868b8c2cecce1" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_XS-256.packed": { + "bytes": 17408, + "sha256": "35b2a41e738a6cb0a86deb4fd366f71ae2dc2a6fad7169f5a9afb53f523e919c" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q2_K-1024.packed": { + "bytes": 43008, + "sha256": "58cb93e09423c7151fac47084de7e38bff98f51e5f304de243b41a17c47ac4af" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_XS-1024.packed": { + "bytes": 69632, + "sha256": "189f75d03197100afafd3fe92183e47a2d73665d64f89b36d8b10daa05adf2c4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_S-1024.packed": { + "bytes": 25600, + "sha256": "6bf00a4b02da43e5505823b12d9e368aa1ded7f87427eea02ec03ebc68288c33" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_K-1024.packed": { + "bytes": 90112, + "sha256": "6dd54fbc62a9818334e50347fe185247156ecc833a5655ce1920651a4dc537b5" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_K-1024.packed": { + "bytes": 149504, + "sha256": "78e39e7ef7317d842a6fd965b356ceb1959a5ce03da824fbc699689ea2ef4877" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_0-256.packed": { + "bytes": 34816, + "sha256": "8be599e194405f9b5429e578a03a5717e4d78f53ab4c9c11a52659495ce805ee" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_XXXS-1024.packed": { + "bytes": 19456, + "sha256": "ae8e061519977e2ba7a77ae9d30e21193b1a009b5ed38739974e945de09b94c6" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_S-256.packed": { + "bytes": 10496, + "sha256": "6eb1966662d9e424fefc5c3625282e7f33fdfab3af9cb4c0cbac6bdc593711ea" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_NL-1024.packed": { + "bytes": 73728, + "sha256": "4e50d50e97e08c448cfff4fbed121ef24d657cfd30c2e09f66e70c647ce545b1" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_0-256.packed": { + "bytes": 22528, + "sha256": "b3531b1abd263bc4c6a3174b22fa1fd54a4b89b66e737f2eb3ba36be771d7528" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_K-256.packed": { + "bytes": 22528, + "sha256": "5e63d961f36486c9636dd2657e9069bd83ece65e466c56c657265fbd97353b07" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XXS-256.packed": { + "bytes": 8448, + "sha256": "4a3c10afb47315763ce507edcb5814e06d1be93a21b178cf73183302a3f1ceb9" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_S-1024.packed": { + "bytes": 41984, + "sha256": "2cc5c79aef24da7bb363c72b7ac91f05c38b87fdc96627253203926f4465d73e" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q6_K-256.packed": { + "bytes": 26880, + "sha256": "134bba0f8076d43d31fcbbaeb37c3d8191b0d383e6595f787d3387e2e016738a" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_NL-256.packed": { + "bytes": 18432, + "sha256": "cd292582c61c4b4b89606c85a80a6bb6ed8af98503a4d2f3737e02ae4e711d19" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_0-1024.packed": { + "bytes": 90112, + "sha256": "b1d241ee00677d6d55a5e774916608aa4479e6c549d8ed1e4803c0938cd6a855" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_S-256.packed": { + "bytes": 6400, + "sha256": "754f0d0b9e7d3656a1f669cf756779352cccb246bf6aa0b25e7f362180cf0882" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/MXFP4-1024.packed": { + "bytes": 69632, + "sha256": "929ef7d789f210f60cede40156f689734aaf36519cd1f43a82d44d17ae0adfb4" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q2_K-256.packed": { + "bytes": 10752, + "sha256": "655f77ebb32d974da7907da4a217c45bbbcd0b127df73a731f85afe427bb7dcc" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/MXFP4-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_S-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_0-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q2_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XXS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_S-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q3_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_XS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_0-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_S-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_S-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_XXS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_S-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q6_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q6_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_S-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q2_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q3_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ3_XXS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_0-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XXS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_0-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_0-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ2_XS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_NL-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_NL-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q5_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_0-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q8_K-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_XXXS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/MXFP4-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ1_XXXS-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/IQ4_XS-256.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + }, + "/home/vikash/.cache/rdna3-gather-impl/corpus/Q4_K-1024.ids": { + "bytes": 16, + "sha256": "519c1b2fc6da05a94eab0732b8b998418d87e1a465ca3560bd9e75b87c20aa15" + } + } +} diff --git a/docs/bench-evidence/rocm-quant-gather/primary-synthetic-v1.operator-receipt.json b/docs/bench-evidence/rocm-quant-gather/primary-synthetic-v1.operator-receipt.json new file mode 100644 index 000000000..df077baf9 --- /dev/null +++ b/docs/bench-evidence/rocm-quant-gather/primary-synthetic-v1.operator-receipt.json @@ -0,0 +1,64 @@ +{ + "argv": [ + "flock", + "-n", + "-F", + "/home/vikash/gpu.lock", + "docker", + "run", + "--name", + "rdna3-gather-primary-synthetic-v1", + "--rm", + "--device=/dev/kfd", + "--device=/dev/dri", + "--pull=never", + "--network=none", + "--ipc=private", + "--shm-size=2g", + "--user", + "1000:1000", + "--group-add", + "44", + "--group-add", + "992", + "--entrypoint", + "/home/vikash/oracle/gfx1100-active-2773/runtime/bin/python", + "-v", + "/home/vikash/oracle/gfx1100-active-2773:/home/vikash/oracle/gfx1100-active-2773:ro", + "-v", + "/home/vikash/.cache/rdna3-gather-impl:/home/vikash/.cache/rdna3-gather-impl", + "-e", + "PYTHONDONTWRITEBYTECODE=1", + "-e", + "PYTHONPATH=/home/vikash/.cache/rdna3-gather-impl/plugin-artifact:/home/vikash/.cache/rdna3-gather-impl/llama-stock-source/gguf-py", + "-e", + "HIP_VISIBLE_DEVICES=0", + "-e", + "ROCR_VISIBLE_DEVICES=0", + "-e", + "USER=vikash", + "-e", + "LOGNAME=vikash", + "-e", + "TMPDIR=/home/vikash/.cache/rdna3-gather-impl/tmp", + "-e", + "XDG_CACHE_HOME=/home/vikash/.cache/rdna3-gather-impl/plugin-cache", + "-v", + "/home/vikash/vllm.cpp-rdna3-gather-impl:/home/vikash/vllm.cpp-rdna3-gather-impl:ro", + "-e", + "PYTHONUNBUFFERED=1", + "sha256:80aab4c182a1f3eeebe286173977e57fcaf10a049b41f475655b35d285de31dc", + "/home/vikash/vllm.cpp-rdna3-gather-impl/tools/rocm_quant_gather/primary.py", + "capture", + "/home/vikash/.cache/rdna3-gather-impl/corpus/manifest.json", + "/home/vikash/.cache/rdna3-gather-impl/primary-synthetic-v1" + ], + "exit_code": 0, + "elapsed_seconds": 12.55049991607666, + "timeout": false, + "manifest_sha256": "6bc9501cf0abe9a8de36bcc652b636ff5a26df3dbb650ad38dcc0ab098fee9f8", + "log_sha256": "90b105e4334e7549cf97fc4943ff1db0f873fa1424000b0e2e108597a53c058d", + "all_inputs_and_138_plugin_files_verified_before_after": true, + "report_sha256": "867aaf215887b2c18f46b20b9211592550274099f721b4fff73cefb2f171dd38", + "output_count": 64 +} diff --git a/docs/bench-evidence/rocm-quant-gather/public-model-trace-captures.tar.gz b/docs/bench-evidence/rocm-quant-gather/public-model-trace-captures.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5454aa8fd1ba49bff3c7c794388777222ef053c8 GIT binary patch literal 3245815 zcmXtg2{@GB`+h`O!x+1)V;?kN zH(3W``Jeam{r#`&b6uwQo%g)wJm-Gy=YH^UM$<};)E2FLL*axw{ zBGVYYBfRK)>L3LOwraCH@y$$s*w8{ei1bg5JJe`(nGz6|o2Yi#S-= zt~^@%vTQchNEvA9b)3m*IU3dI9-R+pY2H!(X-C}qZAIJ**j-+hZwWrESZvvB`Rgd7 zvAgx^LqYQ%(Zltpdh>?72)VbP6h1!~ad>=GDL)l3w(h%nAqhp8hBhlt~~!d!ei|1`}|8k_fxnIQzFa`k2h8| zT8=j6BMt@+BMvFYnB)C_g6hY!UtYBw&$g$iAFvc0udH@gMyxLdWV8e);0g}*6E7a- zkiyotUy;JVsxlABl^T?nvd6nS!)D=>9OA+9k-X#K_Od+j;4krb?Sn?>;VY}-y={5E z-}*jNP4&kcgzycw z$Prx4i8#*D2z^7O?2n@kX5`h6Uq*DL5SxycW(p!)j#@PimwuQzv`~KKR5~0!zes8h zrR;flADH>5Q)V{81_pf8~{*?UD z-Vd_+(ZR5M^U=~5(s2&yc#YT?8FAdwbWwfx3)vxJeZQsouyedJ{IDVDKvpC8$gQjS zcz^gq%kK8YtN#i#BFKXpA>_Rg$Hw5NQ$BW-r~n_0pks2t&+zr7I3M-H2 zht5VzTwvQ8W}baLzxC{x(w<@(uDEdgS5RT&_-rC=Z0&JR!NI@E@ZF1o2fHK3hhIDd z4`$~{^&KJPokV#6Z>P+Zg7B(=;|ClR^l_D7%icy`W@^Y@>(Tb{uQ+1f;k$_4D2gLl za_K14>w(f>yq|jZQCfl0HgRW3!}{o}o#3AS^0Sp=`{72JR(%gkKI!1lKLH|t>mv$} z+mE8;+Z`k*KI>`Zh#Ft_0cUl&R$b+tDB4&6l z3Fc{BI;p(IvQt^`@PcV`$ESQeH@C_LG4Rxpo!Rl=&WPhd(DCv7p$6%AaPpX>@oFz( z^6+?&2=;87%g3?Fx(9Oam}rqOb|?I9Sk{l$H4{PR(c z$&ZUFkv`#*_m3Mcwgmc+_fyn@9Gmtr5~=xJW-Xq50Fk{REyrtd5oEGP@OIPjZoA;& zVZ`pZV9Wk1@aa{{;iB1oN>jb?&df!P5Xzhtfb;RTRm9=WyAgYI=$7}1qqTw$gzP7M z0m)0#l2hmXfB8ut>pUW!Ns;MGgqWz$yLR@P$dahP3J2`DUSx!i3BBm+E%9C|N)2 z>W8WdLR?IvnM5De%<~uidtcP&UAdX-B8o_8f3HE_Q>C+6@LyKl$Zco!9livwRyiv? z!>a#io?poC9fhBkc`*HladZua|1ULLbIPxfFhM@13qQjfshj1u>|79ck;}=gE|2I_ zn`aI^2L{@yAJL}z`OGfVg$z`)Z7}^_ho>k|^uO+`Y|^SY?_SgJ@NDZh?B99W*vEMAb1G~!~y`{}RH>k|Ify{li@GE$L>T-$$A@y1CyMI}ttO|FX zl)C~4(&*~A?$tyI_`$W_C$ghvgW*fV6plw z%4Q>DNOml8qx;uRR{JTf%S+FUtMq>97zlP;!QG1-=)0Nx(qRZ1Q^r$`v^^Wt+~)hT zE$`Asow|Wf#M6%F+D%$scF&V=O!{Iow8A?#7|P-zfq@`8Y2?;-8Pj^qs3LTUR{WFs-PAgM4aL3;8+NqT)VD_ zYy}_*W7Ag`)PFc&bEApcQXm+TZ?q)jTI`hZ zWu7;>TeTL8{ZfV17!-r+q3gnQ>8Ba)=jU{#?KH|seGd|6el0TvO{BQq^_qIhq_XBh zNa}Ei<1#fNAqy2>@;;KLWJ>AvS+c5>(64xmvRCDsf4yj9iGtUv)G%|(T9Hui6n;^p zzi@Gkx^9pvm>9P;)p9L~hNi{a>ET-+qhEdmEo0GwEUk5R4$|vDqPP&cvw>~ONp#Y`Z;nRUpqp-HA^Fn`SVY70fa-^H^wx_rWxAeWkRxISNeGd*QCm zw_hb@!`n)S=y!hTid|MGJ(U>5aANO>!q_hfs4V-!lU+?8a#z>Nkur}x>CpG$n(haM zTpg<7Ks?GCK)i^T>zH`FcO#^2!PTlrSbX?p(QOm%yO zmx^yA3mB+VE)U<}&-LAY)FsniO9X>N)48PE$8w~VKsYQ}z5Cvr27Jhu7rA1&UD9;p zu@LFiyLm+6E|_HPBd4!zrVTe*5n@C1@5g?W&D(z%(bQC6OV1D39xzIcss2@Q=0}_T zYsoS%QTMO@lSzBIvqIwD^Pja)_Jz9?Rv0E!MsGTvXO><5;dC!;(>swU?ANx82HSh0 z7->$~mAd5%VXO&GUvG^11+a?{CP@7G>4nqF=KhoBfu7u1>-HZR4Cu}$%!a3vb4yq^ zS-s}>=Mkjsi6*C?G=vb#$VgY}zr}kw%XFa%T-aFAUI7L|a#jvzh0fp%)?FC$JRIQf zuZ_;PS4Vy@{eA^Rwd|!^{->~A;slFb8dR7V&m$r9fL1>u&mXgu>-undUd^AL8TZa+ zM5|MuFmqM7D+WJ!R;QSCMyr#UEXjRKG8BhzNlx*++v#64o%r&J7-qYVZTJ+l0foB` z4(AvHGC1S!vAG*7Y&mQzgCrK^edaYudXZmHaf$W(O@u95TZoAG8wsxl&7=^J8J|B6 zz%PaSbSP$5%;0prqNYdGd{~%Ja8Xo;sv?07{gPO|JGCN$xr4s(t9+NqQ06H^fsp%Q zK3YW2@*pg8z1f+#+Ohf0^fY!&8-X_&dK!<(DOBUgDSXH3$CW0jg!T}1PcsY7LJX0u|nS-RaDG>yBE8i{Lb~O^v<&joT3WW(9Y{%l`WTYLKZ2z!ZhF&gxVhNv! z#aCipG{dc8xuu)SKdJ;gi7>@wC4TLD(`lf&-hDB7_I-!C1XX82)@=GE+=Z!= zsGBaqzN#(UF3Qe#EIhL50ZWp#m_M{m^i}0mIZrV&&WrD{jv)HIyls6{Z$L4UiYJ$#ED*gE)=)5?_*j z><3FdI6Omz$wphgA25@bRN@iw#R=Q)OTv*OBLc_q#xXbCJiS&eNp znfY(B<82fbKL~@G6JkO4VU`wT^p0v;mS$26KBev2tL5tu_BPGwp34+7azs?toY0o? zw=h=cl-`n1>D|e0}0453y>12%F^uU(TBE6~?O- z&$xT_`aiJ_gmBFH!OTO)#0#`jJ}|z~T#$adtzWa97snb~)(}GK z7lN@P3_R<-`iqOU3t*|YJ5)^(40)QvlZ};GpfdSWn*?k&-$W3&sbQy$`A%bQLnXjR zPx$r=ut^jI3SDgz4$PbHy)L!G_@DY9rRFNEo+(MAZHtEzgf6@(N|&yP`~c%3gN zyGp?jij&)e$#25F=~{VNOai=REe|$cKnmxPWBz|@sl#IFDlh%_v5Scp^B7{KCy9Cl z{i?jEvW70>*Gnpn(q%Gi>G&D3-nM^CZ%|TXkCB zVSAS`1c5dBoZ{qU7?3g!Mt{|srfoNg#Y5Z=+?<3KDq z{t6K+qt8h;kDRls36^4gtn<(A9jYlFL3_CfIUT3<@dIpA87LP|mzMSnfEvMsC!Nie z7Yjh82+@@wm>Y9RH=i=Gx__Sx;h{{pw@FV2C4-bpq1KCIDhAc)waP~_@lV|hAu!}Q!I>ts=N{1Bw2ISt%(cb zG5-!n(O~``qCDhki)KimB1}zG-KbkVfS9OLs32OXenIVN%y|qm6+PCM^SvS$n94iJ z`dcz(j2w;$+MA#h0OlqbV4;!oMo{RfS9fUuViK@h7mPJw@j`TMDjmWxbRBEjbm;Gn7entBASmA4XW*`z-d%L(_j>LyciB zHGgRl@pVy5{AjW(hLmS}A07EoiZ|tTQO(@|ki*NES_B3~OUa2!0Xj7(P zxqD`3Vy=*jIw)~w9xyD6`s4l_Ye;(fF^8TZcs+^iU>okmyo%WX$SDY!4jG$J%Yd|x zD!U`|oU*>AMf_7mnC*-*ee;sZJ8gtAEkcs9Kxf*PwJm9}gxw5CsX_a$V%A5Z@p3D5 zeRQG(m=4#@#1Az$dggIRlz_eh{*@MAS?7tkDy+9s*DxQzhB=;wiah5VY%RQwk&hnF z?&=*gb5Hp7sxCsT$6hj#lh(xQn2HMUEaEyJPM0xc?Q{8$!hTxeB((r?Dh#m>bhz|X zGMohReP`m@-8F`*P>*r80M`9%I=%k0w8?Mw+qjp=4UEY{?t3a0y36ZLT{i&6X)oK5 z`CY)k#*RA0J#9mNAG$h_jdz|sj_hD%fA_DRNX2Nte{KY5Ts#zcfQtI-Qe`q!!~c3p z?+=Qwr^2y+^! zyAG!D2%5|EmZ8kPp>Lp!X}Bu{)4g|EE#Q?l{e6Wv`VKm^fMgpTh39P&F45_lBZ(>^df(9?VzQidEC!$V70$0Urxh)}OowXAF}uM|Q~s=Sua@z_z#HbjP#2>x z;q$2=oxh{wB8@lDgFINyJJvf-W`NK%F3=(1(;}zIc>;>JV@zQvsW&Tm40+%}QO#Sk z%#ajJ;d}+SI6-*;iIfV=&3a>DJv;9Y)!bnWp;~OqreEiRpo+oUal@!EJpnKOEX`6f zlo}tQJan4*Ed3w`WDt9T$Q#YU$;*CNjQ^U1)F6fdb<<6?$t%>24p98@@C z@GT?DbOxMQUXzhWVnXPCZCdi;9xRm~5}oY030i=}0b|~5?@j~rbv>Dxx|@4|p{KZ{ zrc$&dKw0x`l(`OMaEb}N!Xr%yJ`Q4aG~$Ki$BWYH7sYxM(R4E>2- zYM$n**Z!-9TcJ#yQ&ib&yy-h<$ReYgxikntzu)1P)~N0cV*Z_OA-*jZ25KbBOHN@$ zR0!4KA1XEaV+x*n344n9O>EoxLrA=Z(gStDs81l5WX=QZe9um6rxj*036QaoP|kF! zFI-$xFYH|Syoy_ByI4}kIPzK5K15C8SNu&y0z0JTtwvqVB?WTUz8S1H4f_IQ9!+86 z5zVyt?y`ohLe?E#h=IF`7x2%9K;4u?yK~75VyYJ9{Maz3Ye5AqK!1HA7B3fiJVgl< zdGQQnELTbiLX@hXH;~<)?~%|Or(t{f_gUAM^1F_6JJ|e&hsvb%sPQc=T7+5-(1Sm| zz9c;dk=Rb#t6)!;?*4lMHTLqy}ct>zy%H>TYl;pRWK`>&#fjn7y{6##vx+w1qtACVu;EB})G*`h1Mh!8HqBZMauHsa z{=fN_!F>CS?u=7OE76qrxcG~VG*Xl_6v@u>|J-(g<_EYnBL33?dE+#PV~ywJ zhzT`8$GGvwb7pZ!Y>s5b+?;dJ-p-|gvQ^~I16F9V9$&k*kh*l*K&e_>i@44Z3UoRp zoF*C}dlt&0QE`}G%nbdzb3X*F;4o;AIDR7iRY3VRv%BWV7GNcbqV(usB}LQe8N_s> z-|YIG5^8A+Uq}V2_Q!2kFD%rLKj0k5%#$@2^`G>f(QW?FPJKZO#6kS>oWPL`XsIz; z)l3g(={N5X|7Yr)sazm2zyAaA^SVN=(k?6&f#q~R-x6n`21Q6)cZ?MX5dX>hY#LRt z%^x7XkYNeA9W-zvC3piv`bUG{LxDY{5l$i<1k0d>Cv2}l9vZ>S^hqQQ%3EF`t8Kk} z_tV;xQnY5$L;N5b+y4d>MD;~HzK$An;JRG1TgaVo_X=(}wZjl}x_s6PaJ$l=a8DxhD@tVU7?F;gUf;E+a6 z-Usvs;@Gw)H@wev`kS;xZ+cgv+3eZj5rdU_Fd}uHv1Q|FlaZ!CK#$VuXOz|LQX9mj z)g_c)_%(s0MQGUTYSY7Jbvj4N7No6`K)=$Z+1--6xS8e3+_5DBYh6X$&AIJjdV_~@ zOluR!=Kj^-&RT@&TejgS1DX$V9n_r#1KS3^#0RQCmLPe1fwgl9ds%r=a;btAuVL>g zoG{&$WeqxC^|}!$D83C}4OD4_8?UTa_ecnT)Dr^9T#mSm4{5-%|1F|&66eHw_)Rx1 zET_rH^^zy&S<}B6S_Rjd}7=V$GWJqU^*cc(~ke4dvWfMth7C~KoZn**Af zyT%^el2hv?zr3uagrqu32piY;1~L2`q`Oc1E@XX@c!VbxFXE;C(f{-nP)|U_fpnn= zy55a3Ghe?TIVdUjf=<6PbJ#$d14yn<&puZEk>nSQ$J`YAn+tJ`iVlpSJ8C*4F1a!` zdwQ>Tj_o8W9rF^>XCL#nJnsVgH6u~`a$Ot?a3qI+rQ%r6n1}wBRUZ+$)WxkX+n5zY z|2C64X6DNJo!P(u;LbO5JVI2%K`kuw_{dgD=WH2z$56(e?>`%fGwr)2AjkD@&%Ed! za<8viJW9a!7a62tvJ$@DH#^A*_*YdA0Z=T0UhiGTREX03@$WE3UiD+F&`e;0>bv&&P1b)urFGY&Ekp0ENpqF#Q+JLO%06K3oq+|4&aGy+ z{(crO%F}(uoJaM{2f~@McSGOj&d(G#&fRP{98wcSfieu9{{5b@rhmUt=wIJE;6xR})5@ za7ZS#fFob^%iKF~sHNGYG$GSwVX1JZd|gnfY9K{y6N`8c2Te$nKNd%jEQ;!g^U?qF z@%OpC5<%52EdnKI6coGYl*I~R4pDUHe3@#x5~O5oJEMyHT0p)#-sSywfo|=T(L!BA zWqOgxXP@hwpo9V_TsIuK-F!>vte{z0z5PjV(CXG59U-aafGLTcfBRv{9EL z+!s7#N|XLGfN8XS8UtPe>o*_j>`Gxo}@kEgBz>*T0(L#y2)`keGsUar5!L6|8H zpHi3>{kvmdwS4y{Gl*DmGx)@d(Ccgx4l-YlVfi#B^zoTUwUZq=n^lqS&KKkUIIjVd z*f;+YgvG^rj$(uuwFmPmYrjf((O2*rgXz^u)&F$BFBo?C^Y(Ju`D70H&6ATn5LYIq z9z)7IhQrmThDI2KG~DO0IMkojjP5n*abpf7^??1I=@ltlCKTN}7|8PD0w_YUcv7-7 zm{#+9Ma$4{v2Id#GEKBQGf^0*Vwgw2v=`!NEIydEfcu~SwCpz~-WhKJXph~4twP>F^aw|xH=FulI{m;N5z;4Rfi|^FWl;|ENuaBO6MxX}bBOcEpy>?lKQ4gmU zkd~uIkSlMfnwP`BKhxAG36hjN>aE@G0EIsAaev=6F{n2ih#G!!_3pZz^SQZVEs+t6 zqz<<9_oH=ie0P4sM9Ja2X!&sM&3;XS4uBz1NdF#OD~{*7&WN&e?*$>vvxeSFQI!oEYHl_N;5 zg_V+$E^p585_!;t?4jr}HWR>+tYv}|XVl$Zg;Y)Z!8#g=xkb+2R2ZQ$i8NO_P}Zy0 z**XtzTn7MQd6_0Xzv;El5VE#5@)ihzvP$r_Th8*=w{fCS``OHkFZ$SB16ds2u!QH4 zvnSl22P2;1URB&3pUMhcyUllt-hkC_RVYfTSmuNu%SNvQe$lWaI_GVrFl`-U@YQNCM+M&Na2fcU^j zG_|q=BjR~vHUuBCAqGJJ2Jm3@R|!9ZvRAC^UL_$q&xN8PCXr3hxjXEN9<=YTz5BIZ zLKX5z2;3pg@bBO~BUumP5pV#WLEy#?TuM&#M8kooEA&WY!dtSa1>Dn+)`byq zPf%CZ^Jmjp?K*9NudIz{;WD-=nqGHU@d6wVgwgtgVkNq@lx~@m*c|~nOzvim9;A=e|;Eox^E^s8r^;94JP=y>1O@qF-VHs7yoI$ z{CZyf=}FKCJ^udDl$n;%Gkh{c@T-$;>s!{x+Y7jyjvP19@^r^wnMx=0uhUP`jMmFN zv3*WaoIx7TJLG9@p<`2bX`eWzKX%lI^-3PLoj)->Mf2K8ibf5C#C;1nLWUWHrrYC=WP%%n#7QfYU_94<4Uyb}8Zb6umvT@|R)p9DR zC8LePSnIfzdY>G79lSxq<C{qMbS z5*`w1|JiRXQqEJ|aiuD9XYlE4W*J+RrjbLG_?N8hTn1}#oWQrlI+3nIDfxlJKpJM- zKZnU<0gZ?k%x(;v-^2S@ZQ8E3;>HGpQpGNuj~z41um0Z8jr&=~?F9oNC7vqH%}8|Z zVn9#E>k`t7l;v+*n7$7&EQ+M9@kvzjcwZ($C{n9Lhp`)BtTid`F;9NpFT{a+WKTv# z155g|!T0!338nB?+?=o7OAOB^NTa+bmm_xbvR{enV#o8)`My__@0KQK4<3l-l58o!tR7l4xUrIJN4Xrvze4DxskNB zg0C}E7do#{>U!mGGPF1iPO0fp*%%gc-5y&GquDF9sKz^wI85ksIAv)U8HO%ApwPtY zzKuW!O=LcC9fgr3a2BQhjuMh!(O(}XA#IDpZciqjkDo(!4p4`X*YdNhEz;7fgGdgt zaY%6+nd%Vvq-@=W_$#hPw}}nQ^wrU>UFH<>PZvf0-XySYsV-jw_asekLaP|q1o>bs zSgn`~deth`!SHQJr+D*9n0q0b;9Qj`|Lcmf7|*Hk-HiuoMbMQL`H?anTLM#5a%f%o zwN>@#s{khZBAl4}59Ob4BJE^0x8yWGX%z;ZF`dVyF>q4Xn#5W&a1Mp<3v-gCoLV0= zGmQulCUq^HEn0mZe8~}r(hcjYC8Olqz znR4<{SQ!o^<`smkF#uRgu;@c1nLC7v@fI=4{dJ!!Etm*7t;e^(fey?-8AEyT6h%G9 zvt05T%#7;|<;NOVm8PTPl)N=Nv(cZhg=McHZZJEhlVM@Xf0bOHX7h}nsIOwW9VJWK zhaM`fUXkTV6!yII7Rr`;C*ELOUWl%T3rS8HXMU))Zq+J$-XmlqQ&cIhQgsu#DcMCG z7RHQkC}~t{X2?h=)I0wkzC9Y<+&qpqeKhuBh;eIsZe>#DZSJ$4jG>W{LS2_?DKLDw z^IylN4Ht^z{hJhD2 zbPy_>s8&g}r{BI7b^b+{t(c*v)#}UoUA+1u$gIlBMC^^bYgQ*2IQ54{J1lI$z{EVK z)K25+u%U3DG^wt&(wEen)c2K2+9;=M1@(Buwb*)3*A^sVkt#hjAh$YmDfF&*M8ewz;>qx7BlRg^v@m1^4%PAOGZ97PD!E z(Jjq}4eyGveXssYBFbEMWq2{3l60yU&tHC6_?&^W)Vh)rNF}g`$9aD1aTH2T{>M?Q-|JUCPtJ;o^``I5wi0=Y8kPizj+jld*pW8k6{o;>v z(;a+&=sV?bh}M$<^Jpyi$-+M}4&f&rA5*^bmxs*h)WuVDX`ow|pyAVO51Y zQ3A)iYA19*;l@%fb%^vHB#h1XNBH=fgIn(mG%tt+gT#w5LkcIjo>vXcgx$Ps6K3qrWEQm{tcS=vNV$^657GBrJ|kx)5DwGQ-} zI?iB?ku)7&VaX}Cyt+6nGF>yd>+RJ)VJpjh@9w@zo0n`%2@4}Xm3fO0#%3`2RwUp0$JfV->O z;lJe80qL9x*Zdi)28Xs*>W5T?&@h2a90|{?1bA)%l<0GAhT9$S#xtpPKdf6n;etOxPbU{A~>J)XA21EZ|BrL>jO<;_P{d#JS`w0O5kaxiz^Tvy+vfu0oIRT4t@M1 zwnB*(8B=J}<4ere@IbRwP@bsp8n)pI?eo%GInJL73#(NUV3~-mw1C^bu(0BSk_(NjD0eQbtgM&pGFZ!tMGzR#QH?EEiwq}zuf9V`kSOapkujQy*#5FMu(4L; zdIXj}#t}TQc6z*L+P3IWYc&L0`u*!UIEX?Bg`L-~`a0(=jnjK#V!=}1!!N(sP{Ke3 zFRwRsuGtU{!uV>4;vp$Lnru5wp}klw>3-W~>~gyMN`E>-MogiqOOuHO;N1(N8L9o; zp2sV?S4X`b;yPI$EA%VlnWC)dE=sy(`NAQ)%MyQV5@gBNL z%ZHzb#@V0mk{Mg#3}eX996E=U(uKJDtuE!W>A6x+&BnX>ZjV>dY;!l!Rj-;NgWyQI z;03D4`%6|;NSe~;&mLq_Q}yYY=XAjE1|YbULfqE0?R41p=F>q$Bk(i)ZY+KJE^Tc= z)B%CO^bRCGPZ@l0e@AOI04APczDw(PcJI@m_jqC8m^KSrC}JRsSgQF6sQ&y%`j-`vARK^JxHN zxC5Wuo1CHrlvsY=NX76I^%%>YZF~^od1d8V~?T6a~Yd~$&j|HI?HojZz38dr(_Z`u9WE~)hn}$+M;{v8~ zZoqj?QT8_+o<_%7e9ssi$y|0aU28FNXR0X(8A@6$wUzbAjbUjxeJIVFmR>C?xoa=$6!PyNzuM+JWo3iT8fe9Z` zyWYd(flo~w5~S|yo`N7IrZ{WFHNluWrJ)# z;R-2@$JT4S6A(&I@m-e!km(ZV{F1~I$*bD`@stWAy$oH~d7zmWbP%*#2`6}gyc)P( z1;>?%8l8z4pf0GlH-E;{(5*yo{g+bc1z&QTy!wv@$%t-GDAj5OgjPvtH3VGi7*e=1 z^0PlnxLgq1`vznRIl5?PL|GrGmu$F8*;gYG$wjxPdh&&bbBVYLBMGWLe&_}Y9{#la za4Lb_$e;^!YPv2MT~qbhl_~tQKl#&QkbFd4d6LJ709aHzy+1caTk3R=rj*y6s7Fl& zxK`fxyF-Qf9L*|8t;%BT%PSz#w-FhZ{iD>Yq<6iP`4XTmJpbIN^Oioq@g;ccq1=mx z7!McJ^T02&9>$E3g-8u0u{MC6*DIP(mA+Nd>zOI z19|&5GQJxEbcVr;y!t2?zM6=CqPt#~%A9QI46hNJlCJ>Ctru=Xc)JskTjUe(*!019gq9L*$pu?`Quyep0+rRU0I!Wffk(Fc;g|-X?NY z8*Jgi!eqI=8{N5T$pzS^p+{cd!rsZzac3a+|EMV(8IN?QUgg`_F6DUfZT<>)ZJtNJ zA0%L_*KHhQu^i9dm-J(hXFr2Zxb&sG7nD)*E}Se-E4usCBKaDK2I#bk0|$IYN37EG zZ;U7=I540Wl_QRU+yR&RPFG8AWH~z$4>L~N>|757L~~0b=$I*nyzVxxc9URj_a_YQ zeBU+Q8Dq_aZi*KZ1LBOFEH$5B?Ev3tJsTooZ~m)qaB^Be_tZ!vdCZvT*ms;e{-bF3yM7i;G6MprXT39Sv%k z=EWtqDLrdiBN0zi?AL|T6I+E2f4zlapjjq18LkN#Nt^~k+1w*T?lF*LVU8uA9a2Ft z2{Zd<#1!M8bW7vRqL@~ivt)^{MeNNFkgDZT%s_TZzrRAcFS!{IR0L2OP^M1`5V`8g z4JpH{4iOt5aC}TvyB2v7%b=~j;8{eTCqQ>|$l^d2^n&an=U#ICWg-I}CX$>}=L{@^ z=pI`J30{^0_cA$b`o&zRR?P$zGa7zCn!jNIWX5YO=wx%SNV_yy=Gp>wnbN1WY`y&-K}-$)2qhjOu~`{mJzCe8zvuQoudUa^}&P{0*|zO?Rf+2$o1)ZA>G}7%?h; z#~**)(hwSWv9-S?#N;|i_-zx=)&j>MpmIsGWy0(gq-fbkGMnN=+CRA*hNPgsDe%Ya6oC@!XHugiHpN0yTI~K|25P!j*+)K8Xg@%-_D78}Uk7ck-4hvH=PtJ7>SmU`}%z;^%x!Gd}YF=O@ z@xoSxCeSJo%B76VP4{5HpxhVE$c6gY#h2VR57;$4fT*JcDR6qu18{>mg%=u5k)+K* z9n)ya6-s<#4)iB8zWPBfG$%gC$J^0TB0QPtGrDQ~S79zRhB=Yr49|hcCi~)$H(>zr zoYmhm0tIU$1}{Vqom?0clC&L(-dhUT1gI49IeZCb&SQeACgV2N=)4ObI;blH>gBvU z+kVxnTLA$lo?P0;2z-?3xG*w(69ggmlCXDI88UQ+M6T`gGh}F)2VVpK&j!itd$@~; z(aJNZsZDjr>ehO&Q>RkwOGv*33H%gZRJ~@-!J}SU`?lpBB)#j zLJ9OhL%G%nWzam8RVHw}mQMy0fRS%DOp`6D^w}?KvL@M!{bvgYvt5NWEp4}%0hrC5 zMC;pexH%zD1tTd1CiO8t4aD%@YgIy?OiIR`cu1xgI%DY}UxX`JEJXzBft#k;Y}Rx| z2W_e<2NQYEke$=LsNd63|HN*xT5Ov zzbR^nDGBr7F+UY62qu?mM7q;vU00SH3SvYPF%K}KBV2k7B_SJWk&vzo;O+UAU;6`SN5P+66OLM$!cz~rdWaYKXwJ&RBcT&PT=3-zzr05y2YS-MS9 z<{^ogfVxhO52pf#g+S%~k#h-THh-3lBL_%XoZ2g$EC$#c`L!$bZr}XVvV{q&k(4_y9`5L&TPAjBK`B1|YvgKU`v#Yfj zb79$*Z0X>t+{DKY_@Fb2b4=(fsEBX!3p6vPS|mYFaq7i4MDQ;#vE{jOr&0(tN3=Ft z#azgZ2fttKD$QO8G$FTPWT?=uw>l!!@|~ADBWg@u;#!7l7bvommF+O*?jy^L5%8BZ z#s|S4s@N7Rp;|A9l8|{X3@>6z4zsVC4rBHnGUkat{;o$ZP=JmBI3IO(Wq_qvh@Ah@ zma?5W>9hFtH(un_wln#K3~z?k!O-YPVa-2VA0#ajeEgaGwx(g0&RX-}K}&>I`;~rf z#ho`HZ;)@JOBy4)nnM)0b$tyO6g*d!!^Cb9zrkM!@=|zf&e`68N}yxll0BbRn(Vqw z42yJ6=xq#w-Lu#+^o%as$>gxU#Wj)=aJ4*FY{SV@z$EQwNe*Mq{@A=Lz|f@W;uyvI z#o8(pV!q=P_Z3gjm6DWDDM81|w28u!vR-6rF#rl;-cPQ8bf~4gU+NV9Vo3dP;i2Q! z2Vq275)e^SX8(D;yowow+g;SPgSL#7mJ77JlIOOo({@~&M4`QkGgfUWkPA8Naq8p%_j5;Ju5*G^6w1$?jMBV5NL{J(0`Y>%fHL00NN zm0G38P|;F8qvv}jLHZu}Qynfk8Fh#>C5AxUf=gWr$t$dWF1r}%V;9mmyli7$`%u2LZNI4 z&8URz+ZeQ1LaXeQEOTV1L!_*kL)I*lZ7gH?-EZgn`^)<^!~6Zr^W4vUU-xxg&se>w zg#1oN!%AL*rRU9r0bd9*Jph-mKsk*HeNx~yVX);GL$Yl-2#gB_14wg z)L_XfklZrCad_b+gnp`pn6-qDoIHI__T=3VYN;y1#7bnTPb5rE|S_@Yeh`(-p(?)CvYtb+}qVXdK&8N;1%!3y9O>G5jZUIcK$2kX_tXTJZ+u znREWm8z=>x#kZR#lpqb_sKm;Jqij}|b-R~ETkv#- z$^Z7pHVtcQBNRgh}Z+3wc zaU^s?UC~z;W=FH=$(Q?EwIFMn-8)`NtCL3aAn#Dw5Y^_s9(GtIj9yL4>O^)e0cCLa50j*BiDw}ozbYd!??^gAL@wHN zI!V}|v^)<-OP7c*ugnonu8(^}V!5 zPm1{vu-GRC5+>*Ct!HT(w8ksQPzr5ZUbJq4X!DBi-KE!D8yj@~OAgPRxG4J`@@$NM zkxVbXU|!wjL*+q)>z(nDqXHljq)nM&T3nQXBtyg$VcB76&7)Aa%>MtNg2zvlq`92p z0L=zCh%3A54MXX2QL{s_zG)AUZP6HQD3(L7mn_Q>gIHD@+dAEgaBweZSk%+ZG`v5l5z$S2G}Q?phRc?Uhdk@Bka9!M&h zF-=^@`Qhhu)p?vwZ&*vEkPT`bj8<7G;JyzWd@r-#xb1&Nm#s0GH( z%t$xqFoHWmrs_-~9po#0%5&^hq|)aUUjTIzU|Otra61OV$TeZLYV&Z>zk35H0r#`& zplLaeGZC%7vIY<|$bNcPOs=g>I}rUOt)_?>?pw?hJ1%@d^qTCxMytz%=3JEfblfcg zW8Q~INm$lH*?#(Hj>Nn}vZn#UMHYVJyFrn*3!{6dAIiC$Kc4edBh)V8IQMWfv@8#K zZ3nE7fHAlDCTWK>?Yyg1>hh1Y8Gs*k>JFT>*cDD*D0Bw%zd}UM8|^4z@g^P=do`pn36MigiupMaCrdkIf}XXs(4STapSMyWAUlqFat9 z=T?XXlB~q6rI24fr_f;&e^Cxb@y~<6Sz+&2kdvXT*&8D>mOFB0D=H-E0;S z&}i;r3|LnwH#Nb94=zw+TSF{00CB}LURS@{C1)=y2Vx<;71D+X4HrTsfA0#$Y;$KP zNOviRd!lT#vk7-OyDu*ew3LXM1%;kZzV2b1v8)Z<_GmJA@?Fq^=R0$YQHGwoa%eeT zP^=u1z;maF>RU;tY5@L*A7VLxjrt<;nsBJQHuZ!((+y3!7CGUP(Sre6?7r|j9alST zxyq@6%+9TEuGKOBw&Su5`UQ>`a}T=m>K~^4pdbu3a3P9#rtj##6GL1y!G|Y{^CcI6 z5;1dbMTCgX8kB92BoaB@56{NyrG#af%HFZ$#C>(~9r!**P>m|S*4i!37TfqrJ4I}T zaYuk1VEkNjok!rI1tdNDCSZLGH-VzbDjxdw9nr6zPIVnd1pC6`tncsG_2pnsZQflT zs){}epfG$mr1I>#Wcz2c3yvIor^o|H72nEdvaJ9hsTFL0AzUWCI5tabSQD%_U$^J} z)#WL*M0kw3BAxoAm_|Jnn-UFYqB3pA?_vK3l=uBhl26S$kqoqPO9rM{lCB!ZO-JAO3Vn&wM-+M+s1P>h(F!lNi*mC;a%wX#$h(39scn z1il$h0?CQG{>a7>kq$jsBIF_+&ohSY|BelRf9*jNe7@l8v=wJ$^%+A`gv^spf6b|C zrY@b+0ZO~J35lkGXsg{hS|kdEVT+1scMk0_jsu!jfj&Mbtg9n& zr*I9eHhCd^0+dw4tV=871a=8XVnH!BVyfOAv+WlnWmc15W>hYYkf#9iE_z%|Tyk3m zdji!jQyw8(Vr@aWQK092J1rUf>J1D;_4}E?n|8=J6dG+Xtt>qIE(X0#kPPgOjwP(V zy9jDocwJL1~?H+O^BNSfgLJm4Mm|?6&S{E0;9GBV%f~f^^xhMB4lz{vRrPARhnE zGDA~*+|nJL2MurLn#|bNS}TGH77fwRiqdXUn{3XI6_(@Z%B=GA{;i??wkpMvP+{%3 zjA_?^;5y$c=Tb>q+Yc#nmA|DV`1T&2ed+*;4q5O()27nc_Z}!(j;x9n#vQS{^muwvd4WSbN{59(8^s6-f0{luJg?K~Wo- zHu8Ecbt|s!i^9@vU9BRqY+Bw&Z-$DU(!phxKQ&KTy7Ca>#$1ijGLaFb#snSN4PA7$ zO(H<)O|JbBE@03_Dbl>%D1!>h;A_k+{gRo<k5ZPWPk7{RZ~7_r^sumwlb>3Kf{SBXtQXO~t&=L#AY8SZ~5@kH2vOlBDbicK0F#1a1#qF+s?t^*xBO zq}>2>G|E6Pa8`@|`XR$z`%xZSX#_Hq%%1~-wx5n6<|xH-gEA+{vO|agivM~*0@A>( zZdUz~x`7 zo3aQ@dM!Xb9{6MO^;WJcq3Su9Q|EYZQnbO)wXJSU%W{%l1O(Z?C6Q=jgz(d@uU5~7 zGwtg5hX~5U;lr`auzL~L9Sp9@sOj^%hb9Y;AHB|c0W4*d!){+~=2aa*_uCcX#q)VP^(LUOe`;!``KJmLg2l zk)<^1E$e-V<7%@+8$1pK>atD8hZn;3%Q-X`9Ybf>5l@2!+7}SAxoV`D1!fCeoJA*#MuVng4-hjsgWdq?4!OEg{L!8rRzUMd6JPXT{s|D%8U;!7VamJWwKQl#+;71i z`SH}!ixG)SkpzM_C1g+i+=rupC&7D+^qHE^25!}VaA`V7qNg}4f=mx_To`l45WJ$v zzsC#=clp{^k|w*7x5cGX`i8#|&UXe=w9F=q7@~ePoakbuuZ-uu#W2jIphHtBmB^4X zkG^~w(&nm;>0hi5c&?`nKbA%`wMtLU=-h{mwY6$JA4#qdfbfURQDdU5h*3aq#l~nj z20c4tTrWsM)4c5v6^n74d}U_|C(o-u|E{)nz49fd@!I)KU018Vi`^{b(5y(a_F&gy zghT)f<&IzTrZK4N#LhpjI{PS7MDq}Sv-Cr)qz4==P4&38r(EQcKp)|FR<&O6-- z%yx`TuX8B&0*RKa^3L9ulJ-w7Fuey3jn9Ae_ay`j4~a9>8_nwWjE1bsv$N}Sw*AR1 z(UM%Dem}n}xi6UK^100|IWn7{nGvQ+!H1ABaS@tM;+F>M$k;IE=naZe({Bl$H0?Rw zH$I091OIwYSXJk%Uh&k4*-0(;wdE4~@O}y-p83Cu?ISWZ3!k%NcZRRIf17N}NPGOL zMD3>zIMlhSkF{J#a>_c-xcO&r!ONyzt6yF~U!tb(jCt19Io`9AD{q_GxmALBCa20( zg5}H`rVQO%rjcK7*QjUwU9Tl6a53=XQX@^0HILwVX~oA`N#g7Fr_JGwTG|MT`^L^& zM=zlRVFU5v#7JKu?i-qc-#rxlPP%28GXlqLRSw-Yhng5|_~toB6rW7>5{1D)tCQt} zNTXe>Wt0OHi}`T;<4w5rs^=_AUPUMvAX4K>>t67Z=qn+CG7LiRSQ9PPP;Gnt=%4ob z3pStFMrmP>%zaeDX-yu8Cp_|z8Gc1yIzpTD%Poo? z=xkpf@0t9%4NXC`<8Ql+{R0${LXRmX<40PaR0c8UQ4+`H7ZtSOIl zWc|!f#}1oGOn=qL+rERzby7W{d4nr_ z3c1xM`1ghlgiI?6s;TSEMbK?*6fg?qA|-rPPW{z=J;XNW*$Ho#UqjxM6~lOcm5Hp! zUFJr}nBvW}P4AJ@zO>b@MfK}e3r$e1Z2EbBUCp++QkXx>s_c<1NXF@1$78FfAF-1! zb4fEsFP`%F$T3%1LPI7YBQ6pC_O7C4$#EHVrn%9)$_Bbffn~RBl5Kygh^E+d zI1lB4kDL6PR8(e|kGr2p_EpyX17?*99|T|OVw{)5HSi%Kx6w@%`1mp`}F4!uYn z+A3pe%jz1dO1fuX!_=1BCDXZRDk=-HU7h*5gtrxWDl1=hE>5hp1f#?9V~LRG0ih`* zWZ3G&-`YboGU+hUf5iDFm2NYKgsRlkc;055En65tb|SzaaGVXfds=ROCro@_uU-Jl zxJnZr3&YvNvHvT3`+qN{$NTFjJIk>!g6cltV`}y$u#s4EtegAFzqHusRdm^F8yd%V zxuK_v`*>=&W63eaW%<~s0a~Sn#7N6}^g!Wp; z^=$O&_Wd+RYZYOp(U9_l#_(zmmIg|=Uw;smgHPh{PSUr6DyKsS#NFi;C4WZ17E{lZ zfApZlqMw&$LbOzw4lrkmeW})7aNGRY_IE=~$w^Y^o`piw4a3TBqp25jj;sGrjtSMC zYv!6;m7jolQIAc8=!UU4E-^Q9I*FbAZF}*Ai6^UW%t^`j1Nf}0lET<|t~P%+krYDL zPFuuGL!hcevR-KAw~WksjKu8C997s9ov@2D9vBApe&&;i(8C>U$yBGjy%OUADAvZ+2ar++}- za@hJElTo*uM>Yu`qs7n^-0~<|=F?rf^E0=u8z(UvjIC@do%KQHiPJUGvBMj=>hcx+ z0EZf+y&x_YB6FPWGT_0-&?Gf@Zl;w)r3@tdb8(jgvL9&At+p9U^m59i6Ki7M#UuMd zJEkcq+{aBMjF5<9&RcRhfbVvb{XB-^X?xL?L%RK%3*LxUe08UO_o1HhE-~+YVqCcC zHB~kIGT)L<nLJV^m5g>MK`+B2urAbA1MFtA%o*t`m$_wR^f3i%R9Oa>i z#kP&v(*6kV-9JFfO_O_nPKfhmgPV!FgucmjC#)w?b%>oDm>EWR9v6vKON0ymvgQKu z4=xVapE;x=HP-T-E5jZ(WY=uEs;H>AW;43!Q>~HEKspbsjMWRgkiJHfb

    n_2llG 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ൡ%VA%Z?NNUfQEwh!LFd$wAT(<+& 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