[BUG] Model reload after idle unload takes ~70s on NVIDIA Vulkan (coopmat) -> transcription times out after 30s
Bug Description
On Linux with an NVIDIA GPU (Vulkan), every model reload after an idle unload takes ~70s on the CPU (a single thread pegged at 100%), which blows the app's 30s transcription timeout. The result is that the first transcription after Handy has been idle for model_unload_timeout fails with Timed out waiting 30s for live transcription to finalize or Model is not loaded for transcription..
The first load after app start is fast (~1s). Only reloads after unload are slow. Inference itself is fast once the model is loaded (8–13x real-time).
This is NVIDIA-specific: on the Intel iGPU (no coopmat), the same reload is ~1s. It correlates with ggml detecting KHR_coopmat matrix cores.
Environment
- OS: Ubuntu 24.04 LTS, X11
- Hardware: hybrid GPU — Intel UHD (TGL GT1) iGPU + NVIDIA RTX A4000 Laptop (8GB), driver 595.71.05
- Handy: 0.9.4 (deb),
transcribe_accelerator: gpu,transcribe_gpu_device: 1(NVIDIA) - Model:
handy-computer/parakeet-unified-en-0.6b-gguf/parakeet-unified-en-0.6b-Q8_0.gguf - Stack: transcribe.cpp / ggml-vulkan (libggml-vulkan.so from /usr/lib/Handy), coopmat enabled (
matrix cores: KHR_coopmat)
Steps to Reproduce
- Set
model_unload_timeoutto a short value (e.g.sec15) and force the GPU device to the NVIDIA GPU (transcribe_gpu_device: 1). - Start Handy fresh. Trigger a transcription (Ctrl+Space). First model load: ~1s.
- Wait for the idle unload (~15s).
- Trigger a transcription again.
Observed: the reload takes ~70–76s. The 30s transcription timeout fires first, so the transcription fails.
Repeated consistently across multiple cycles in a fresh process (load 17:35:47 → loaded 17:37:03 = 76s; repeated at ~72s, ~73s, ~75s).
Root Cause Evidence
- During the slow reload, a single Handy thread spins at 100% CPU while the GPU is idle (0% util). The slow step is entirely inside
transcribe_model_load_file(CPU-side shader/pipeline build). - The slowness is caused by the cooperative-matrix (coopmat) path: ggml-vulkan reports
matrix cores: KHR_coopmaton the NVIDIA device, and reloading the model rebuilds the coopmat pipeline set. This only happens on NVIDIA. - A standalone test harness using the same
/usr/lib/Handy/libtranscribe.so.0, same model, same device, doestranscribe_open → transcribe_run → transcribe_closecycles in ~0.4s even with coopmat enabled — so the fast/slow difference is tied to how the app tears down/recreates the engine (see the related issue below). - On the Intel iGPU (no coopmat), the app's reload is ~1s.
Workaround (verified)
Setting GGML_VK_DISABLE_COOPMAT=1 for the Handy process makes the same reload <1s (loaded in the same second it started), with no measurable impact on inference speed for this model (~86ms vs ~100ms per run on a 2s clip — both far above real-time).
Related Issue
Closely related to #1775 ("ggml-vulkan device contexts persist after model unload and degrade system performance") — that issue documents the ggml-vulkan context lifecycle on hybrid Intel+NVIDIA laptops being broken. This report is the other side of the same lifecycle problem: the reload path pays a pathological coopmat shader-rebuild cost after unload.
Source: cjpais/Handy