Skip to content

llama : make tensor-split regex patterns static to avoid per-token recompilation - #24710

Merged
JohannesGaessler merged 1 commit into
ggml-org:masterfrom
eduardopessin:fix/static-regex-tensor-split
Jul 10, 2026
Merged

llama : make tensor-split regex patterns static to avoid per-token recompilation#24710
JohannesGaessler merged 1 commit into
ggml-org:masterfrom
eduardopessin:fix/static-regex-tensor-split

Conversation

@eduardopessin

@eduardopessin eduardopessin commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Overview

I hit this while running Qwen3.6-35B-A3B with -sm tensor, -np 5, and a large context on 3 consumer GPUs over PCIe Gen3, without NVLink.

The visible symptom was simple: the decode thread was stuck at 100% CPU, while the GPUs were only around 30% utilized. They were basically waiting on the CPU.

I profiled only the decode thread, not the whole process, to avoid mixing this with the HTTP worker threads:

perf record -e cpu-clock -F 299 -t <decode-tid> --call-graph dwarf

That showed a large amount of time under llama_meta_device_get_split_state() and the related split-state path. About 30% of the decode thread was in std::regex compilation frames, including _Compiler::_M_*, _BracketMatcher, std::collate::do_transform, __strxfrm_l, and __dynamic_cast. Another ~22% was in the ggml_backend_meta_get_split_state machinery.

The problem is that llama_meta_device_get_split_state() declared 29 std::regex objects as local variables. In tensor split mode, this callback runs once per tensor, per token, because the graph is rebuilt on each decode step. That means the same regexes are compiled again and again in the decode path.

This moves those patterns to file scope (compiled once, reused). The patterns are literals and do not carry mutable state, so the behavior is unchanged. Keeping them outside the function also avoids the function-local static concern raised in review.

After the change, the std::regex compilation frames disappear from the profile. get_split_state drops from roughly 22% to roughly 13%, freeing about 40% of the decode thread in this setup. With concurrent load, the GPUs are then able to saturate.

I am not quoting absolute tok/s numbers here, since those depend heavily on the hardware and workload. The useful result is the profile delta.

Requirements

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: YES — I used AI assistance while profiling, diagnosing, and preparing this change. I ran the profiling myself on my own hardware and validated the result locally.

@eduardopessin
eduardopessin requested a review from CISC as a code owner June 16, 2026 22:01
@ggml-gh-bot

This comment was marked as resolved.

@eduardopessin
eduardopessin force-pushed the fix/static-regex-tensor-split branch from e4aedf2 to f0667e6 Compare June 16, 2026 22:18
@eduardopessin

Copy link
Copy Markdown
Contributor Author

Done

@CISC

CISC commented Jun 17, 2026

Copy link
Copy Markdown
Member

This just introduces MT issues, I suppose they need to live outside llama_meta_device_get_split_state.

Also, please use our PR template in the OP.

@CISC
CISC requested a review from JohannesGaessler June 17, 2026 07:24
@eduardopessin
eduardopessin force-pushed the fix/static-regex-tensor-split branch from f0667e6 to 87a50f6 Compare June 17, 2026 08:49
@eduardopessin

Copy link
Copy Markdown
Contributor Author

Done, plz let me know if you need something else

@eduardopessin

Copy link
Copy Markdown
Contributor Author

Also tested and profiled, regex completly gone from hot path

@JohannesGaessler

Copy link
Copy Markdown
Contributor

Regarding multi-threading issues: to my knowledge since C++ 11 the creation of local static variables is thread safe so it should be fine to just add static to the code on master in order to keep the variables contained to the function. Also if at all possible, please post benchmark numbers to show the actual impact of this change.

llama_meta_device_get_split_state() recompiled 29 std::regex on every call.
In -sm tensor mode the callback runs once per tensor per token, so this
dominated the decode thread in profiling. Mark them static const so they are
compiled once. Kept inside the function (local statics are thread-safe since
C++11). Patterns are literal and stateless, so behavior is unchanged.
@eduardopessin
eduardopessin force-pushed the fix/static-regex-tensor-split branch from 87a50f6 to 4f19d39 Compare July 3, 2026 20:31
@JohannesGaessler

Copy link
Copy Markdown
Contributor

@CISC can you re-review?

@JohannesGaessler

Copy link
Copy Markdown
Contributor

@ggml-org/maintainers can I get a second approval, please?

@JohannesGaessler
JohannesGaessler merged commit c749cb0 into ggml-org:master Jul 10, 2026
25 checks passed
fukuro-kun pushed a commit to fukuro-kun/fukuro-llama-cpp-turboquant that referenced this pull request Jul 12, 2026
AtomicBot-ai#6 MUL_MAT_ID Subgroup (PR ggml-org#15524):
- Subgroup ballot operations für MoE-Expert-Selection auf non-coopmat GPUs
- 18 Merge-Konflikte in ggml-vulkan.cpp gelöst (HEAD-Features erhalten)
- 2 PR-Änderungen übernommen: subgroup_min_size<=16 Check, fused RMS_NORM+MUL
- mul_mm.comp: neuer subgroup load_row_ids() Code
- vulkan-shaders-gen.cpp: MatMulIdType::SUBGROUP integration

AtomicBot-ai#2 Tensor Split Regex (PR ggml-org#24710, open):
- 29 std::regex Patterns von const auf static const geändert
- Verhindert pro-Token Regex-Recompilation im Tensor-Split-Modus
- Befreit ~40% des Decode-Threads auf Multi-GPU-Systemen

Build: grün auf Hydra (CUDA)
fukuro-kun pushed a commit to fukuro-kun/fukuro-llama-cpp-turboquant that referenced this pull request Jul 12, 2026
…AtomicBot-ai#6 revert

AtomicBot-ai#6 MUL_MAT_ID Subgroup (PR ggml-org#15524) wurde revertiert:
- 23 Merge-Konflikte in 3 Vulkan-Dateien, davon 18 in ggml-vulkan.cpp
- Subagent-Lösung beschädigte Shader-Generierung (undefined references)
- Erfordert manuelle Portierung mit tiefem Vulkan-Shader-Verständnis
- Für spätere Session mit fokussiertem Ansatz

AtomicBot-ai#2 Tensor Split Regex (PR ggml-org#24710, open) erfolgreich:
- 29 std::regex Patterns von const auf static const geändert
- Verhindert pro-Token Regex-Recompilation im Tensor-Split-Modus
CowboyTim pushed a commit to aardbeiplantje/llama.cpp that referenced this pull request Jul 21, 2026
llama_meta_device_get_split_state() recompiled 29 std::regex on every call.
In -sm tensor mode the callback runs once per tensor per token, so this
dominated the decode thread in profiling. Mark them static const so they are
compiled once. Kept inside the function (local statics are thread-safe since
C++11). Patterns are literal and stateless, so behavior is unchanged.
satindergrewal pushed a commit to satindergrewal/llama.cpp that referenced this pull request Aug 12, 2026
llama_meta_device_get_split_state() recompiled 29 std::regex on every call.
In -sm tensor mode the callback runs once per tensor per token, so this
dominated the decode thread in profiling. Mark them static const so they are
compiled once. Kept inside the function (local statics are thread-safe since
C++11). Patterns are literal and stateless, so behavior is unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants