Repository navigation
Conversation
…threads
Ordinary GGUFs ship per_layer_token_embd.weight in other formats than
IQ4_NL: Unsloth's UD-Q6_K_XL and Swift-1.5 Q4_K_L as Q8_0 (170-byte rows,
~54 GB), a Q5_K_M finetune as Q5_1 (120-byte rows). The engine
refused both at start ("... not IQ4_NL, Q5_0 or FP8 (I8)").
- dequantize_q5_1 in strata/artifact/dequant.hpp (ggml's dequantize_row_q5_1:
unsigned 5-bit codes times d plus the block minimum m); Q8_0 rows use the
existing dequantize_q8_0
- PleTable decodes Q5_1 / Q8_0 rows on both readers (the direct reader takes
the row size at runtime since the FP8 table); PLE_ROW_BYTES_MAX grows to 170
- --ple-io ram: before mlock, 16 threads fault the table in. mlock alone
brings a cold file in one page at a time from one thread, ~0.47 GiB/s
(about two minutes for a 54 GB Q8_0 table); 16 threads reach ~2 GiB/s.
- tests: dequant_q5_1_test (synthetic blocks against ggml, no model, no GPU),
dequant_bf16_test knows Q5_1, ple_q5_parity takes Q5_0, Q5_1 or Q8_0 tables
and checks both the mapped and the direct reader
|
I made the same Q8_0 part of this independently before finding this PR, so here is what I measured with it, in case End to end with a Q8_0 table. Unsloth's plain
How far each table encoding is from Qwen's original.
The IQ4_NL figure matches the 8.1% in 505e5e9, which was measured against the FP8 values. So for a model whose GGUF One small addition you may want: |
…_1/Q8_0) From the superseded PR Niko1221#651: tests/core/dequant_q5_1_test.cpp (dequantize_q5_1 vs ggml's dequantize_row_q5_1 on synthetic blocks), the dequant_bf16_test case for type 7, and ple_q5_parity's Q5_1/Q8_0 real-artifact check through both readers.
|
Superseded by #896: rebased on the current main (this branch conflicted after the upstream changes to |
Ordinary GGUFs ship per_layer_token_embd.weight in other formats than IQ4_NL: Unsloth's UD-Q6_K_XL and Swift-1.5 Q4_K_L as Q8_0 (170-byte rows, ~54 GB), a Q5_K_M finetune as Q5_1 (120-byte rows). The engine refused both at start. - dequantize_q5_1 in strata/artifact/dequant.hpp (ggml's dequantize_row_q5_1: unsigned 5-bit codes times d plus the block minimum m); Q8_0 rows use the existing dequantize_q8_0 - two entries in the PLE format list (the table-driven commit before this one): Q5_1 and Q8_0, on both readers; PLE_ROW_BYTES_MAX grows to 170 - tests: dequant_q5_1_test (synthetic blocks against ggml, no model, no GPU), dequant_bf16_test knows Q5_1, ple_q5_parity takes Q5_0, Q5_1 or Q8_0 tables and checks both the mapped and the direct reader Ported onto the format table by the maintainer from anon761's PR #651 (the --ple-io ram fault-in is the next commit). Quality of the Q8_0 table: ksanislo measured 0.53% error against the BF16 table, FP8 2.66%, IQ4_NL 7.59%. Co-authored-by: ksanislo <ksanislo@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PleTable::open compared rows x row_bytes against the file after the 64-bit product could already have wrapped, and mapped the tensor before checking it fits. Now: refuse a row count that overflows rows x row_bytes and a data section that starts past the end of the file, check offset and size without an addition that can wrap (offset > have, need > have - offset), require a single-tensor shard to start at offset 0 and fill the file, and map the table only after all of that. close() also resets the FP8 scale and the byte counter. ple_reader_test --selftest writes tables that claim one row too many, one too few and a wrapping row count, for every format, and checks both readers refuse each with a message and stay closed. Checks taken from CC-David-CC's #865 (its opt-in Q8_0 table is #651's; the direct reader reads Q8_0, so the experimental switch and the mapped-only limit are not needed). Co-authored-by: CC-David-CC <CC-David-CC@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#651) mlock alone brings a cold file in one page at a time from one thread, ~0.47 GiB/s (about two minutes for a 54 GB Q8_0 table); 16 threads reach ~2 GiB/s on anon761's machine. The pages are then resident and mlock only pins them. When mlock fails, the pages stay faulted in (the message says they may be reclaimed) instead of being touched again one by one. ple_reader_test gets --make-table PATH FORMAT (a big synthetic table, with --rows) and --ram-time PATH (open mapped and locked, print the seconds) to time it cold. Ported by the maintainer from anon761's PR #651. Co-authored-by: ksanislo <ksanislo@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…m the BF16 table Row error on 4,000 random rows against the checkpoint's BF16 table (Q8_0 0.53%, FP8 2.64%, IQ4_NL 7.60%, matching the numbers reported in #651), and teacher-forced KL on the Q2_0 model with each table. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…Q8_0 PLE hunk is left to the #651 series The PLE Q8_0 reader duplicates #651 and is dropped here. The grouped Q6_K instance is built only on request because every instance is loaded at engine start (EAGER) and costs slots for every other model. Co-authored-by: Thomas Weaver <266026663+DaRealDaHoodie@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…dy in f-140 (drops the duplicate hunks of #860) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Fixed in 0.1.40: the engine reads a Q8_0 or Q5_1 n-gram table, on the direct and the mapped reader, as one entry each in a new table of PLE formats (it also reads Q4_0, Q5_0, FP8 and BF16 now). |
Ordinary GGUFs ship per_layer_token_embd.weight in other formats than IQ4_NL: Unsloth's UD-Q6_K_XL and Swift-1.5 Q4_K_L as Q8_0 (170-byte rows, ~54 GB), a Q5_K_M finetune as Q5_1 (120-byte rows). The engine refused both at start. - dequantize_q5_1 in strata/artifact/dequant.hpp (ggml's dequantize_row_q5_1: unsigned 5-bit codes times d plus the block minimum m); Q8_0 rows use the existing dequantize_q8_0 - two entries in the PLE format list (the table-driven commit before this one): Q5_1 and Q8_0, on both readers; PLE_ROW_BYTES_MAX grows to 170 - tests: dequant_q5_1_test (synthetic blocks against ggml, no model, no GPU), dequant_bf16_test knows Q5_1, ple_q5_parity takes Q5_0, Q5_1 or Q8_0 tables and checks both the mapped and the direct reader Ported onto the format table by the maintainer from anon761's PR #651 (the --ple-io ram fault-in is the next commit). Quality of the Q8_0 table: ksanislo measured 0.53% error against the BF16 table, FP8 2.66%, IQ4_NL 7.59%. Co-authored-by: ksanislo <ksanislo@users.noreply.github.com>
PleTable::open compared rows x row_bytes against the file after the 64-bit product could already have wrapped, and mapped the tensor before checking it fits. Now: refuse a row count that overflows rows x row_bytes and a data section that starts past the end of the file, check offset and size without an addition that can wrap (offset > have, need > have - offset), require a single-tensor shard to start at offset 0 and fill the file, and map the table only after all of that. close() also resets the FP8 scale and the byte counter. ple_reader_test --selftest writes tables that claim one row too many, one too few and a wrapping row count, for every format, and checks both readers refuse each with a message and stay closed. Checks taken from CC-David-CC's #865 (its opt-in Q8_0 table is #651's; the direct reader reads Q8_0, so the experimental switch and the mapped-only limit are not needed). Co-authored-by: CC-David-CC <CC-David-CC@users.noreply.github.com>
#651) mlock alone brings a cold file in one page at a time from one thread, ~0.47 GiB/s (about two minutes for a 54 GB Q8_0 table); 16 threads reach ~2 GiB/s on anon761's machine. The pages are then resident and mlock only pins them. When mlock fails, the pages stay faulted in (the message says they may be reclaimed) instead of being touched again one by one. ple_reader_test gets --make-table PATH FORMAT (a big synthetic table, with --rows) and --ram-time PATH (open mapped and locked, print the seconds) to time it cold. Ported by the maintainer from anon761's PR #651. Co-authored-by: ksanislo <ksanislo@users.noreply.github.com>
…m the BF16 table Row error on 4,000 random rows against the checkpoint's BF16 table (Q8_0 0.53%, FP8 2.64%, IQ4_NL 7.60%, matching the numbers reported in #651), and teacher-forced KL on the Q2_0 model with each table.
…Q8_0 PLE hunk is left to the #651 series The PLE Q8_0 reader duplicates #651 and is dropped here. The grouped Q6_K instance is built only on request because every instance is loaded at engine start (EAGER) and costs slots for every other model. Co-authored-by: Thomas Weaver <266026663+DaRealDaHoodie@users.noreply.github.com>
…dy in f-140 (drops the duplicate hunks of #860)
Ordinary GGUFs ship per_layer_token_embd.weight in other formats than IQ4_NL: Unsloth's UD-Q6_K_XL and Swift-1.5 Q4_K_L as Q8_0 (170-byte rows, ~54 GB), a Q5_K_M finetune as Q5_1 (120-byte rows). The engine refused both at start. - dequantize_q5_1 in strata/artifact/dequant.hpp (ggml's dequantize_row_q5_1: unsigned 5-bit codes times d plus the block minimum m); Q8_0 rows use the existing dequantize_q8_0 - two entries in the PLE format list (the table-driven commit before this one): Q5_1 and Q8_0, on both readers; PLE_ROW_BYTES_MAX grows to 170 - tests: dequant_q5_1_test (synthetic blocks against ggml, no model, no GPU), dequant_bf16_test knows Q5_1, ple_q5_parity takes Q5_0, Q5_1 or Q8_0 tables and checks both the mapped and the direct reader Ported onto the format table by the maintainer from anon761's PR Niko1221#651 (the --ple-io ram fault-in is the next commit). Quality of the Q8_0 table: ksanislo measured 0.53% error against the BF16 table, FP8 2.66%, IQ4_NL 7.59%. Co-authored-by: ksanislo <ksanislo@users.noreply.github.com>
PleTable::open compared rows x row_bytes against the file after the 64-bit product could already have wrapped, and mapped the tensor before checking it fits. Now: refuse a row count that overflows rows x row_bytes and a data section that starts past the end of the file, check offset and size without an addition that can wrap (offset > have, need > have - offset), require a single-tensor shard to start at offset 0 and fill the file, and map the table only after all of that. close() also resets the FP8 scale and the byte counter. ple_reader_test --selftest writes tables that claim one row too many, one too few and a wrapping row count, for every format, and checks both readers refuse each with a message and stay closed. Checks taken from CC-David-CC's Niko1221#865 (its opt-in Q8_0 table is Niko1221#651's; the direct reader reads Q8_0, so the experimental switch and the mapped-only limit are not needed). Co-authored-by: CC-David-CC <CC-David-CC@users.noreply.github.com>
Niko1221#651) mlock alone brings a cold file in one page at a time from one thread, ~0.47 GiB/s (about two minutes for a 54 GB Q8_0 table); 16 threads reach ~2 GiB/s on anon761's machine. The pages are then resident and mlock only pins them. When mlock fails, the pages stay faulted in (the message says they may be reclaimed) instead of being touched again one by one. ple_reader_test gets --make-table PATH FORMAT (a big synthetic table, with --rows) and --ram-time PATH (open mapped and locked, print the seconds) to time it cold. Ported by the maintainer from anon761's PR Niko1221#651. Co-authored-by: ksanislo <ksanislo@users.noreply.github.com>
…m the BF16 table Row error on 4,000 random rows against the checkpoint's BF16 table (Q8_0 0.53%, FP8 2.64%, IQ4_NL 7.60%, matching the numbers reported in Niko1221#651), and teacher-forced KL on the Q2_0 model with each table.
…Q8_0 PLE hunk is left to the Niko1221#651 series The PLE Q8_0 reader duplicates Niko1221#651 and is dropped here. The grouped Q6_K instance is built only on request because every instance is loaded at engine start (EAGER) and costs slots for every other model. Co-authored-by: Thomas Weaver <266026663+DaRealDaHoodie@users.noreply.github.com>
…es already in f-140 (drops the duplicate hunks of Niko1221#860)
Ordinary GGUFs ship per_layer_token_embd.weight in other formats than IQ4_NL: Unsloth's UD-Q6_K_XL and Swift-1.5 Q4_K_L as Q8_0 (170-byte rows, ~54 GB), a Q5_K_M finetune as Q5_1 (120-byte rows). The engine refused both at start. - dequantize_q5_1 in strata/artifact/dequant.hpp (ggml's dequantize_row_q5_1: unsigned 5-bit codes times d plus the block minimum m); Q8_0 rows use the existing dequantize_q8_0 - two entries in the PLE format list (the table-driven commit before this one): Q5_1 and Q8_0, on both readers; PLE_ROW_BYTES_MAX grows to 170 - tests: dequant_q5_1_test (synthetic blocks against ggml, no model, no GPU), dequant_bf16_test knows Q5_1, ple_q5_parity takes Q5_0, Q5_1 or Q8_0 tables and checks both the mapped and the direct reader Ported onto the format table by the maintainer from anon761's PR Niko1221#651 (the --ple-io ram fault-in is the next commit). Quality of the Q8_0 table: ksanislo measured 0.53% error against the BF16 table, FP8 2.66%, IQ4_NL 7.59%. Co-authored-by: ksanislo <ksanislo@users.noreply.github.com>
PleTable::open compared rows x row_bytes against the file after the 64-bit product could already have wrapped, and mapped the tensor before checking it fits. Now: refuse a row count that overflows rows x row_bytes and a data section that starts past the end of the file, check offset and size without an addition that can wrap (offset > have, need > have - offset), require a single-tensor shard to start at offset 0 and fill the file, and map the table only after all of that. close() also resets the FP8 scale and the byte counter. ple_reader_test --selftest writes tables that claim one row too many, one too few and a wrapping row count, for every format, and checks both readers refuse each with a message and stay closed. Checks taken from CC-David-CC's Niko1221#865 (its opt-in Q8_0 table is Niko1221#651's; the direct reader reads Q8_0, so the experimental switch and the mapped-only limit are not needed). Co-authored-by: CC-David-CC <CC-David-CC@users.noreply.github.com>
Niko1221#651) mlock alone brings a cold file in one page at a time from one thread, ~0.47 GiB/s (about two minutes for a 54 GB Q8_0 table); 16 threads reach ~2 GiB/s on anon761's machine. The pages are then resident and mlock only pins them. When mlock fails, the pages stay faulted in (the message says they may be reclaimed) instead of being touched again one by one. ple_reader_test gets --make-table PATH FORMAT (a big synthetic table, with --rows) and --ram-time PATH (open mapped and locked, print the seconds) to time it cold. Ported by the maintainer from anon761's PR Niko1221#651. Co-authored-by: ksanislo <ksanislo@users.noreply.github.com>
…m the BF16 table Row error on 4,000 random rows against the checkpoint's BF16 table (Q8_0 0.53%, FP8 2.64%, IQ4_NL 7.60%, matching the numbers reported in Niko1221#651), and teacher-forced KL on the Q2_0 model with each table.
…Q8_0 PLE hunk is left to the Niko1221#651 series The PLE Q8_0 reader duplicates Niko1221#651 and is dropped here. The grouped Q6_K instance is built only on request because every instance is loaded at engine start (EAGER) and costs slots for every other model. Co-authored-by: Thomas Weaver <266026663+DaRealDaHoodie@users.noreply.github.com>
…es already in f-140 (drops the duplicate hunks of Niko1221#860)
upstream v0.1.39..v0.1.40.2 の PLE の表の正味の変更を、ファイルごとに 3 方向で移す(upstream 側はリベースで同じ変更が二重に入っていて、 後で edc0cb6 が落としたため、コミットごとには当てない)。含むもの: ce62f50(形式の一覧)、74945954(Q8_0・Q5_1)、e79b8fc1(表の大きさの 計算の確認)、626a89bc(--ple-io ram で 16 スレッドまで使ってページを 読み込んでから mlock)、cb87a62e(BF16 の表)、bea06429(表より長い ファイルの言い方)、16bdc707 の Q4_0 の表。Windows の mlock の代わりは XeStrata で外しているので入れない。 dequant_q5_1_test(ggml の Q5_1 と合わせる、モデルも GPU も使わない)を CTest に足す。新しいファイルに SPDX の見出しを付け、clang-tidy の指摘を 直した(再現のための固定の種とビット単位の比較は NOLINT で理由を書く)。 B70 の IQ2_XS(IQ4_NL の表、icpx)で、思考あり・なしの 4 問の答えが マージ前の dev のエンジンとすべて同じで、出力の速さも同じだった。 CTest は llvm7・icpx で 54 件通る。
What
Several ordinary GGUFs of Qwen3.8-Flash-Next ship
per_layer_token_embd.weightin a format the PLE reader refuses at start:UD-Q6_K_XLQ4_K_LQ5_K_MThe rest of these files already has a path in the engine (Q5_K/Q6_K/Q5_1/Q8_0 experts, the K-quant projections,
--compat-bf16). For the Q5_K_M file the table was the only thing keeping it from starting (end to end below); the Q8_0 tables are covered by the parity test on the real files.dequantize_q5_1instrata/artifact/dequant.hpp(ggml'sdequantize_row_q5_1: unsigned 5-bit codes timesdplus the block minimumm); Q8_0 rows use the existingdequantize_q8_0PleTabledecodes Q5_1 / Q8_0 rows on both readers. The direct reader already takes the row size at runtime (since the FP8 table), so no reader change was needed;PLE_ROW_BYTES_MAXgrows to 170--ple-io ram: beforemlock, 16 threads fault the table in.mlockalone brings a cold file in one page at a time from one thread; on a ZFS pool that read the 54 GB Q8_0 table at ~0.47 GiB/s (about two minutes), 16 threads at ~2 GiB/s (measured from a cold cache before the rebase onto currentmain; the container this was re-tested in cannot drop the file cache). The fallback whenmlockfails keeps the pages faulted in instead of touching them a second time.Tests
dequant_q5_1_test(new, CTest): 4096 synthetic blocks incl. the edge codes 0 and 31 and a negative minimum against ggml'sto_float, bit-exact. No model, no GPU.dequant_bf16_testknows Q5_1.ple_q5_paritynow takes a Q5_0, Q5_1 or Q8_0 table and checks both the mapped and the direct reader (single rows and a 16-row batch) against ggml'sto_floaton the real file:End to end
The Q5_K_M file (Q5_1 table) on 2x RTX 3090, layer split auto, 262K context,
--kv int8 --pcie-frac 0;mainrefuses it at start:--ple-ioram(table locked in 3.2 s, warm file cache)direct(default)