You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Eval bug: Heavy nondeterminism in Qwen3 MoE (CUDA)Â #13280
llama-cli --version
ggml_cuda_init: GGML_CUDA_FORCE_MMQ: no
ggml_cuda_init: GGML_CUDA_FORCE_CUBLAS: no
ggml_cuda_init: found 2 CUDA devices:
Device 0: NVIDIA GeForce RTX 4060 Ti, compute capability 8.9, VMM: yes
Device 1: NVIDIA GeForce RTX 5060 Ti, compute capability 12.0, VMM: yes
version: 5269 (1d36b36)
built with cc (Debian 12.2.0-14) 12.2.0 for x86_64-linux-gnu
Operating systems
Linux
GGML backends
CUDA
Hardware
rtx 5060ti 16GB + rtx4060ti 16GB
Models
Qwen_Qwen3-30B-A3B-Q6_K.gguf by bartowski.
sha256sum: d511d02955714b08ff1b4354d6eae8ea513179a83fa5498466db2731528074dd
Problem description & steps to reproduce
I'm using a grammar to simulate the nothink qwen prompt format. Sometimes the output is generated correctly, sometimes the model outputs the wrong token while still aligned with the grammar.
Sometimes the model outputs the correct output, sometimes it outputs the wrong output and the following output breaks since the model cannot see the </think> token. I'm not restarting llama-server between tests and not changing the seed. I expect the model to always output the token 151668
Command line used to launch llama-server: /llama-server -ngl 175 -t 6 -c 32768 --host 0.0.0.0 -fa -ctk q8_0 -ctv q8_0 --slots -a current --temp 0.6
You can't use grammar to force a specific token, only a specific sequence of characters, if the model can complete that sequence with alternate tokens that's perfectly acceptable to the grammar.
This is a different problem. The output shouldn't be random when the seed is fixed and the temperature is zero.
Shouldn't, but is, at least with CUDA unfortunately.
If I let the model generate its output "naturally", the generated tokens are always the same at every run.
If I use the grammar to force the exact same output string, then the output tokens can change randomly, producing extremely low probability tokens.
Well, grammar will naturally skew the probabilities, I think you're just seeing the results of the numerical instability of CUDA more frequently due to the limited token selection.
<think> \n \n </think> when the output is generated correctly
<think> \n \n < when the generation is wrong. The model then goes out of distribution and generates low quality output.
The logprob of the 4th token is:
</think> : -22.50234603881836,
<: -23.995466232299805
Sometimes I get the wrong result 30 times in a row, sometimes I get the correct result 30 times in a row. With these settings it should be less than 1 in a billion chance ( 2^30) of being correct behavior.
EDIT: nevermind. I have to test with "cache_prompt": false
The log probabilities in Qwen-MoE (CUDA) vary wildly between -22 and -27, which is not expected. The inputs are always the same and the probability distribution should be always the same.
I might be wrong but I'm not expecting this behaviour. @JohannesGaessler Maybe you can confirm this?
Given the server parameters the output should to my knowledge be deterministic, even with CUDA. I have recently made quite a lot of changes to the MoE code. Unfortunately, as was pointed out to me in ggml-org/ggml#1178 (comment) , prior to my changes the results were already non-deterministic so I think a git bisect will be inconclusive.
Just to rule out the possibility of a hardware issue: do you get deterministic results after running nvidia-smi --lock-gpu-clocks 0,1000 --mode 1? I have a machine with multiple 4090s running off of a single 2050 W PSU and as it turns out even with just 3 of them running in parallel the power spikes can overlap in unlucky ways that either cause bit flips or system crashes.
Just to rule out the possibility of a hardware issue: do you get deterministic results after running nvidia-smi --lock-gpu-clocks 0,1000 --mode 1? I have a machine with multiple 4090s running off of a single 2050 W PSU and as it turns out even with just 3 of them running in parallel the power spikes can overlap in unlucky ways that either cause bit flips or system crashes.
commit 93c4e23 fixed the nondeterminism issue. Now I'm getting the same answer in each consecutive run. Nice!
I see some differences when I change the parameters. I don't know if it's an issue.
My launch command: llama-server -ngl 175 -t 6 -c 32768 --host 0.0.0.0 --slots -a current --temp 0.6 -m Qwen3-30B-A3B-Q6_K.gguf
Generally speaking it is expected that results will not be bit-for-bit identical if you vary some of the parameters. If different code is being run, then the floating point rounding error will be different (there are potentially other differences too). Such small differences can then blow up to comparatively larger differences in the outputs.
Activity
CISC commentedon May 3, 2025
You can't use grammar to force a specific token, only a specific sequence of characters, if the model can complete that sequence with alternate tokens that's perfectly acceptable to the grammar.
CISC commentedon May 3, 2025
If you are just trying to disable thinking you yourself have already implemented the means to do that, see #13212 (comment) :)
matteoserva commentedon May 3, 2025
This is a different problem. The output shouldn't be random when the seed is fixed and the temperature is zero.
If I let the model generate its output "naturally", the generated tokens are always the same at every run.
If I use the grammar to force the exact same output string, then the output tokens can change randomly, producing extremely low probability tokens.
CISC commentedon May 3, 2025
Shouldn't, but is, at least with CUDA unfortunately.
Well, grammar will naturally skew the probabilities, I think you're just seeing the results of the numerical instability of CUDA more frequently due to the limited token selection.
CISC commentedon May 3, 2025
I'll reopen the issue in case someone wants to take a closer look, but you might want to change the title to a more accurate description of the issue.
matteoserva commentedon May 3, 2025
I made some tests and I can provide more context. I used the following command to print the probabilities:
The 4 output tokens are
<think> \n \n </think>when the output is generated correctly<think> \n \n <when the generation is wrong. The model then goes out of distribution and generates low quality output.The logprob of the 4th token is:
</think>: -22.50234603881836,<: -23.995466232299805Sometimes I get the wrong result 30 times in a row, sometimes I get the correct result 30 times in a row. With these settings it should be less than 1 in a billion chance ( 2^30) of being correct behavior.EDIT: nevermind. I have to test with "cache_prompt": false
[-]Eval bug: grammar breaks Qwen3 MoE[/-][+]Eval bug: grammar breaks sampling in Qwen3 MoE[/+]matteoserva commentedon May 3, 2025
Ok. I am able to narrow down the problem even more with this python script:
This is the output of Qwen3-MoE for CPU debug:
This is the output of Qwen3-MoE for CUDA Release:
This is the output with Qwen3-0.6 (Dense), CUDA Release:
problem
The log probabilities in Qwen-MoE (CUDA) vary wildly between -22 and -27, which is not expected. The inputs are always the same and the probability distribution should be always the same.
I might be wrong but I'm not expecting this behaviour.
@JohannesGaessler Maybe you can confirm this?
JohannesGaessler commentedon May 3, 2025
Given the server parameters the output should to my knowledge be deterministic, even with CUDA. I have recently made quite a lot of changes to the MoE code. Unfortunately, as was pointed out to me in ggml-org/ggml#1178 (comment) , prior to my changes the results were already non-deterministic so I think a git bisect will be inconclusive.
Just to rule out the possibility of a hardware issue: do you get deterministic results after running
nvidia-smi --lock-gpu-clocks 0,1000 --mode 1? I have a machine with multiple 4090s running off of a single 2050 W PSU and as it turns out even with just 3 of them running in parallel the power spikes can overlap in unlucky ways that either cause bit flips or system crashes.matteoserva commentedon May 4, 2025
It doesn't seem to change anything
Qwen-moe with default settings:
Qwen-moe with
nvidia-smi --lock-gpu-clocks 0,1000 --mode 1Qwen 32b (dense) with
nvidia-smi --lock-gpu-clocks 0,1000 --mode 1[-]Eval bug: grammar breaks sampling in Qwen3 MoE[/-][+]Eval bug: Heavy nondeterminism in Qwen3 MoE (CUDA)[/+]JohannesGaessler commentedon May 4, 2025
Please check this fix: #13294 . There was a race condition in the new MMQ code that could be causing this.
matteoserva commentedon May 4, 2025
No change even after 9a0053f
Is there something (compiler flags, macros) that I could try to help narrow down the issue?
More tests I made:
-ngl 0or-ngl 1I get correct results-ngl 2and higher give slightly wrong results.-nglmakes the results worse and worse (worse as in higher standard deviation/ the probability assigned to that token becomes more random)JohannesGaessler commentedon May 4, 2025
Does
-ub 1fix the issue?Does this patch fix the issue?
matteoserva commentedon May 4, 2025
-ub 1I get correct and deterministic results-ngl 0I get wrong but deterministic results-ngl 99I get wrong and non deterministic resultsyour patchmerged with cuda-mmq-fix-race-condI get a crash
JohannesGaessler commentedon May 4, 2025
Potential fix: #13299
matteoserva commentedon May 4, 2025
commit 93c4e23 fixed the nondeterminism issue. Now I'm getting the same answer in each consecutive run. Nice!
I see some differences when I change the parameters. I don't know if it's an issue.
My launch command:
llama-server -ngl 175 -t 6 -c 32768 --host 0.0.0.0 --slots -a current --temp 0.6 -m Qwen3-30B-A3B-Q6_K.ggufTesting with the python script I posted.
-ub 1-fa-fa -ub 1JohannesGaessler commentedon May 4, 2025
Generally speaking it is expected that results will not be bit-for-bit identical if you vary some of the parameters. If different code is being run, then the floating point rounding error will be different (there are potentially other differences too). Such small differences can then blow up to comparatively larger differences in the outputs.
matteoserva commentedon May 4, 2025
Well. The issue is solved, then.
Thanks for the quick fix and update!