speech.cpp 0.8.4 released: quantized versions of every model, and more
by 逆瀬川ちゃん
17 min read
Hi! This is Sakasegawa (@gyakuse)!
Today I'm writing about the 0.8.4 release of speech.cpp. The biggest change is that almost every model now comes in smaller files that fit on PCs with little memory.
speech.cpp is an engine that runs speech synthesis, speech recognition and voice activity detection models in C++ (earlier post).
0.8.4 brings four changes:

The biggest is that you can choose the size of each model's file. A smaller type takes this much less memory:

The speed changes differently by model. Qwen3-ASR and Qwen3-TTS get faster the smaller the type, while FastConformer (ReazonSpeech and the others) and Irodori-TTS stay about the same. Below, the time to recognize one utterance:

Both were measured on an Apple M5. This post goes through the accuracy, memory and speed of every model, with numbers.
What changed in 0.8.4
- Quantized files
- Nine models, all but Silero VAD, come in Q6_K, Q5_K and Q4_K
- Models that only had an F16 file also come in Q8_0
- Qwen3-TTS and Qwen3-ASR also get faster in the smaller types
- ReazonSpeech and parakeet-ja now use their Q8_0 file when named alone
- The accuracy is almost the same as F16, and the memory is close to half
- Fixed Qwen3-TTS's Q5_K and Q4_K stopping with an error partway through synthesis on Vulkan
- The memory peak while a model loads dropped by about 150 to 320 MB
- On the Mac, a program that embeds
libspeechno longer has its environment variables changed
Updating
Run the same command you installed with. On Apple silicon Macs and Linux:
curl -fsSL https://raw.githubusercontent.com/nyosegawa/speech.cpp/main/install.sh | sh
On Windows, in PowerShell:
irm https://raw.githubusercontent.com/nyosegawa/speech.cpp/main/install.ps1 | iex
ReazonSpeech (reazonspeech-v2) and parakeet-ja (parakeet-tdt_ctc-0.6b-ja) now use their Q8_0 file instead of F16 when named alone, so the first run after updating downloads the Q8_0 file (0.66 GB). To keep using F16, add :f16 after the name, as in reazonspeech-v2:f16. If you no longer need the F16 file, this removes it:
speech rm reazonspeech-v2:f16
Using a quantized type
Add a colon and the type after the model's name. The first time, the file is downloaded from Hugging Face.
speech asr qwen3-asr-1.7b:q6_k meeting.wav
speech tts qwen3-tts-0.6b:q6_k "It will be sunny in Tokyo tomorrow."
speech serve qwen3-tts-1.7b:q4_k qwen3-asr-0.6b silero-vad
speech models lists the types each model has.
qwen3-tts-0.6b q8_0 1.21 GB yes synthesis de en es fr it ja ko pt ru zh
qwen3-tts-0.6b:q6_k q6_k 0.99 GB no synthesis de en es fr it ja ko pt ru zh
qwen3-tts-0.6b:q5_k q5_k 0.87 GB no synthesis de en es fr it ja ko pt ru zh
qwen3-tts-0.6b:q4_k q4_k 0.76 GB no synthesis de en es fr it ja ko pt ru zh
The number in a type is roughly how many bits each weight takes. The smaller the number, the smaller the file and the memory, and the lower the accuracy. How much lower turned out to differ a lot between models.
Choosing a type for each model
First, the short version: what to pick when you want to save memory. How far a model goes down with almost no loss of accuracy differs by model:

The memory and accuracy of each model are in the chart and the table below. The memory is the peak of one recognition or synthesis.

| Model | Named alone | To save memory | What changes |
|---|---|---|---|
| parakeet-ja | Q8_0 (0.78 GB) | Q4_K (0.47 GB) | Almost nothing |
| ReazonSpeech | Q8_0 (0.78 GB) | Q4_K (0.47 GB) | Almost nothing |
| parakeet-v3 | F16 (1.37 GB) | Q6_K (0.63 GB) | WER up 0.1 points |
| Qwen3-ASR 0.6B | Q8_0 (1.00 GB) | Q6_K (0.84 GB) | Almost nothing |
| Qwen3-ASR 1.7B | Q8_0 (2.34 GB) | Q6_K (1.85 GB) | Almost nothing |
| Qwen3-TTS 0.6B | Q8_0 (1.37 GB) | Q6_K (1.15 GB) | Almost nothing; Q4_K misreads more |
| Qwen3-TTS 1.7B | Q8_0 (2.44 GB) | Q6_K (1.98 GB) | No difference we could measure |
| Irodori-TTS | F16 (2.03 GB) | Q6_K (1.16 GB) | No difference we could measure |
| Irodori-TTS MF | F16 (2.04 GB) | Q6_K (1.16 GB) | Every quantized type is a little harder to understand |
The rest of this section shows the numbers behind that table. Everything was measured with speech-bench on an Apple M5 with Metal; Appendix E has the details.
Japanese speech recognition
The CER on the Japanese test set of Common Voice 8.0 (4,483 utterances). The number after the slash is the CER when other spellings of the same words, such as 「行う」 and 「行なう」, count as correct.
| Type | File | Memory | parakeet-ja | ReazonSpeech |
|---|---|---|---|---|
| F16 | 1.24 GB | 1.37 GB | 7.88% / 2.98% | 12.02% / 7.13% |
| Q8_0 | 0.66 GB | 0.78 GB | 7.93% / 3.00% | 12.05% / 7.15% |
| Q6_K | 0.51 GB | 0.63 GB | 7.88% / 3.00% | 11.98% / 7.12% |
| Q5_K | 0.43 GB | 0.54 GB | 7.79% / 2.97% | 11.99% / 7.14% |
| Q4_K | 0.36 GB | 0.47 GB | 7.94% / 3.01% | 12.16% / 7.23% |
parakeet-ja and ReazonSpeech barely move even at Q4_K, while the memory goes from 1.37 GB to 0.47 GB. If memory is short, Q4_K is a safe pick for both.
| Type | 0.6B file | Memory | Qwen3-ASR 0.6B | 1.7B file | Memory | Qwen3-ASR 1.7B |
|---|---|---|---|---|---|---|
| Q8_0 | 0.84 GB | 1.00 GB | 11.89% / 7.05% | 2.18 GB | 2.34 GB | 9.49% / 4.67% |
| Q6_K | 0.68 GB | 0.84 GB | 12.01% / 7.02% | 1.68 GB | 1.85 GB | 9.52% / 4.72% |
| Q5_K | 0.59 GB | 0.75 GB | 12.49% / 7.57% | 1.41 GB | 1.58 GB | 9.85% / 4.96% |
| Q4_K | 0.51 GB | 0.67 GB | 14.23% / 8.66% | 1.16 GB | 1.32 GB | 11.21% / 5.96% |
Qwen3-ASR stays close to Q8_0 down to Q6_K, and its CER rises at Q5_K and Q4_K. One interesting point: the 1.7B model at Q4_K (1.32 GB) has a lower CER than the 0.6B model at Q8_0 (1.00 GB). If you have another 0.3 GB to spare, the 1.7B model at Q4_K recognizes more accurately than the 0.6B model.
Recognition in English and other languages
parakeet-v3 (parakeet-tdt-0.6b-v3) was measured by WER on 300 English utterances of FLEURS. Its files and memory are about the same as parakeet-ja's.
| Type | WER |
|---|---|
| F16 | 8.76% |
| Q8_0 | 9.06% |
| Q6_K | 8.87% |
| Q5_K | 9.13% |
| Q4_K | 9.51% |
Speech synthesis
For synthesis, 20 Japanese sentences were synthesized with three seeds, Qwen3-ASR 1.7B transcribed the audio, and the CER was taken against the original text. Each number is the mean of 60 syntheses. The same type moves by a few points from seed to seed, so a difference of one or two points does not say which type is better.
| Type | 0.6B file | Memory | Qwen3-TTS 0.6B | 1.7B file | Memory | Qwen3-TTS 1.7B |
|---|---|---|---|---|---|---|
| Q8_0 | 1.21 GB | 1.37 GB | 6.14% | 2.29 GB | 2.44 GB | 6.25% |
| Q6_K | 0.99 GB | 1.15 GB | 6.03% | 1.82 GB | 1.98 GB | 4.42% |
| Q5_K | 0.87 GB | 1.03 GB | 7.35% | 1.57 GB | 1.72 GB | 6.02% |
| Q4_K | 0.76 GB | 0.92 GB | 13.60% | 1.33 GB | 1.48 GB | 7.19% |
Only Qwen3-TTS 0.6B at Q4_K more than doubled its CER over Q8_0. To shrink the 0.6B model, stop at Q6_K. That said, from what I heard, every quantized version of Qwen3-TTS tends to come out with flatter intonation. That is hard to put into a score, so it's worth trying them and listening for yourself. The 1.7B model at Q4_K stayed within the seed-to-seed spread on average. Still, when I later listened sentence by sentence, it turned a sentence with English words into entirely different words, so the table above suggests Q6_K.
| Type | MF file | Memory | Irodori-TTS MF | File | Memory | Irodori-TTS |
|---|---|---|---|---|---|---|
| F16 | 1.92 GB | 2.04 GB | 5.92% | 1.91 GB | 2.03 GB | 3.43% |
| Q8_0 | 1.21 GB | 1.33 GB | 8.35% | 1.20 GB | 1.32 GB | 4.09% |
| Q6_K | 1.04 GB | 1.16 GB | 7.35% | 1.03 GB | 1.16 GB | 3.65% |
| Q5_K | 0.95 GB | 1.07 GB | 7.74% | 0.94 GB | 1.07 GB | 4.37% |
| Q4_K | 0.86 GB | 0.99 GB | 7.57% | 0.86 GB | 0.98 GB | 4.54% |
Irodori-TTS (irodori-tts) was measured with 16 steps (the default is 40). Down to Q4_K, its difference from F16 stayed within the seed-to-seed spread. Unlike Qwen3-TTS, the quantized versions kept a normal intonation. On the other hand, effects such as the caption's may have weakened. Both Irodori-TTS models keep the codec that decodes the audio in F32 in every type, so their files shrink less than the other models'.
The MF model got worse in every quantized type. Its F16 CER per seed was 5.31 to 6.30%, and the means of the quantized types (7.35 to 8.35%) fall outside that range. MF makes its audio in four steps, so an error made in one step may survive to the end. MF delivers its first audio in about a fifth of the time Irodori-TTS takes with 16 steps, so the choice comes down to memory versus speed.
The type a name uses alone
The type a model uses when named alone was decided like this:
- A recognition model uses Q8_0 when its CER is within 0.2 points of F16's, with and without other spellings counted as correct
- A synthesis model uses Q8_0 when its mean CER falls within the range of F16's per-seed CERs
- Q6_K, Q5_K and Q4_K are never used, however good their numbers
The third rule is there because a type that does well on this data may still do worse on other recordings or another GPU. If that happened to the type a name uses alone, it would reach everyone who never chose a type. The smaller types are for people who choose them after seeing the numbers above.
With these rules, parakeet-ja and ReazonSpeech changed to Q8_0. parakeet-v3 stays at F16, since its WER rose 0.3 points at Q8_0, and both Irodori-TTS models stay at F16.
Using Qwen3-TTS's Q5_K and Q4_K on Vulkan
Qwen3-TTS's Q5_K and Q4_K need 0.8.4 on Vulkan. With the Vulkan build of 0.8.3 or earlier, these two files stop partway through synthesis with this error:
speech: internal: no token has a finite logit to pick from
The cause is in ggml's Vulkan backend: a value in the middle of the computation went past the largest number F16 can hold (65504) and became infinite. 0.8.4 builds on a ggml with a fix; Appendix A explains the cause and the fix. Q8_0 and Q6_K synthesize correctly on 0.8.3 and earlier too.
To carry this fix, speech.cpp now builds on my fork of ggml (nyosegawa/ggml) instead of the upstream repository. Appendix C describes how the fork is kept.
Memory and speed
0.8.4 also lowers the memory peak while a model loads. 0.8.3 read each tensor from the file into a temporary buffer as large as the largest tensor; 0.8.4 reads 16 MB at a time, so the peak drops by that buffer.
| Model (M5, Metal) | 0.8.3 | 0.8.4 |
|---|---|---|
| Qwen3-TTS 1.7B Q8_0 | 2758 MB | 2443 MB |
| Qwen3-ASR 0.6B Q8_0 | 1154 MB | 1005 MB |
| Irodori-TTS F16 | 2171 MB | 2030 MB |
On Vulkan the memory also drops after loading. On an RTX 2080, a Qwen3-ASR 1.7B worker waiting for requests went from 2635 MB to 2325 MB; Appendix D explains why.
For the same type, the speed is the same as 0.8.3, and so is the time to load. On the Mac, 0.8.4 computes exactly what 0.8.3 did: the output of all ten models matched 0.8.3 byte for byte.
Speed by type
The type does change the speed. I measured the time to the first audio and the time to make a second of audio (RTF) for synthesis, and the time from a finished utterance to its text for recognition. The type a name uses alone is 100%. First, the Apple M5:

- Qwen3-TTS and Qwen3-ASR get faster the smaller the type
- At Q4_K, Qwen3-ASR 1.7B recognizes 27% faster, and Qwen3-TTS makes its audio in about 30% less time
- Qwen3-TTS's first audio already arrives in 0.04 to 0.06 s, and Q4_K changes it by a few milliseconds
- The three FastConformer models (parakeet-ja, ReazonSpeech, parakeet-v3) and Irodori-TTS run at about the same speed in every type
Qwen3-TTS and Qwen3-ASR read all their weights from memory for every token they make, so smaller weights mean less to read and a faster model. FastConformer and Irodori-TTS process many frames in each computation, so the computing takes longer than reading the weights, which is likely why smaller weights do not make them faster.
I measured the same on an RTX 2080 (Vulkan) under Windows:

The pattern is the same as on the M5. At Q4_K, Qwen3-ASR 1.7B recognizes 25% faster and Qwen3-TTS 1.7B makes its audio in 22% less time, while FastConformer and Irodori-TTS stay about the same. This release's fix changed how Vulkan computes Q4_K and Q5_K, and they are still faster than Q8_0. On the RTX 2080, parakeet-ja and ReazonSpeech are also 10 to 20% slower in F16 than in Q8_0, so using Q8_0 when they are named alone pays off in speed too.
Load time
Smaller types also load faster. I measured it on an Apple M5 with the system's file cache emptied (the first use after starting the computer) and with the file in the cache (later uses).

- The load time shrinks about in proportion to the file
- The three FastConformer models load in 0.35 s at F16 and about 0.2 s at Q4_K
- Qwen3-TTS 1.7B and Qwen3-ASR 1.7B take a little over 0.6 s at Q8_0 with the cache empty, and just under 0.5 s at Q4_K
- With the file in the cache, every model loads in about half the time it takes with the cache empty
The M5's SSD is fast, so every model loads within 0.7 s even with the cache empty. The first run after installing, though, also takes about 15 s to prepare Metal's shaders, once.
Summary
- In 0.8.4, every model but Silero VAD comes in types from Q8_0 down to Q4_K
- parakeet-ja, ReazonSpeech, Qwen3-ASR and Irodori-TTS barely change down to Q6_K, and parakeet-ja and ReazonSpeech not even at Q4_K
- If you use Qwen3-TTS's Q5_K or Q4_K on Vulkan, update to 0.8.4
Appendix A: why Q5_K and Q4_K gave NaN on Vulkan
How it showed up
I found it while running the published files one by one on an RTX 2080 under Windows. Only Qwen3-TTS 0.6B synthesized or failed depending on the type. The same files synthesized fine on the Windows CPU and with Metal on the Mac.
| Qwen3-TTS 0.6B | Vulkan (RTX 2080) |
|---|---|
| Q8_0 | synthesizes |
| Q6_K | synthesizes |
| Q5_K | error |
| Q4_K | error |
ggml's Vulkan backend has environment variables that turn off some ways of computing. Trying them one at a time, synthesis worked only with GGML_VK_DISABLE_MMVQ or GGML_VK_DISABLE_INTEGER_DOT_PRODUCT set. Both stop the backend from computing matrix products with integer dot products.
The block sum of q8_1 goes past F16
When ggml's Vulkan backend computes a matrix product with integer dot products, it quantizes the activations that multiply the weights to a format called q8_1. q8_1 groups 32 values and stores 32 int8 values, an F16 scale d and an F16 sum s. s is about the sum of the 32 activations.

The largest number F16 can hold is 65504, so 32 activations above 2048 in a row make s infinite. LLMs are known to produce very large activations in a few channels (Sun et al., 2024), and somewhere in Qwen3-TTS they reached this size.
Whether s is used depends on the weight type. Q4_K stores a scale d and a minimum m for every 32 weights and writes a weight as w = d·q − m (q an integer from 0 to 15). Writing an activation as a ≈ d_a·r (r an int8), the dot product of 32 of them is:
The first term is an integer dot product, and the second uses s. ggml's shader computes Q4_K and Q5_K exactly this way:
return ACC_TYPE(float(cache_b.ds.x) * float(cache_a[ib_a].dm.x) * float(q_sum) - float(cache_a[ib_a].dm.y) * float(cache_b.ds.y));
ggml-org/ggml v0.25.3: src/ggml-vulkan/vulkan-shaders/mul_mmq_funcs.glsl
cache_b.ds.y is s. When it is infinite, the result is infinite or NaN. Q8_0 and Q6_K have no minimum, so they have no second term and never read s, which is why only those two synthesized. Reading the shaders, eight types use s: Q2_0, Q4_0, Q4_1, Q5_0, Q5_1, Q4_K, Q5_K and IQ1_S.
On the CPU, Q4_K quantizes the activations to a different format, Q8_K, which stores its sums as int16 and its scale as F32, so the problem does not arise there.
The fix
For the eight types that use s, the backend no longer computes through q8_1. ggml already does the same for Q6_K on NVIDIA GPUs, and the fix adds these eight types to that condition. Nothing changes for Q8_0 and Q6_K.
A Codex review of the fix found one more problem. Without q8_1, ggml converts the weights back to F16 and computes the product from them. When a matrix product has no precision set, this path sums in F16 and clips results above 65504 to 65504. Qwen3's decoder in speech.cpp sets no precision, so an input whose block sums stay under 65504 but whose products go past it would be clipped after the fix, where it was correct before. So these eight types now sum in F32. The q8_1 path always summed in integers and F32, so the fixed path handles values as large as before.
Test cases
ggml's tests (test-backend-ops) had no case that fails on this problem, so I added two kinds:
- Activations from 2048 to 4096, so that the sum of 32 goes past F16
- Activations from 512 to 1024 and weights from 0.5 to 1, so that the sums fit but the products go past F16
Each runs for Q4_0, Q5_0, Q4_K and Q5_K as a matrix-vector product, a small batch and a large batch. Q4_1 and Q5_1 are left out because the CPU they are compared with also quantizes their activations to q8_1 and returns -inf the same way.
test-backend-ops -b Vulkan0 (RTX 2080) |
Before | After |
|---|---|---|
| Added cases | 8 / 24 | 24 / 24 |
| All MUL_MAT cases | 1138 / 1154 | 1154 / 1154 |
| All MUL_MAT_ID cases | 937 / 937 | 937 / 937 |
With the fix, Qwen3-TTS synthesizes at Q5_K and Q4_K too, and its Q8_0 output is byte for byte the same as 0.8.3's.
Appendix B: why Metal's Tensor API stays off
On M5 and later chips, ggml's Metal backend computes matrix products with Metal 4's Tensor API. When I ported Irodori-TTS, I found that on the M5 this computation writes past the end of its output (speech.cpp #13). It happens when the number of output columns is 64 modulo 128, and turns the codec's 64-frame windows into noise.
So up to 0.8.3, speech.cpp set the environment variable GGML_METAL_TENSOR_DISABLE while it prepared the devices. But that changes the environment of any program embedding libspeech, and it is not safe while another thread reads the environment. Since I was forking ggml anyway, I tried fixing where it writes and using the Tensor API.
With the write fixed, 3 of speech.cpp's 25 Metal checks failed.
| Check (M5, F32) | Without the Tensor API | With the Tensor API |
|---|---|---|
| Irodori-TTS v4.1-Small, SNR of the synthesized audio against the official implementation | 8.7 to 62.5 dB | 2.3 to 48.3 dB |
| ReazonSpeech, 311 seconds of audio recognized with beam search | the same text as NeMo | a few characters differ |
Two runs of the same build give the same values, so this is not sampling noise. Even the check that runs the DiT once (109 cases) showed the median SNR dropping from 59.1 dB to 52.9 dB, and that difference piled up over 40 sampling steps. The cause is an argument ggml passes to the Tensor API's matrix product:
mpp::tensor_ops::matmul2d<
mpp::tensor_ops::matmul2d_descriptor(
NRB, NRA, static_cast<int>(dynamic_extent), false, true, true,
mpp::tensor_ops::matmul2d_descriptor::mode::multiply_accumulate),
execution_simdgroups<N_MM_SIMD_GROUP_X * N_MM_SIMD_GROUP_Y>> mm;
ggml-org/ggml v0.25.3: src/ggml-metal/kernels/mul_mm.metal
The sixth argument is relaxed_precision, and true allows a faster, less precise computation. Setting it to false passed all 25 checks, and Irodori-TTS's SNR became 14.0 to 64.8 dB, better than without the Tensor API. But now it was slower.
| M5, median | Without the Tensor API | Tensor API (relaxed_precision false) |
|---|---|---|
| Irodori-TTS MF, to the first audio | 0.251 s | 0.351 s |
| Irodori-TTS 16 steps, to the first audio | 1.239 s | 1.762 s |
| Qwen3-TTS 0.6B, to the first audio | 0.039 s | 0.072 s |
| Qwen3-ASR 0.6B, recognition | 0.123 s | 0.150 s |
| ReazonSpeech, recognition | 0.078 s | 0.107 s |
Every model got 22 to 85% slower. With a choice between less precision and less speed, the Tensor API is off by default. ggml already leaves it off by default on chips before the M5, and the fork extends that to every chip. speech.cpp no longer needs to set the environment variable, and the Mac computes exactly what 0.8.3 did.
Appendix C: the ggml fork
The fixes in Appendices A and B both change ggml's source. So speech.cpp's submodule now points at the speech.cpp branch of nyosegawa/ggml (#111).

A fork that drifts far from upstream becomes hard to update. To keep that from happening, the fork follows these rules:
- The branch is an upstream ggml tag, plus one commit of test cases, plus one commit for each fix
- Every fix comes with a test case that fails on its bug
- Moving to a new ggml tag starts with only the test-case commit on the new tag
- A test case that passes without its fix means upstream ggml has fixed the bug, and the fix is dropped
The Windows machine has no C++ compiler, so running CI with checks=true now also builds ggml's test-backend-ops.exe. Downloading and running it on Windows shows whether a fix is still needed.
Appendix D: why loading takes less memory
0.8.3 read each GGUF tensor into a std::vector and then sent it to the device. That buffer grew to the size of the largest tensor. In the Qwen3 models the largest is the text embedding, 331 MB in Qwen3-TTS and Qwen3-ASR 1.7B. 0.8.4 reads and sends 16 MB at a time (#105).
On Vulkan there is a second saving. ggml's Vulkan backend stages data in a temporary host buffer before writing it to the GPU, and that buffer stays at the size of the largest write until the process ends. Writing a 331 MB tensor at once leaves a 331 MB buffer behind; writing 16 MB at a time leaves 16 MB.
Appendix E: how it was measured
- Mac: Apple M5, macOS 26.2, Metal
- Windows: Windows 11, NVIDIA GeForce RTX 2080, Vulkan SDK 1.4.357.0
- Accuracy and memory of each type: speech-bench, 2026-10-12, M5
- Synthesis CER: the 20 sentences of speech-bench's
prompts/speak-ja-JP.json, seeds 1, 2 and 3- Qwen3-TTS used the speaker
ono_anna, and Irodori-TTS a voice file made from one reference recording - Transcribed with Qwen3-ASR 1.7B Q8_0
- Qwen3-TTS used the speaker
- Speed: synthesis is the median of the same 20 sentences, seed 1, three rounds. Recognition uses Common Voice's 4,479 utterances on the M5 and its first 100 (99 kept) on the RTX 2080; parakeet-v3 uses English FLEURS, 299 utterances on the M5 and 100 on the RTX 2080
- Memory: the peak memory footprint of one synthesis or recognition with
speech(macOS) - Q6_K, Q5_K and Q4_K quantize 256 values at a time, so a matrix whose rows are not a multiple of 256 stays Q8_0. That applies to Qwen3-ASR 0.6B's encoder (rows of 896) and to FastConformer's prediction network and joint (640)
References
- speech.cpp
- Models (Hugging Face)
- ggml
- ggml-org/ggml
- Massive Activations in Large Language Models
- ggml-org/llama.cpp #12135: Vulkan: Add DP4A MMQ and Q8_1 quantization shader
- ggml-org/llama.cpp #30105: vulkan: honor FP32 source precision in MUL_MAT_ID
- deepbeepmeep/kernels #4: MMQ returns NaN when a 32-activation block sum exceeds 65504 (CUDA)
- Measurement
- Related