Repository navigation
Eval bug: Vulkan/RADV Radeon 680M regression: --load-mode auto causes device loss/OOM on large Gemma model; --load-mode mmap fixes it #27360
Description
Name and Version
d@mpc1:~/main/llama-cpp/prebuilt-vulkan$ ./llama-server --version
version: 0.1.1-dev (build 10470, commit 34af94c)
built with GNU 11.4.0 for Linux x86_64
Operating systems
Linux
GGML backends
Vulkan
Hardware
CPU: AMD 6800H
Discrete GPU: None
iGPU: Radeon 680M
Models
Gemma 4 26B A4B IT QAT Q4_0,
MTP assistant at Q4_0
MMPROJ at F16
Problem description & steps to reproduce
ChatGPT wrote this, ChatGPT troubleshot and fixed the issue. I submit this in case it is useful to anyone else:
I found what appears to be a regression affecting large models on an AMD Radeon 680M iGPU using Vulkan/RADV.
System
AMD Radeon 680M integrated GPU
amdgpu kernel driver
RADV Vulkan
32 GB physical RAM (~27 GiB usable by Linux)
Kernel reports:
4096 MiB VRAM
13918 MiB GTT
Linux Mint
Kernel 7.0.0-28-generic
Model/configuration
Gemma 4 26B A4B QAT Q4_0 with multimodal projector and MTP speculative decoding:
Main model: ~14 GB
mmproj F16: ~1.2 GB
MTP draft model: ~241 MB
Context: 50000
Parallel slots: 1
GPU layers: auto
Draft GPU layers: auto
Flash attention: auto
Regression
b10353 works reliably with this configuration.
By b10470 the same configuration started failing. I also reproduced it with b10488 (9d77fa1).
The failure is:
radv/amdgpu: Not enough memory for command submission.
ggml_vulkan: device lost on Vulkan0
vk::Queue::submit: ErrorDeviceLost
The kernel reports at the same time:
amdgpu_vm_validate() failed.
Not enough memory for command submission!
Sometimes the model fails while loading after a clean boot. In another test it loaded successfully and completed the first request, then failed during the second request.
Smaller models continue to work normally with the newer builds.
Workaround / important finding
While troubleshooting this with ChatGPT, we noticed that PR #26081 changed the default model-loading behavior for iGPUs between my known-good and known-bad versions.
I tested the newer llama.cpp build with only this additional option:
--load-mode mmap
This completely fixes the problem.
Gemma 4 26B + mmproj + MTP now loads and runs successfully on the newer build when --load-mode mmap is specified.
So on this Radeon 680M/RADV system:
b10353 default behavior -> works
newer build, --load-mode auto/default -> Vulkan device loss / command submission OOM
same newer build, --load-mode mmap -> works
This makes PR #26081 / the new iGPU auto loading path look like a possible regression, although I have not done a git bisect and therefore cannot say that PR #26081 is definitely the cause.
Possibly unrelated warning
The log also contains:
Gemma4Assistant requires ctx_other to be set
failed to measure draft model memory: failed to create llama_context from model
However, this warning was already present in b10353 and in several earlier working builds, so I don't think that warning itself is responsible for this regression.
Additional information
I previously tried:
--no-cache-idle-slots
--fit-target 6144
Neither fixed the problem.
After a Vulkan device loss, subsequent model loads often fail until reboot, but I have also seen the original failure after a clean boot, so stale GPU state does not appear to be the root cause.
I don't personally need an immediate fix because --load-mode mmap is a good workaround for me. I'm reporting this because the clean good/bad behavior may be useful for debugging the new iGPU loading path.
Related change: #26081
First Bad Commit
No response
Relevant log output
Error: llama-server exited with status -6.
#17 0x00007a0f9daee608 in llama_server(common_params&, int, char**) () from /home/d/main/llama-cpp/prebuilt-vulkan/libllama-server-impl.so
#18 0x00007a0f9daefe8f in llama_server(int, char**) () from /home/d/main/llama-cpp/prebuilt-vulkan/libllama-server-impl.so
#19 0x00007a0f9d22a1ca in __libc_start_call_main (main=main@entry=0x5d8b4d33b260
warning: 58 ../sysdeps/nptl/libc_start_call_main.h: No such file or directory
#20 0x00007a0f9d22a28b in __libc_start_main_impl (main=0x5d8b4d33b260 , argc=55, argv=0x7ffdb066ca48, init=, fini=, rtld_fini=, stack_end=0x7ffdb066ca38) at ../csu/libc-start.c:360
warning: 360 ../csu/libc-start.c: No such file or directory
#21 0x00005d8b4d33b295 in _start ()
[Inferior 1 (process 3324) detached]
terminate called after throwing an instance of 'vk::DeviceLostError'
what(): vk::Queue::submit: ErrorDeviceLost
Activity
tobiasvandriessel commentedon Sep 2, 2026
I’m also impacted by this problem and the mmap mode indeed resolves the issue!
foolish-dev commentedon Sep 11, 2026
Same failure here on a Strix Halo APU (Ryzen AI Max+ 395 / Radeon 8060S, gfx1151): 4 GiB carve-out, 13.52 GiB GTT, 27.0 GiB RAM visible to Linux, the same layout as the 680M report above.
Setup: RADV (Mesa 26.2.2), Linux 7.2.3-1-cachyos, llama-server built from
a2878d3(build 10909) with-DGGML_VULKAN=ON, dense 27B Q4_K_M (qwen35 arch, ~16 GiB),--jinja -c 16384, default--load-mode auto. All 3 runs (1 with default--fit, 2 with-ngl 32) aborted in the warm-up decode withvk::DeviceLostError: vk::Queue::submit: ErrorDeviceLost.The kernel log for those runs has 1560x
amdgpu 0000:c4:00.0: [drm] *ERROR* amdgpu_vm_validate() failed.and 1563xamdgpu 0000:c4:00.0: [drm] *ERROR* Not enough memory for command submission!. There are no ring timeout or ring reset lines in that boot.Likely mechanism
Line numbers are at
a2878d3; no commit up to master8172e657touches these files. The code facts are cited; that they cause the crash is my inference.ggml/src/ggml-vulkan/ggml-vulkan.cpp:19116, from llama: add default load-mode auto, which avoids mmap on iGPUs #26081), so--load-mode auto, the default (common/common.h:484,src/llama-model.cpp:2766), turns mmap off (src/llama-model.cpp:1417-1426).Vulkan_Host. Non-offloaded layers and the input layer use the CPU weight list (src/llama-model.cpp:1498-1500,:1510):ACCEL -> GPU host -> CPU extra -> CPU, with the host type added unlessno_hostis set (:1033-1063,:1055). The loader takes the first entry whose device supports the weight's op (src/llama-model-loader.cpp:1060-1071) and swaps a host buffer type back to CPU only when mmap is on (:1262-1270), which is why--load-mode mmapworks around this. So the CPU-side weights that Vulkan can run stay inVulkan_Hostinstead of CPU/CPU_REPACK. This is the same path as Eval bug: llama_model_load: error loading model: vk::Queue::submit: ErrorDeviceLost #18962; as I read it, llama: add default load-mode auto, which avoids mmap on iGPUs #26081 made it the default on iGPUs.Vulkan_Hostis GTT, and so is anything Vulkan0 can't fit in the carve-out.Vulkan_Hostis allocated byggml_vk_host_malloc(ggml-vulkan.cpp:16897-16914), which first asks for HOST_VISIBLE|HOST_COHERENT|HOST_CACHED (:8204-8208); in Mesa 26.2.2 those memory types areRADEON_DOMAIN_GTT(src/amd/vulkan/radv_physical_device.c:571-586). Offloaded weights on UMA prefer DEVICE_LOCAL|HOST_VISIBLE (ggml-vulkan.cpp:3799-3804), and RADV also allows GTT as a placement for VRAM-domain buffers (src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c:565-585), so Vulkan0 memory beyond the 4 GiB carve-out lands in GTT as well. So the whole model sits in carve-out + GTT whatever-nglis;-nglonly moves weights betweenVulkan0andVulkan_Host.--fitcan't see this: its dry run loads withLLAMA_LOAD_MODE_NONE(common/fit.cpp:57), so it places weights inVulkan_Hosttoo, and it counts every buffer type whoseis_hostis true as host memory (:77-83).Vulkan_Hostreuses the CPUis_host(ggml-vulkan.cpp:16941), and the iGPU's free memory includes the GTT budget (ggml-vulkan.cpp:18987-19009). So GTT is offered to fit as free device memory, while theVulkan_Hostweights that use the same GTT are charged to system RAM.Workaround:
--no-host(observed)These numbers come from llama-server b10760 (
0f3a71be), the build bundled in Ollama 0.33.3 (CachyOSollama 0.33.3-1.1), withlibggml-vulkan.sofrom the matching signedollama-vulkan 0.33.3-1.1package, run as a privateollama servewithOLLAMA_IGPU_ENABLE=1andLLAMA_ARG_NO_HOST=1(Ollama passes its environment to llama-server). The buffer-placement and fit code is unchanged between b10760 anda2878d3. The 27B is the same GGUF the crash runs used, restamped since: identical tensors, onlytokenizer.chat_templatediffers.With
--no-host, non-offloaded weights go to CPU and CPU_REPACK buffers. 27B Q4_K_M (17.3 GB file), ctx 4096, q8_0 KV, flash attention on, Ollamanum_batch512,num_gpu= the -ngl column:GPU pool usage now tracks the Vulkan0 buffer plus ~1.5-1.7 GiB (KV cache, compute buffers, other GPU clients); the CPU-side weights no longer show up in it. CPU-only generation is ~5.0 tok/s. At
-ngl 32the host ran short of RAM, so I stopped the run. I have no prompt-processing numbers.Suggested fix
When
autoturns mmap off because an iGPU reports no mmap support, don't put weights in the device host buffer type (behave as ifno_hostwere set for the weight lists). This puts those weights back on the CPU side, as before #26081 (in CPU/CPU_REPACK buffers, as with--no-host), and keeps #26081's load-time RAM saving. Tradeoff: on UMA the backend can use host buffers directly (ggml-vulkan.cpp:9467-9471), which may help PP when weights are CPU-side; I haven't measured that.On the
--fitside,common/fit.cppcould charge a host buffer type to its device when that device isGGML_BACKEND_DEVICE_TYPE_IGPU(Vulkan reports that type,ggml-vulkan.cpp:19100;Vulkan_Host's.deviceis already Vulkan0,:16943). On its own that can't make lowering-nglhelp, so fit would have to shrink the context or fail loudly, which is still better than DeviceLost.Related: #26081 (introduced
auto); #18962 (the same CS ENOMEM viaVulkan_Hostwith mmap off, fixed by--mmap; closed as stale, it includes an APU report after #26081); #22592 (UMA accounting in--fit).YuWei-CH commentedon Oct 26, 2026
I can reproduce this issue.
System:
APU: AMD Ryzen 7 7735HS / Radeon 680M (RADV REMBRANDT)
RAM: 32 GB DDR5-4800, 3 GiB VRAM carve-out
GTT limit: 14,403 MiB (mem_info_gtt_total)
OS: Ubuntu 24.04.5, kernel 7.0.0-38-generic
Mesa: 25.2.8
llama.cpp: d854d98 (b11889), Release build with GGML_VULKAN=ON
Here are my actions and results:
I am using Qwen3.6-35B-A3B-Q4_K_M (19.01 GiB) with this command:
./llama-server -m Qwen3.6-35B-A3B-Q4_K_M.gguf -vWith no additional flags, --fit selects all 41 layers for GPU offloading (10 overflowing) and reports:
Vulkan0: 16140 MiB used, 1034 MiB free
common_fit_params: successfully fit params to free device memory
However, the actual allocations include:
Vulkan0 model buffer size = 15589.26 MiB
Vulkan_Host model buffer size = 3873.88 MiB
radv/amdgpu: Not enough memory for command submission.
ggml_vulkan: device lost on Vulkan0
llama_model_load: error loading model: vk::Queue::submit: ErrorDeviceLost
On this CPU, Vulkan0 allocations beyond the 3 GiB carve-out and Vulkan_Host allocations both consume GTT. Using the reported model-buffer sizes, the estimated GTT requirement for weights alone is:
15589 - 3072 + 3874 = 16391 MiB
This exceeds the 14,403 MiB GTT limit, which confirm the issue described above: --fit treats Vulkan_Host allocations as host memory, although they consume the same GTT budget as the portion of Vulkan0 memory beyond the carve-out.
Also, same as above, --no-host allows the same model to run:
With the same model and default --fit, adding --no-host succeeds:
Vulkan0 model buffer size = 15729.13 MiB
CPU model buffer size = 278.01 MiB
CPU_REPACK model buffer size = 3456.00 MiB