Skip to content

Abyss v1.3.83 — CUDA の投機デコード(検証窓)でエキスパートの重みが消えていた不具合を修正

Choose a tag to compare

@zephel01 zephel01 released this 31 Oct 01:53
· 79 commits to main since this release

v1.3.74 から、CUDA で投機デコードを使うと答えが崩れていました。修正しました。

RTX 5090 で測りました。条件は Qwen3.8-Flash-Next ISTA IQ3_S、MTP ドラフター on、greedy です。能力問題 120 問と日常タスク 30 本の結果:

ドラフター on(修正前) ドラフター on(修正後) ドラフター off
数学 3/50 43/50 43/50
ループした答え — 2/130 3/130
速度 — 100.4 tok/s 72.0 tok/s
  • 原因: ルートカーネルが配列の外に書いていた。 v1.3.74 から、fetch_src の未使用欄を 16 個目まで 0 で消していました。ところが配列は max(8, k) 個しかありません。検証窓の列ごとの領域では、この配列の直後に plan_w(各エキスパートの重み)が置かれています。そのため、CUDA の検証窓では選ばれたエキスパートが全部重み 0 になり、共有エキスパートと CPU レーン分しか効いていませんでした。
    • 影響したのは窓を使う投機デコード全部です。Qwen3.8 の MTP ドラフター、DeepSeek V4.1 の DSpark、n-gram 窓が該当します。
    • V4.1 UD-IQ2_XXS + DSpark の答えは、修正前は 2〜6 トークン目でドラフトなしの答えと分かれていました。修正後は、16 トークン目以降で分かれるか、最後まで同じです。
    • 1 トークンずつの通常経路は影響を受けていません。
    • HIP(AMD)は、今 PC に AMD のカードが無いため確かめていません。
  • Qwen3.8 の窓のスクラッチ置き場を列ごとに分けました(最大 6 列。V4.1 と同じ方式)。これまでは列 3〜5 が同じ置き場を共有しており、ある列の読み込みが別の列のエキスパートを上書きすることがありました。
  • Qwen3.8 で 2,051 トークンを超えたとき: 却下された窓の列が、注意インデクサのキー末尾を書き換えたまま残る問題を直しました。
  • ./abyss.sh --bench に「ドラフターチェック」を追加しました。 最初の答えをもう一度 1 トークンずつ出させ、どこで分かれるかを表示します(docs/BENCH.ja.md)。
    • --serve の GEN ... spec=0 で、1 回分だけ投機デコードなしで答えさせられます。
    • tools/mtp_greedy_check.py を使うと、複数のプロンプトでまとめて比べられます。

更新方法はいつもどおりで、git pull してから ./setup.sh を実行してください。


CUDA speculative decoding: the verify windows kept their experts' weights again

Speculative decoding on CUDA gave wrong answers since v1.3.74. Fixed.

Measured on an RTX 5090 with Qwen3.8-Flash-Next ISTA IQ3_S, the MTP drafter on, and greedy decoding. The set was 120 capability items and 30 everyday tasks:

drafter on (before) drafter on (after) drafter off
math 3/50 43/50 43/50
looping answers — 2/130 3/130
speed — 100.4 tok/s 72.0 tok/s
  • Cause: the route kernel wrote past an array. Since v1.3.74 it cleared fetch_src up to 16 entries, but the array holds only max(8, k). In a verify window column's block, plan_w (the experts' weights) comes right after it. So every window column on CUDA ran without its routed experts: only the shared expert and the CPU lane's share were left.
    • This hit every windowed drafter: Qwen3.8's MTP, DeepSeek V4.1's DSpark, and the n-gram windows.
    • V4.1 UD-IQ2_XXS + DSpark answers parted from the no-draft answers at token 2-6. Now they part at token 16 or later, or not at all.
    • The token-by-token path was not affected.
    • HIP (AMD) is not checked: there is no AMD card in the test PC right now.
  • Qwen3.8's windows: one scratch slot set per column (up to 6 columns, as for V4.1). Columns 3-5 shared one set before, so a fetch for one column could overwrite another column's experts.
  • Qwen3.8 past 2,051 tokens: a rejected window column no longer leaves the attention indexer's key tail changed.
  • ./abyss.sh --bench has a drafter check. It asks the first answer again token by token and shows where the two part (docs/BENCH.md).
    • GEN ... spec=0 on the --serve wire asks for one answer without speculative decoding.
    • tools/mtp_greedy_check.py compares many prompts at once.

Update as usual: git pull, then run ./setup.sh.