Repository navigation
Abyss v1.3.83 — CUDA の投機デコード(検証窓)でエキスパートの重みが消えていた不具合を修正
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_srcup 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 --benchhas a drafter check. It asks the first answer again token by token and shows where the two part (docs/BENCH.md).GEN ... spec=0on the--servewire asks for one answer without speculative decoding.tools/mtp_greedy_check.pycompares many prompts at once.
Update as usual: git pull, then run ./setup.sh.