llama-hot-experts: pin hottest MoE experts in RAM via --pin-hot-experts - #26414
llama-hot-experts: pin hottest MoE experts in RAM via --pin-hot-experts#26414Ghimli wants to merge 1 commit into
Conversation
Problem: Large MoE models loaded via mmap suffer from OS page cache eviction of infrequently accessed experts, causing severe latency spikes when those experts are needed later. Solution: --pin-hot-experts N dynamically tracks expert usage at runtime and uses mlock() to pin the top-N most frequently used experts in RAM, preventing OS eviction. Cold experts remain paged normally. Dense parts are mlocked automatically: Before any hot experts are pinned, all dense (non-MoE-expert) tensors that reside in host memory are mlocked in place. Dense parts (embeddings, attention/FFN weights, RMSNorm, output projection, router weights, etc.) are used on every single token — they are the hottest data by definition. This happens unconditionally when --pin-hot-experts is enabled and mlock is supported, consuming the global budget first so that hot experts only ever get the leftover budget. Key features: - Real-time tracking via tensor callback on ffn_moe_topk tensors - On-the-fly eviction/replacement of cold experts with hot ones - Budget cap via --pin-hot-experts-budget-mib - Fail-safe rollback on mlock failure - Per-layer stats reporting at --pin-hot-experts-stats-interval N - New load mode --load-mode mmap+pin (mmap without global mlock) CLI arguments: --pin-hot-experts <n> Number of hot experts to pin (0=off) --pin-hot-experts-budget-mib <n> Max pinned memory in MiB (0=unlimited) --pin-hot-experts-stats-interval N Print stats every N tokens --load-mode mmap+pin mmap without global mlock Naming convention: C API: underscores (n_pin_hot_experts) CLI: hyphens (--pin-hot-experts)
|
Hi @Ghimli, thanks for your contribution! Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:
Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below. |
|
@ggml-gh-bot Resolved. Please mark it with a "feature" label dear Bot :). |
|
Quoting myself from the previous pr (why new pr??):
So something like mmap+hot or mmap+lockhot |
|
@Green-Sky Changed the name of underlying and previous PR closed itself. I couldn't reopen. |
|
Does this change influence experts in CPU RAM only? I have 24 GB GPU and lets say that dense + full context takes 14 GB so I have 10 GB VRAM left. I could just use -cmoe to have all experts on CPU RAM + SSD (if experts size > RAM) or get manually a few experts into VRAM with -ncmoe. If there would be a way to have the hot experts first loaded into remaining VRAM then RAM it would be great. Also, if you could provide explanation how this change would interact wit things like -ngl or -fit options I would appreciate. |
|
@PmNz8 Yes RAM only. I already tried several times to do that, but each time i only got lower token processing speed. With RAM, weights are already there, just need protective malloc. With VRAM->RAM you need to transfer a lot of data when expert become hot or cold and it it just too expensive to do. Which expert is hot is dynamic and task dependent. As of second it just optimizes experts which are in RAM and you can't mlock them all. |
|
It does not seem to play nice with no-warmup |
|
At least on my system (Intel 270K + 5090) mmap is quite slow, even if the whole model fits into RAM and is mlocked. So an approach avoiding mmap would be more promising (#25294 ? or https://github.com/Lidenburg/llama.cpp) |
|
Windows 11, gemma-4-26b-a4b, tried a bunch of different configurations of this, but it seemed to use the same amount of system ram no matter what I did and spammed 'failed to VirtualUnlock buffer: The segment is already unlocked.' |
|
It seems memory locking is failing silently somehow. I'm on vacation right
now. I will fix that when I come back.
wt., 4 sie 2026, 02:25 użytkownik Midaychi ***@***.***>
napisał:
… *Midaychi* left a comment (ggml-org/llama.cpp#26414)
<#26414 (comment)>
Windows 11, gemma-4-26b-a4b, tried a bunch of different configurations of
this, but it seemed to use the same amount of system ram no matter what I
did and spammed 'failed to VirtualUnlock buffer: The segment is already
unlocked.'
Maybe I'm using it wrong?
I mean I had plenty of ram to load all the experts I was just trying to
test if it had an actual effect
—
Reply to this email directly, view it on GitHub
<#26414?email_source=notifications&email_token=ABU4MNXNKI6J6QYRAFSGMA35IEUOTA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJXGMYTMNJVGUY2M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5173165551>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABU4MNUXTWSHTODSHMFLFYT5IEUOTAVCNFSNUABFKJSXA33TNF2G64TZHM3DCMRTGU2DOOBUHNEXG43VMU5TKMBTHA4TEMZXGYY2C5QC>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/ABU4MNSCKTSEB5MEU5APMZT5IEUOTA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJXGMYTMNJVGUY2M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y>
and Android
<https://github.com/notifications/mobile/android/ABU4MNQTFTNRN246QWTQIM35IEUOTA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJXGMYTMNJVGUY2M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
Download it today!
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
|
I gave it a try today - in combination with #24524 . I ran DeepSeek 0731 Q4_K_XL on 32 GB VRAM + 128 GB RAM on Ubuntu 26.04. Issues observed:
|
|
You should get some improvements in pp. Sometimes when model is almost
fitting just mmap is enough and there are no disk io operation. Observe
iotop when using vanilla if no IO or almost none you are as good as full
mlock and your limits are RAM speed and cpu matmul operations. The same
when getting almost 100 proc CPU usage that means even nvme speed in enough
and you are just CPU limited.
niedz., 9 sie 2026, 14:22 użytkownik xashr ***@***.***>
napisał:
… *xashr* left a comment (ggml-org/llama.cpp#26414)
<#26414 (comment)>
I gave it a try today - in combination with #24524
<#24524> . I ran DeepSeek 0731
Q4_K_XL on 32 GB VRAM + 128 GB RAM on Ubuntu 26.04.
Issues observed:
- Running with mlock requires changing the system config
/etc/security/limits.conf as the mlock max default is 8 MB. So it
won't work out of the box, unfortunately.
- There is/was a bug in llama-model-loader.cpp where load_mode ==
LLAMA_LOAD_MODE_MMAP_PIN is missing in this->use_mmap = load_mode ==
LLAMA_LOAD_MODE_MMAP || load_mode == LLAMA_LOAD_MODE_MMAP_MLOCK ||
load_mode == LLAMA_LOAD_MODE_MMAP_PIN; => In my case this resulted in
llama.cpp trying to put the whole model into CUDA memory. Had to fix that.
- After that it was working, but there was not real performance
improvement ( I was hoping to see some improvements for PP)
—
Reply to this email directly, view it on GitHub
<#26414?email_source=notifications&email_token=ABU4MNTMONHND7Z7Y2WGR6L5JBUI7A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMRTGE2DSNZQGIYKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5231497020>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABU4MNU33US7XY4DVUX7IGL5JBUI7AVCNFSNUABFKJSXA33TNF2G64TZHM3DCMRTGU2DOOBUHNEXG43VMU5TKMBTHA4TEMZXGYY2C5QC>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/ABU4MNSJH4F47WFFQUCOVCD5JBUI7A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMRTGE2DSNZQGIYKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y>
and Android
<https://github.com/notifications/mobile/android/ABU4MNXQL6S6ZWAQAB4NFSL5JBUI7A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMRTGE2DSNZQGIYKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
Download it today!
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
|
I also noticed typical benchmarks are very poor to measure this kind of
improvements. They tend to have almost static heatmap of MOE experts. Even
VRAM->RAM hot experts swapping looks good on benchmarks. While real agentic
operations are actually slower due to experts heatmaps being more dynamic.
niedz., 9 sie 2026, 14:36 użytkownik Damian O ***@***.***>
napisał:
… You should get some improvements in pp. Sometimes when model is almost
fitting just mmap is enough and there are no disk io operation. Observe
iotop when using vanilla if no IO or almost none you are as good as full
mlock and your limits are RAM speed and cpu matmul operations. The same
when getting almost 100 proc CPU usage that means even nvme speed in enough
and you are just CPU limited.
niedz., 9 sie 2026, 14:22 użytkownik xashr ***@***.***>
napisał:
> *xashr* left a comment (ggml-org/llama.cpp#26414)
> <#26414 (comment)>
>
> I gave it a try today - in combination with #24524
> <#24524> . I ran DeepSeek 0731
> Q4_K_XL on 32 GB VRAM + 128 GB RAM on Ubuntu 26.04.
>
> Issues observed:
>
> - Running with mlock requires changing the system config
> /etc/security/limits.conf as the mlock max default is 8 MB. So it
> won't work out of the box, unfortunately.
> - There is/was a bug in llama-model-loader.cpp where load_mode ==
> LLAMA_LOAD_MODE_MMAP_PIN is missing in this->use_mmap = load_mode ==
> LLAMA_LOAD_MODE_MMAP || load_mode == LLAMA_LOAD_MODE_MMAP_MLOCK ||
> load_mode == LLAMA_LOAD_MODE_MMAP_PIN; => In my case this resulted in
> llama.cpp trying to put the whole model into CUDA memory. Had to fix that.
> - After that it was working, but there was not real performance
> improvement ( I was hoping to see some improvements for PP)
>
> —
> Reply to this email directly, view it on GitHub
> <#26414?email_source=notifications&email_token=ABU4MNTMONHND7Z7Y2WGR6L5JBUI7A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMRTGE2DSNZQGIYKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5231497020>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABU4MNU33US7XY4DVUX7IGL5JBUI7AVCNFSNUABFKJSXA33TNF2G64TZHM3DCMRTGU2DOOBUHNEXG43VMU5TKMBTHA4TEMZXGYY2C5QC>
> .
> Triage notifications, keep track of coding agent tasks and review pull
> requests on the go with GitHub Mobile for iOS
> <https://github.com/notifications/mobile/ios/ABU4MNSJH4F47WFFQUCOVCD5JBUI7A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMRTGE2DSNZQGIYKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y>
> and Android
> <https://github.com/notifications/mobile/android/ABU4MNXQL6S6ZWAQAB4NFSL5JBUI7A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMRTGE2DSNZQGIYKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
> Download it today!
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>
|
|
@xashr And you can ramp up pp alone almost indefinitely by just playing with --batch-size --ubatch-size settings, especially ubatch at the expense of VRAM/RAM, as prefill uses whole batch size of token at each pass, decode almost always just single token. Just in case you did't know that :). |
Overview
Add
--pin-hot-experts Nto dynamically pin the top-N most frequently used MoE experts in RAM viamlock(), preventing OS page cache eviction. Large MoE models loaded via mmap suffer from severe latency spikes when the OS evicts experts from RAM and they need to be paged back from disk on later use. This feature tracks expert usage at runtime through a tensor callback onffn_moe_topktensors and on-the-fly replaces cold pinned experts with hotter ones.Dense (non-MoE-expert) tensors residing in host memory are mlocked automatically before any hot experts, since they are used on every token. They consume the global budget first, leaving the remainder for hot expert pinning.
A new load mode
--load-mode mmap+pinis added for mmap without global mlock, designed to pair with--pin-hot-experts.CLI arguments
--pin-hot-experts <n>0(disabled)--pin-hot-experts-budget-mib <n>0(unlimited)--pin-hot-experts-stats-interval <n>0(disabled)--load-mode mmap+pinKey design points
ffn_moe_topktensorsmunlock()'d when replaced by hotter ones--pin-hot-experts-budget-mibstd::setrankingExample
llama-server \ -m /path/to/moe-model-00001-of-00006.gguf \ --load-mode mmap+pin \ --pin-hot-experts 190 \ --pin-hot-experts-budget-mib 130000 \ --pin-hot-experts-stats-interval 2000 \ -lv 4Additional information
Files changed
include/llama.h— public API fields inllama_context_params, newLLAMA_LOAD_MODE_MMAP_PINenumsrc/llama.cpp— load mode name/parser formmap+pinsrc/llama-model.cpp—use_mlocklogic (MMAP_PIN does NOT trigger global mlock)src/llama-hot-experts.cpp/src/llama-hot-experts.h— core implementation (new files)src/llama-context.cpp/src/llama-context.h/src/llama-cparams.h— context integrationcommon/arg.cpp/common/common.cpp/common/common.h— CLI argument handlingsrc/CMakeLists.txt— build integrationHardware / testing environment
Baseline test (no pinning, plain mmap):
llama-server \ -m "/home/ghimli/rootmodels/GLM-5.2-UD-Q2_K_XL-00001-of-00007.gguf" \ --ctx-size 131072 --threads 32 --flash-attn on -np 1 \ --fit off --no-warmup --cache-type-k q8_0 --cache-type-v q8_0 \ --host 127.0.0.1 --port 7777 --jinja --reasoning-preserve \ --n-gpu-layers 999 --cpu-moe -lv 4Hot experts pinned test (
--load-mode mmap+pin --pin-hot-experts 160):llama-server \ -m "/home/ghimli/rootmodels/GLM-5.2-UD-Q2_K_XL-00001-of-00007.gguf" \ --ctx-size 131072 --threads 32 --flash-attn on -np 1 \ --fit off --no-warmup --cache-type-k q8_0 --cache-type-v q8_0 \ --host 127.0.0.1 --port 7777 --jinja --reasoning-preserve \ --n-gpu-layers 999 --cpu-moe -lv 4 \ --load-mode mmap+pin \ --pin-hot-experts-stats-interval 2000 \ --pin-hot-experts 160pinned count range=[53, 657] — all hot experts used more than 53 times are mlocked, cold experts used less are just mmapped and read from disk on cache miss. Hottest expert was used 657 times.
Related
Requirements