Repository navigation
Misc. bug: CUDA memory leak with MTMD requests loop with Gemma3 #19639
Description
Hi.
Thanks a lot for sharing this so great ggml work 💌.
Name and Version
./build/bin/llama-cli --version
ggml_cuda_init: found 1 CUDA devices:
Device 0: NVIDIA GeForce RTX 3060, compute capability 8.6, VMM: yes
version: 7971 (5fa1c19)
built with GNU 13.3.0 for Linux x86_64
Operating systems
Linux NS5x-NS7xAU.localdomain 6.17.0-14-generic #14~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Jan 15 15:52:10 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
Which llama.cpp modules do you know to be affected?
llama-server
$ git log -1
commit 5fa1c190d9fc86c02698b730a2cb933195e19d96 (HEAD -> master, origin/master, origin/HEAD)
Author: Adrien Gallouët <angt@huggingface.co>
Date: Sun Feb 8 09:06:45 2026 +0100
rpc : update from common.cpp (#19400)
Signed-off-by: Adrien Gallouët <angt@huggingface.co>
$ export CUDA_VERSION=12.9 && cmake -B build -DGGML_CUDA=ON \
-DCMAKE_CUDA_ARCHITECTURES="86;120" \
-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
-DCMAKE_CUDA_COMPILER=/usr/local/cuda-${CUDA_VERSION}/bin/nvcc \
-DCMAKE_INSTALL_RPATH="/usr/local/cuda-${CUDA_VERSION}/lib64;\$ORIGIN"
$ cmake --build build --config Release -j 10
Command line
./llama.cpp/build/bin/llama-server --port 8012 \
-m ~/Data/AI_ModelsVision/gemma-3-4b-it-Q4_K_M.gguf \
--mmproj ~/Data/AI_ModelsVision/mmproj-model-f16.gguf \
-c 0 --parallel 1--parallel 1 does not change the count of requests before fail.
Problem description & steps to reproduce
The use case is object detection (MTMD) in small jpeg images (1.7Ko to 19ko) and llama-server fails with CUDA out of memory after ~700 requests.
I do iterations on many different images (thousands) so it should not be image that throws the fail but is it all the time around 700 / 780 requests.
Perhaps it should not be a RTX/CUDA/Driver error because I can relaunch the script and it works fine for another ~700 requests and no message in the system journal (unlike for rtx/cuda/driver errors).
My bug report is poor of precision, but ask me for operations, I'll try to apply them for report completion.
First Bad Commit
No response
Relevant log output
Logs
ggml_cuda_init: found 1 CUDA devices:
Device 0: NVIDIA GeForce RTX 3060, compute capability 8.6, VMM: yes
build: 7971 (5fa1c190d) with GNU 13.3.0 for Linux x86_64
system info: n_threads = 4, n_threads_batch = 4, total_threads = 16
system_info: n_threads = 4 (n_threads_batch = 4) / 16 | CUDA : ARCHS = 860 | USE_GRAPHS = 1 | PEER_MAX_BATCH_SIZE = 128 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX_VNNI = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
Running without SSL
init: using 15 threads for HTTP server
start: binding port with default address family
main: loading model
srv load_model: loading model '~/Data/AI_ModelsVision/gemma-3-4b-it-Q4_K_M.gguf'
common_init_result: fitting params to device memory, for bugs during this step try to reproduce them with -fit off, or provide --verbose logs if the bug only occurs with -fit on
...
... running well for 700 request ...
...
./llama.cpp/ggml/src/ggml-cuda/ggml-cuda.cu:97: CUDA error
CUDA error: out of memory
current device: 0, in function ggml_cuda_graph_evaluate_and_capture at ./llama.cpp/ggml/src/ggml-cuda/ggml-cuda.cu:3910
cudaGraphInstantiate(&graph->instance, graph->graph, __null, __null, 0)
[New LWP 7622]
[New LWP 7621]
[New LWP 7620]
[New LWP 7619]
[New LWP 7618]
[New LWP 7617]
[New LWP 7616]
[New LWP 7615]
[New LWP 7614]
[New LWP 7613]
[New LWP 7612]
[New LWP 7611]
[New LWP 7610]
[New LWP 7609]
[New LWP 7608]
[New LWP 7607]
[New LWP 7606]
[New LWP 7605]
[New LWP 7604]
[New LWP 7603]
[New LWP 7598]
This GDB supports auto-downloading debuginfo from the following URLs:
<https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) [answered N; input not from terminal]
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x000071e034310813 in __GI___wait4 (pid=9109, stat_loc=0x0, options=0, usage=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
warning: 30 ../sysdeps/unix/sysv/linux/wait4.c: Aucun fichier ou dossier de ce nom
#0 0x000071e034310813 in __GI___wait4 (pid=9109, stat_loc=0x0, options=0, usage=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
30 in ../sysdeps/unix/sysv/linux/wait4.c
#1 0x000071e03496e703 in ggml_print_backtrace () from ./llama.cpp/build/bin/libggml-base.so.0
#2 0x000071e03496e8ab in ggml_abort () from ./llama.cpp/build/bin/libggml-base.so.0
#3 0x000071e028963607 in ggml_cuda_error(char const*, char const*, char const*, int, char const*) () from ./llama.cpp/build/bin/libggml-cuda.so.0
#4 0x000071e02897bbbb in ggml_cuda_graph_evaluate_and_capture(ggml_backend_cuda_context*, ggml_cgraph*, bool, bool, void const*) () from ./llama.cpp/build/bin/libggml-cuda.so.0
#5 0x000071e02897ca7e in ggml_backend_cuda_graph_compute(ggml_backend*, ggml_cgraph*) () from ./llama.cpp/build/bin/libggml-cuda.so.0
#6 0x000071e03498ae37 in ggml_backend_sched_graph_compute_async () from ./llama.cpp/build/bin/libggml-base.so.0
#7 0x000071e034abde01 in llama_context::graph_compute(ggml_cgraph*, bool) () from ./llama.cpp/build/bin/libllama.so.0
#8 0x000071e034abf8c4 in llama_context::process_ubatch(llama_ubatch const&, llm_graph_type, llama_memory_context_i*, ggml_status&) () from ./llama.cpp/build/bin/libllama.so.0
#9 0x000071e034ac6daa in llama_context::decode(llama_batch const&) () from ./llama.cpp/build/bin/libllama.so.0
#10 0x000071e034ac881f in llama_decode () from ./llama.cpp/build/bin/libllama.so.0
#11 0x00005db023ec4a48 in server_context_impl::update_slots() ()
#12 0x00005db023f0c7ae in server_queue::start_loop(long) ()
#13 0x00005db023e25770 in main ()
[Inferior 1 (process 7597) detached]
Abandon (core dumped)
Activity
[-]Misc. bug:[/-][+]Misc. bug: CUDA out of memory after 700 requests (MTMD)[/+]LucaAmigoni commentedon Feb 16, 2026
I have a similar issue on Windows 11 using precompiled bins (llama-b8069-bin-win-cuda-13.1-x64), building from source seems to resolve. Note that git pull is ahead b8069, but I don't see resolutions for this in recent commits.
BTW, it seems that cache access (prompt or kv) triggers a new CUDA alloc of variable size depending on model, from 30 to 100MB.
git log -1
commit d612901 (HEAD -> master, origin/master, origin/HEAD)
Author: AesSedai 7980540+AesSedai@users.noreply.github.com
Date: Mon Feb 16 08:44:44 2026 -0800
Build with:
-G "Visual Studio 17 2022" ^
-DLLAMA_CURL=OFF ^
-DLLAMA_SERVER_SSL=OFF ^
-DGGML_NATIVE=ON ^
-DGGML_RPC=ON ^
-DLLAMA_BUILD_SERVER=ON ^
-DGGML_BACKEND_DL=OFF ^
-DGGML_AVX=ON ^
-DGGML_AVX2=ON ^
-DGGML_AVX512=ON ^
-DGGML_AVX512_VBMI=ON ^
-DGGML_AVX512_VNNI=ON ^
-DGGML_AVX512_BF16=OFF ^
-DGGML_MATMUL_INT8=ON ^
-DGGML_CUDA=ON ^
-DGGML_CUDA_GRAPH=ON ^
-DGGML_CUDA_USE_CUBLASLT=ON ^
-DGGML_CUDA_FORCE_CUBLAS=ON ^
-DGGML_LTO=ON ^
-DGGML_OPENMP=ON ^
-DGGML_FLASH_ATTN=ON ^
-DGGML_CUDA_FA_ALL_QUANTS=true
osma commentedon Feb 17, 2026
I have the same issue as OP. I'm using Gemma3-4b-it model (Unsloth UD Q5_K_XL quantization) with mmproj-BF16.gguf and I'm analyzing images one at a time via API with a simple prompt. VRAM usage starts at ~4.7GB but slowly grows as llama-server processes API requests and eventually hits CUDA OOM at 6GB.
I have a RTX 3060 Laptop GPU. Using llama.cpp version 8057 on Linux Mint.
I think it has to do with processing images because I successfully processed 30k+ text prompts with the same Gemma model without loading mmproj.
osma commentedon Feb 19, 2026
I tried to narrow this down and come up with a minimal example.
First, I recompiled latest llama.cpp with CUDA.
Then I started up llama-server with Unsloth Gemma3-4b-it and mmproj directly from HuggingFace using
-hfoption. With-c 50000initial VRAM usage according tonvidia-smiis5479MiB / 6144MiB.Then I ran this test script that generates simple images with random text and sends them to the API endpoint with a prompt to OCR the text.
Test script
Requires
pillowandopenailibraries.Here is the output when tried to run it for 100 rounds:
So llama.cpp is able to process 16 requests before crashing due to CUDA OOM when VRAM usage hits 6GB, which is what I have on my RTX 3060 Laptop GPU.
Final output from llama.cpp
If I start with a smaller context (
-c 30000) then initial VRAM usage is 5089MiB / 6144MiB and I can do 41 requests before hitting OOM. Calculating from this, I think that llama.cpp leaks around 25MB VRAM on every request.What I have tried as well:
What I have not tried:
Cyrille37 commentedon Feb 19, 2026
Nice report, thanks 👌
osma commentedon Feb 19, 2026
Some more observations:
I tried SmolVLM-2B with the command
build/bin/llama-server -hf ggml-org/SmolVLM2-2.2B-Instruct-GGUF. VRAM usage is stable at 3445 MiB even after 100 requests with the test script. Result quality is pretty bad: some of the responses are long strings of numbers or gibberish. But that's a model quality issue, not a VRAM issue.I also tried Qwen3-VL-4B-Instruct with a 10000 token context using the command
build/bin/llama-server -hf unsloth/Qwen3-VL-4B-Instruct-GGUF -c 10000. VRAM usage is stable at 5425MiB after 100 requests. It's also amazingly fast - around six times faster than the similarly sized Gemma3 4B!Finally, I tested Gemma3 again with a smaller test image (256x128 instead of 768x512). The result did not change; with a 30000 context I can still make 41 requests before OOM crashing, so the VRAM leak is apparently not affected by image size.
Conclusion: This VRAM leaking does not apply to all VLMs equally; it might be specific to Gemma.
@Cyrille37 Perhaps you could update the issue title to reflect these findings? E.g. "CUDA memory leak on Gemma3 processing images" or something along those lines?
[-]Misc. bug: CUDA out of memory after 700 requests (MTMD)[/-][+]Misc. bug: CUDA out of memory after MTMD requests loop with Gemma3[/+][-]Misc. bug: CUDA out of memory after MTMD requests loop with Gemma3[/-][+]Misc. bug: CUDA memory leak with MTMD requests loop with Gemma3[/+]ORippler commentedon Mar 2, 2026
Does #19754 or alternatively disabling cuda graphs via GGML_CUDA_DISABLE_GRAPHS fix this?
osma commentedon Mar 2, 2026
@ORippler Thank you for the suggestions.
I tried again with the test case in #19639 (comment) (anyone can try this BTW). I'm using llama.cpp version: 8179 (ecbcb7e) which already contains #19754.
jstrot commentedon Apr 6, 2026
@ORippler Thanks!
Indeed
GGML_CUDA_DISABLE_GRAPHS=1prevents the issue for me as well.llama.cpp: Docker ghcr.io/ggml-org/llama.cpp:server-cuda12-b8667 (today's latest)
Model: unsloth/gemma-4-E4B-it-GGUF UD-Q8_K_XL + mmproj-BF16
GPU: RTX 5060 Ti
Task: image analysis
2264K commentedon Apr 10, 2026
Gemma 4 VLM VRAM/Host Memory Leak — Full Investigation Report
Summary
Repeated image inference with Gemma 4 31B + mmproj on llama-server causes two separate memory leaks:
Both leaks are Gemma 4 + image specific. Qwen3.5-27B with identical VLM setup shows zero leak on both metrics.
Environment
unsloth/gemma-4-31B-it-GGUF:UD-Q4_K_XL(17 GB)Qwen/Qwen3.5-27Bandgoogle/gemma-4-31b-itusingconvert_hf_to_gguf.py --mmprojReproduction
Controlled Experiments
Leak is Gemma 4 + Image Specific
Key observations:
Leak is NOT in vision encoder
Instrumented
clip_image_batch_encode()withggml_backend_dev_memory()probes at each stage:Vision encoder is clean from request 3 onwards. Leak occurs during llama_decode() when generating text with image tokens in KV cache.
Graph allocator buffers are constant
Instrumented
process_ubatch()→ggml_backend_sched_alloc_graph():Buffer size never changes.
ggml_gallocr_needs_realloc()returns false after initial warmup.ALL tracked CUDA allocations are balanced
LD_PRELOAD interceptor tracking
cudaMalloc/cudaFree/cuMemCreate/cuMemMap/cuMemUnmap:No cudaMalloc or cuMemCreate leak. VRAM growth is from allocations NOT visible to these APIs.
Root Cause Analysis
Host Memory Leak (FIXED)
Cause: cuBLAS internal host-side workspace caching. cuBLAS allocates host memory for each unique matmul configuration. Gemma 4's hybrid attention (SWA head_dim=256 + full head_dim=512) combined with image prefill batches (300+ tokens) vs decode batches (1 token) creates many unique configurations. The workspace is only freed on
cublasDestroy().Fix: Periodic
cublasDestroy()+ lazy recreate every 100 graph computes:Result: RSS delta went from +925 MiB → 0 MiB over 20 requests.
Note: Resetting every compute (instead of every 100) causes worse RSS leak from create/destroy overhead.
VRAM Leak (UNRESOLVED)
After fixing the host memory leak, VRAM still grows at ~6.4 MiB/request.
What we ruled out:
What remains: VRAM growth is not from any tracked allocation API (
cudaMalloc,cuMemCreate,cublasSetWorkspace,cudaMemPool). It appears to be CUDA runtime/driver internal state (kernel launch metadata, context bookkeeping) that accumulates when processing varying compute patterns specific to Gemma 4 + image tokens.Cross-Framework Validation
The VRAM leak appears to be a systemic issue across frameworks when handling Gemma 4's hybrid SWA architecture with vision inputs.
Suggested Investigation Directions
CUDA runtime internal allocation tracking:
cudaMemGetInforeports decreasing free memory, but no tracked allocation API accounts for it. NVIDIA'scompute-sanitizeror internal tooling may reveal which CUDA runtime subsystem is accumulating device memory.Gemma 4 Shared KV Cache interaction: Gemma 4 has
num_kv_shared_layers=20where later layers reuse K/V from earlier layers. This shared reference pattern during sequence processing (especially with varying-length image token sequences) may cause the KV cache management to retain more state than expected.Flash attention kernel workspace: The leak occurs during
llama_decode()which usesggml_flash_attn_ext(not cuBLAS) for attention. The flash attention kernel may allocate per-launch device memory that isn't properly reclaimed between varying batch sizes.Profile with
nsys/ncu: Per-kernel device memory delta analysis would pinpoint exactly which kernel launch causes the VRAM increase.Files & Tools
cudaMalloc/cudaFree/cuMemCreate/cuMemMap/cuMemUnmapmalloc/free/reallocwith caller address logging/proc/<pid>/status VmRSSper requestcublasDestroy()/recreate (fixes host memory leak)All available on request.
Related Issues
github-actions commentedon May 25, 2026
This issue was closed because it has been inactive for 14 days since being marked as stale.