Skip to content

docs: qwen4exp results, an upstream-sync warning, and a caveat on "bit-identical" - #10

Open
cpuchip wants to merge 2 commits into
thecodacus:perffrom
cpuchip:threadchip/moe-cache-qwen4exp-notes
Open

cpuchip wants to merge 2 commits into
thecodacus:perffrom
cpuchip:threadchip/moe-cache-qwen4exp-notes

Conversation

@cpuchip

@cpuchip cpuchip commented Aug 27, 2026

Copy link
Copy Markdown

Ran your expert cache on Qwen3.8-Flash-Next (qwen4exp, 177B, 512 experts/layer, 10+1 active) on a single RTX 3090 — five cherry-picks onto ggml-org PR ggml-org#27742 and it worked. Three things a downstream reader of the guide would want, all docs-only.

1. A collision waiting on your next upstream sync. ggml-org ebb546b7e (ggml-org#26802, 2026-08-11) adds ggml_cuda_mul_mat_id_needs_sync() and asserts it at the single mul_mat_id caller. Your op_params[0] = 1 correctly disqualifies both fast paths, so the op reaches the sync path — but the new predicate predates the flag and answers "no sync needed" for a small quantized batch. First decode, every time:

ggml-cuda.cu:1948: GGML_ASSERT(ggml_cuda_mul_mat_id_needs_sync(dst, cc)) failed

Two lines fix it, on the branch linked in the README text. Not sent as a code PR because perf doesn't carry needs_sync yet — there's nothing for the patch to apply to. Ready whenever you take the sync.

2. A caveat on "bit-identical". On qwen4exp the cached output is not bit-identical — it diverges from baseline at temperature 0, coherent and on-topic, consistent with float non-associativity between one fused chain and two summed pack chains. Quality is unaffected as far as a proper test can tell: paired over the same 64 chunks, ΔPPL +0.047% (t = +0.88), below that test's own 0.107% detection floor, with the cached arm's peak VRAM confirming it engaged. Suggesting statistically indistinguishable rather than bit-identical for architectures beyond the three you measured — your claim may well hold exactly on those.

3. The silent no-op, added to your troubleshooting table: --moe-cache-slots without --moe-cache-profile does nothing, reports clean, and reads as a small regression in tok/s. VRAM is the only tell — it doesn't move a megabyte. Cost us an evening.

The numbers

arm VRAM decode
--n-cpu-moe 48, no cache 6,284 MiB 16.00 tok/s
--n-cpu-moe 48 + --moe-cache-slots 64 + profile 15,522 MiB 21.52 tok/s (+34.5%)
--n-cpu-moe 40 (whole layers on GPU instead) 18,784 MiB 17.63 tok/s (+10%)

The comparison we found most useful: moving whole layers onto the card spent 12.5 GB to buy 10%, the cache spent 9.2 GB to buy 34.5%. Oracle hit rates from llama-moe-trace + your simulate.py: 68.2% at 64 slots/layer, 88.0% at 128 (which OOMs on 24 GB).

We went in expecting the routing to be too flat for a cache to help — 512 fine-grained experts with load balancing look designed against one, and Laguna measured barely-skewed. It isn't: only 51.5% of (layer, expert) pairs are ever used.

Falsifier on all of the above: one card, one model, one quant (unsloth UD-Q4_K_XL), routing profile traced from a single prompt. Happy to adjust or drop any of it.

… caveat

Ran the expert cache on Qwen3.8-Flash-Next (qwen4exp, 177B, 512 experts/layer) on a
single RTX 3090: +34.5% decode for 9.2 GB, where moving whole layers with
--n-cpu-moe instead spent 12.5 GB to buy 10%.

Three things a downstream user would want in the guide:

1. After syncing past ggml-org ebb546b (ggml-org#26802), the pack chains trip
   GGML_ASSERT(ggml_cuda_mul_mat_id_needs_sync) on the first decode. op_params[0]=1
   correctly disqualifies both fast paths, but the new predicate predates the flag
   and answers 'no sync needed' for a small quantized batch. Two-line fix included;
   not a code PR because this branch has no needs_sync to patch.

2. On qwen4exp the output is NOT bit-identical to baseline -- it diverges at
   temperature 0, consistent with float non-associativity between one fused chain
   and two summed pack chains. Quality is unaffected as far as a proper test can
   see: paired over 64 chunks, dPPL +0.047% (t=+0.88) against that test's own
   0.107% detection floor.

3. --moe-cache-slots without --moe-cache-profile is SILENT. Added to the
   troubleshooting table: tok/s reads as a small regression and VRAM is the only
   tell.
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Aug 27, 2026
@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 80dc3ce7-2c6f-42f5-8f5d-a63646fc4ae5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

The first draft cited only Pride and Prejudice, and that corpus is a poor
discriminator: baseline PPL 1.0594 means the model is near-certain of every token,
so there is little room for a defect to show. Re-ran the whole comparison on
technical prose (NASA SP-4205 OCR, baseline PPL 8.2438).

  NASA    cache-64 vs baseline  -0.047%  t -0.85  floor 0.112%
  Austen  cache-64 vs baseline  +0.113%  t +1.68  floor 0.107%

Neither detectable, and the SIGN FLIPS between corpora -- a real quality cost would
keep its sign. Both rows shown rather than only the favourable one.
@cpuchip

cpuchip commented Aug 27, 2026

Copy link
Copy Markdown
Author

Updated the quality evidence — the first version cited only Pride and Prejudice, and that corpus turned out to be a poor discriminator: baseline PPL 1.0594 means the model is near-certain of every token, which we read as memorisation rather than a usable test. Re-ran the whole comparison on technical prose the model has not swallowed (NASA SP-4205 OCR, baseline PPL 8.2438):

corpus baseline PPL cache-64 ΔPPL t detection floor
NASA SP-4205 OCR 8.2438 −0.047% −0.85 0.112%
Pride and Prejudice 1.0594 +0.113% +1.68 0.107%

64 paired chunks each, cached arm's peak VRAM 15,544 MiB against 6,286 for cache-off so it provably engaged. Neither delta is detectable — and the sign flips between corpora, which a real quality cost would not do. Both rows are in the diff rather than only the favourable one.

So the claim I would stand behind for qwen4exp: +34.5% decode for 9.2 GB, at no measurable quality cost, with the effect bounded under ~0.11% PPL. Still not bit-identical, which is the wording note in the PR.

One near-miss worth passing on, since anyone comparing perplexity runs can hit it: mid-run I read the cached arm at chunk 38 (cumulative 9.29) against the other arms' final values (8.24) and it looked 12.7% worse. Cumulative perplexity is not comparable across different chunk counts. At matched indices the cached arm was the lowest of the three at every checkpoint.

@ql0wn4

ql0wn4 commented Sep 17, 2026

Copy link
Copy Markdown

Ran your expert cache on Qwen3.8-Flash-Next (qwen4exp, 177B, 512 experts/layer, 10+1 active) on a single RTX 3090 — five cherry-picks onto ggml-org PR ggml-org#27742 and it worked. Three things a downstream reader of the guide would want, all docs-only.

1. A collision waiting on your next upstream sync. ggml-org ebb546b7e (ggml-org#26802, 2026-08-11) adds ggml_cuda_mul_mat_id_needs_sync() and asserts it at the single mul_mat_id caller. Your op_params[0] = 1 correctly disqualifies both fast paths, so the op reaches the sync path — but the new predicate predates the flag and answers "no sync needed" for a small quantized batch. First decode, every time:

ggml-cuda.cu:1948: GGML_ASSERT(ggml_cuda_mul_mat_id_needs_sync(dst, cc)) failed

Two lines fix it, on the branch linked in the README text. Not sent as a code PR because perf doesn't carry needs_sync yet — there's nothing for the patch to apply to. Ready whenever you take the sync.

2. A caveat on "bit-identical". On qwen4exp the cached output is not bit-identical — it diverges from baseline at temperature 0, coherent and on-topic, consistent with float non-associativity between one fused chain and two summed pack chains. Quality is unaffected as far as a proper test can tell: paired over the same 64 chunks, ΔPPL +0.047% (t = +0.88), below that test's own 0.107% detection floor, with the cached arm's peak VRAM confirming it engaged. Suggesting statistically indistinguishable rather than bit-identical for architectures beyond the three you measured — your claim may well hold exactly on those.

3. The silent no-op, added to your troubleshooting table: --moe-cache-slots without --moe-cache-profile does nothing, reports clean, and reads as a small regression in tok/s. VRAM is the only tell — it doesn't move a megabyte. Cost us an evening.

The numbers

arm VRAM decode
--n-cpu-moe 48, no cache 6,284 MiB 16.00 tok/s
--n-cpu-moe 48 + --moe-cache-slots 64 + profile 15,522 MiB 21.52 tok/s (+34.5%)
--n-cpu-moe 40 (whole layers on GPU instead) 18,784 MiB 17.63 tok/s (+10%)
The comparison we found most useful: moving whole layers onto the card spent 12.5 GB to buy 10%, the cache spent 9.2 GB to buy 34.5%. Oracle hit rates from llama-moe-trace + your simulate.py: 68.2% at 64 slots/layer, 88.0% at 128 (which OOMs on 24 GB).

We went in expecting the routing to be too flat for a cache to help — 512 fine-grained experts with load balancing look designed against one, and Laguna measured barely-skewed. It isn't: only 51.5% of (layer, expert) pairs are ever used.

Falsifier on all of the above: one card, one model, one quant (unsloth UD-Q4_K_XL), routing profile traced from a single prompt. Happy to adjust or drop any of it.

Hey, what fork did you use, GenerelSchwerz or thecodacus?

I’ve been digging into your Qwen3.8-Flash-Next MoE-cache results from PR #10 and trying to reproduce the behavior on my side.

Your 3090 result was:

RTX 3090 24 GB
Ryzen 5600X
64 GB RAM
Qwen3.8-Flash-Next, qwen4exp
No cache: 16.00 tok/s
64-slot cache: 21.52 tok/s (+34.5%)
Cache consumed about 9.2 GB additional VRAM
You measured ~68.2% cache hit rate at 64 slots

My setup is very similar on the CPU/RAM side, but I’m using an RTX 3080 Ti 12 GB:

Ryzen 5600X
64 GB RAM
Qwen3.8-Flash-Next IQ3_XXS
Same general -ngl 99 -ncmoe 99 -fa 1 setup

I first had trouble figuring out whether the cache was actually working. I instrumented init_moe_expert_cache() and confirmed that it is definitely active:

48/48 layers eligible
8 slots → ~834 MiB cache
32 slots → ~3.34 GB cache
Cache initialization succeeds and uploads to CUDA

But my performance goes in the opposite direction:

Cache OFF: ~9.88 tok/s
8 slots: ~7.78 tok/s
16 slots: ~8.02 tok/s
32 slots: ~8.76 tok/s
56 slots: ~8.52 tok/s

I also tested the two CUDA options independently:

GGML_CUDA_REGISTER_HOST=1
GGML_SCHED_PREFETCH_EXPERTS=1

and neither made a meaningful difference. At 32 slots I got roughly 8.0–8.2 tok/s regardless of those settings.
So I’m trying to understand what explains the huge discrepancy between your 3090 result and mine.
The CPU and RAM are essentially the same, the model architecture is the same, and the cache is definitely being populated on my side.
The obvious difference is GPU/VRAM — 24 GB on your 3090 versus 12 GB on my 3080 Ti — but I’m not sure VRAM capacity alone explains it, because even an 8-slot cache only uses ~834 MiB and still hurts decode.
Could you help me understand what you think is happening?

In particular:
Did you measure the cache hit rate for your 64-slot run directly from the actual workload/profile, or was the 68.2% figure from the simulator?
What was your actual VRAM usage during the 64-slot benchmark, and how much VRAM was left for KV/cache/compute buffers?
Do you think the difference could be memory bandwidth / GPU scheduling rather than simply VRAM capacity?
Was your 3090 benchmark using the same IQ3_XXS quant, or a different quant? I noticed PR #10 says the reported 3090 experiment used UD-Q4_K_XL.
My curve is basically “more slots helps the cache, but never enough to beat no-cache.”
I’m not trying to prove the cache is broken — quite the opposite.
The instrumentation shows that it works.
I’m trying to understand why the same cache mechanism gives you +34.5% on a 3090 but gives me a ~10–20% decode penalty on a 12 GB card.
Your thoughts on where the bottleneck is would be really useful.

Kind Regards

@cpuchip

cpuchip commented Sep 17, 2026

Copy link
Copy Markdown
Author

Thank you for this — instrumenting init_moe_expert_cache() before asking, and reporting "the cache is definitely active and definitely slower", is a far more useful report than a bug. I think I can explain it, and most of the explanation is our fault.

First: our host, which the PR never named

You wrote our result as Ryzen 5600X / 64 GB RAM. That's your box. Ours:

yours ours
GPU RTX 3080 Ti, 12 GB RTX 3090, 24 GB
CPU Ryzen 5600X, 6c/12t Threadripper PRO 3975WX, 32c/64t
RAM 64 GB 160 GiB installed, 152.8 GiB usable
quant UD-IQ3_XXS (76.3 GiB) UD-Q4_K_XL (103.7 GiB)

The PR says only "on a single RTX 3090" and never named the host, so you had no way to know. That omission is on us, and it's the reason the comparison looked like apples to apples.

Second: the thing I think actually decides it

A quarter of this model isn't experts at all. From our file:

per_layer_token_embd   [160, 320001536]   IQ4_NL   26.82 GiB

That's the PLE n-gram table — 51.2B parameters (160 × 320,001,536), 16 head vocabs of ~20M each, addressed by a hash of the last three tokens. It lives inside the GGUF shards, and it's 25.9% of our 103.7 GiB.

It behaves nothing like the expert weights:

  • Experts — 10+1 of 512 per layer, large contiguous blocks. This is what --moe-cache-slots targets.
  • The n-gram table — a gather of 16 rows × 160 values, about 2.7 KB per token, once per forward pass, scattered across 27 GB.

So the cache you're tuning cannot touch the n-gram path at all. Worse, uploading ~3.3 GB of experts at init pulls pages through the page cache and can evict exactly the n-gram rows that were warm — which fits the shape you measured, where the penalty appears immediately at 8 slots (9.88 → 7.78) rather than scaling with cache size the way pure VRAM pressure would.

And on a 64 GB box the table cannot be resident alongside everything else. Worth stating plainly: no quant Unsloth publishes for this model fits in 64 GB — the smallest, UD-IQ1_S, is 67.6 GiB. On our box the whole 103.7 GiB sits in page cache with ~49 GiB to spare. Those are not the same experiment, and our +34.5% is partly a measurement of our RAM.

What I'd actually try on your hardware

You are roughly the twin of the box in this discussion — RTX 3080 Ti + 64 GB + NVMe. The approach there deliberately puts the n-gram table on the SSD and keeps prefetch off, because 2.7 KB per token is nothing for an NVMe once the kernel stops reading ahead around it:

-ngl all \
-ot "per_layer_token_embd=CPU,blk\.([6-9]|1[0-9]|2[0-9]|3[0-9]|4[0-6])\.ffn_.*=CPU" \
-lm mmap --no-prefetch \
--ram-tensors "blk\.([6-9]|1[0-9]|2[0-9]|3[0-9]|4[0-6])\.ffn_"

Three tiers: VRAM for active experts and KV, RAM for inactive expert layers, NVMe for the n-gram table. Reported there as +344% prefill and +167% generation over plain mmap, at 8–10 tok/s generation — which is already around where your cache-off number sits, so I'd expect the headroom on your box to be in prefill.

--no-prefetch and --ram-tensors are from dandandelion's fork; neither is in our branch or in upstream, and I think that gap matters more for you than any cache tuning. Stock llama.cpp maps with MAP_POPULATE and POSIX_FADV_SEQUENTIAL, which is right for bulk weights and wrong for a scattered row-gather table.

A one-minute check before any of that: run your 32-slot arm and watch vmstat 1 (the bi column) during decode, after the prompt is in. Sustained reads while generating means you're storage-bound and the cache isn't the thing to tune.

Your four questions, straight

  1. Fork: ours — cpuchip/llama.cpp, branch threadchip/qwen4exp-moecache. thecodacus's cache work (feat: MoE expert cache — keep hot routed experts resident in VRAM #5, feat: overlap CPU cold-expert and GPU hot-expert computation in the MoE cache #9) cherry-picked onto ggml-org PR model: add Qwen3.8-Flash-Next (qwen4exp) ggml-org/llama.cpp#27742, plus the qwen4exp graph wiring, the llama-graph conflict resolved as a union, the expert prefetch/pinning commits, and the two-line mul_mat_id needs_sync fix this PR's point 1 is about. That last one will bite you directly if your tree carries ggml-org ebb546b7e — you'll hit the GGML_ASSERT(ggml_cuda_mul_mat_id_needs_sync(...)) abort without it.

  2. Hit rate — simulator, not live, and I should have led with that. 68.2% at 64 slots and 88.0% at 128 are oracle figures from llama-moe-trace plus simulate.py, over a routing profile traced from a single prompt. Not a counter read during the benchmark. Treat them as an upper bound for that one prompt's routing.

  3. VRAM: 6,284 MiB with no cache, 15,522 MiB at 64 slots — the cache itself was ~9.2 GB, leaving roughly 9 GB free on a 24 GB card for KV, compute buffers and fragmentation. 128 slots OOMed even for us. On 12 GB, a 3.34 GB cache leaves very little.

  4. Bandwidth or capacity: I don't think it's really about the GPU. My order of suspicion is host-side residency of the n-gram table first, VRAM headroom on a 12 GB card second, and IQ3_XXS dequant throughput on CUDA third — the cache's premise is "compute this expert on the GPU instead of the CPU", and that trade is worth less when the GPU path is a slower quant format and your CPU has a fifth of the threads ours does.

And yes, the quant differs, as you spotted — our falsifier says one card, one model, one quant (UD-Q4_K_XL), single-prompt routing profile. You've now added a second card, a second quant and a second host to that picture, and the honest summary is that our headline doesn't transfer to a 12 GB / 64 GB box. That's worth more than a confirmation would have been.

(Aside, if you ever have the VRAM for it: SGLang has day-0 support for this model and handles the n-gram table properly — pinned host memory with async prefetch overlapped with compute, gathered via a Triton UVA kernel, rather than leaning on the page cache. vLLM has VLLM_PLE_CPU_OFFLOAD=1, though its PLE-offload PR is paused pending a UVA implementation. Both assume you can hold the rest of a 177B model in VRAM, so neither helps on our cards — but it's the right design, and worth knowing it exists.)

@ql0wn4

ql0wn4 commented Sep 17, 2026

Copy link
Copy Markdown

Thank you very much for the deep analysis and for taking the time to look into this so thoroughly. It’s been really helpful.

In your opinion, do you think the performance results reported by Codacus are realistically within reach on the same hardware (RTX 3080ti 12GB), or do you think there is a fundamental hardware limitation that would make those numbers unrealistic?

At the moment I’m getting around 11–12 tokens/sec, depending on the task. I’m mainly asking because I’d like to know whether it’s worth investing more time into trying to squeeze significantly more performance out of this hardware, or whether I’m already reasonably close to its practical limits.

Thanks again!

@cpuchip

cpuchip commented Sep 18, 2026

Copy link
Copy Markdown
Author

Short answer: I don't think 21.5 tok/s is reachable on a 12 GB card, and I think you're closer to its practical limit than not. But the reason is one specific number, and there's one cheap thing worth checking before you stop.

First, the caveat that should colour everything below: we have no hardware resembling yours. No 12 GB card, no 64 GB host. Everything I say about your configuration is extrapolation from a machine with twice the VRAM and 2.4× the RAM, and I've been wrong twice already in this thread by reasoning past what I'd actually measured.

What I measured today, on our box

I re-ran the PR's own pair on a current build, plus the SSD-offload approach I pointed you at last time, all with one client and 128-token greedy generations:

config decode VRAM
--n-cpu-moe 48, no cache 16.10 tok/s 6,658 MiB
--n-cpu-moe 48 + --moe-cache-slots 64 + profile 22.47 tok/s 15,896 MiB
the SSD/hybrid offload route (-ot per_layer_token_embd=CPU + expert regex) 14.20 tok/s 17,716 MiB
same + dandelion's --no-prefetch --ram-tensors 15.54 tok/s 17,716 MiB

The PR's numbers reproduce (16.00 → 16.10, 21.52 → 22.47), so that part is solid.

The number that decides your question

The winning configuration used 15,896 MiB of VRAM — more than your card has in total.

The +39.6% is the expert cache, and the cache is the VRAM. At 64 slots it costs ~9.2 GB on top of the ~6.6 GB the model needs. You measured 3.34 GB at 32 slots yourself, which lines up. On 12 GB, after weights, KV and compute buffers, you simply cannot hold the cache that produced that number.

So it isn't a tuning gap — the configuration that gets 21.5 doesn't fit on your card.

And the other two tiers are also against you

Your GPU is not the problem, which surprised me: the 3080 Ti has ~97.6% of the 3090's CUDA cores and within ~3% of its memory bandwidth. It is essentially a 3090 with half the VRAM. Per-expert GPU compute on your card is as fast as ours.

What differs is everything below the GPU. Measured on our host:

GPU VRAM      ~936 GB/s        1x
host RAM        69.0 GB/s     13.6x slower   (8-channel; yours is dual-channel, likely 1.5-2x slower again)
PCIe H2D        24.9 GB/s     37.6x slower
NVMe           ~3-7 GB/s     ~150-300x slower

And the one that I think actually caps you: UD-IQ3_XXS is 76.3 GiB against ~59.6 GiB usable on a 64 GB box. The model cannot be resident, so a share of every token's expert reads comes off the bottom tier. No quant Unsloth publishes fits — the smallest, UD-IQ1_S, is 67.6 GiB.

Worth knowing: our two SSD-offload runs above never actually touched the SSD — the whole 103.7 GiB sat in page cache (105 GiB cached, confirmed in the logs). So 14–15 tok/s is that technique with disk latency removed entirely. It is a ceiling you won't reach, not a target.

The one cheap thing worth checking first

Confirm --moe-cache-profile is on your command line, not just --moe-cache-slots. Slots without a profile is a documented silent no-op that reads as a small regression, which is the exact shape of your original curve. Your VRAM did move (834 MiB at 8 slots), and by our own troubleshooting note that means it engaged — so this is probably fine. It costs one line to verify and it's the only remaining free win I can see.

What I'd actually do in your position

You've gone 9.88 → 11–12 tok/s, which is real. My honest guess is that the ceiling on that machine is mid-teens, not low-twenties, and that further cache tuning has little left to give because the cache is VRAM-bound.

If you want a step change, the upgrade that matters is RAM, not the GPU. Going to 128 GB would put the whole model in page cache and take the bottom tier out of the loop entirely — which is the single biggest difference between your box and ours, and it's the cheaper half of your machine. A bigger card would help too, but you'd be replacing a GPU that is already ~97% of ours.

I'd stop optimising and either accept mid-teens or add RAM. Thanks for pushing on this — the comparison forced us to measure four configurations we'd never have run otherwise, and the finding that the hybrid/SSD route is worse than plain --n-cpu-moe on a RAM-rich box is not something we knew yesterday.

@cpuchip

cpuchip commented Sep 18, 2026

Copy link
Copy Markdown
Author

Follow-up, because the weakest part of my last answer was that we had no card like yours — so we simulated one.

We held 12,800 MiB of the 3090 with a ballast process, leaving 11,055 MiB free, and re-ran the same config on the same host. A ballast rather than just configuring fewer slots, deliberately: fewer slots shows what a small cache costs, a ballast shows what happens when the allocator genuinely cannot get the memory. That's your card rather than your config.

slots result llama's VRAM
32 failed to load
24 17.97 tok/s ~10.4 GB
16 17.02 tok/s ~9.3 GB

Everything else identical to the 22.47 run. So the VRAM variable is now isolated:

our best, 24 GB card           22.47 tok/s
same host, card capped ~11 GB  17.97 tok/s   <- VRAM alone costs 20.0%
your box (your figure)          ~11.5 tok/s  <- the host costs a further 36.0%
                                                total gap 48.8%

About 41% of the gap is the card and 59% is everything below it — dual-channel RAM, six cores, and a 76.3 GiB model that cannot be resident in 64 GB.

The practical consequence, which I think is what you're actually weighing: a 24 GB card on its own would take you to roughly 14.4 tok/s, not 22. The host stays the larger term. And the mid-teens ceiling I guessed at last time is what we measured — 17.97 — on a host with 8-channel memory, 32 cores, and the whole model in page cache. You won't exceed that on a machine that pages from SSD.

Two caveats, both of which cut in your favour:

  • Your UD-IQ3_XXS has smaller experts than our UD-Q4_K_XL — you measured 3.34 GB at 32 slots where we pay considerably more. You may fit more slots than our 24, so treat 17.97 as an upper bound for your card on our host, not a prediction of your machine.
  • The ~11.5 is your own "depending on the task" figure, not something we measured.

So: if you want a step change it's RAM, and if you don't want to spend anything, you're nearer the practical limit than not. Either way the cache is worth keeping on — it's the single largest effect we measured anywhere in this thread (+39.6%), it's just VRAM-bound on 12 GB.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants