Skip to content

win32: auto-enable the GPU in bare coli chat#363

Merged
JustVugg merged 1 commit into
JustVugg:devfrom
woolcoxm:fix/win32-coli-chat-cuda-autoenable
Jul 20, 2026
Merged

win32: auto-enable the GPU in bare coli chat#363
JustVugg merged 1 commit into
JustVugg:devfrom
woolcoxm:fix/win32-coli-chat-cuda-autoenable

Conversation

@woolcoxm

Copy link
Copy Markdown
Contributor

Summary

On Windows, a bare coli chat (no --gpu/--vram/--auto-tier) always ran CPU-only, even on a CUDA build with a GPU present. Two defects:

  1. cuda_binary() returned False on Windows. It detects CUDA by running ldd glm | grep libcudart β€” Linux-only (no ldd on win32) and meaningless anyway, because the Windows engine links cudart only inside a runtime-loaded coli_cuda.dll, not as a libcudart symbol in glm.exe. So the --gpu/--vram/--auto-tier gates (which all call cuda_binary()) never opened.

  2. Bare coli chat set no CUDA env even with detection fixed. env_for's else:-branch only enables CUDA when --gpu/--vram is passed. Nothing auto-enabled the GPU. So every Windows user running coli chat on a CUDA build silently got CPU-only.

The fix

cuda_binary() β€” on non-Linux, return True iff coli_cuda.dll exists next to glm.exe. That is the exact file backend_loader.c loads from the engine's own directory, so its presence is a faithful, cheap, DLL-hijack-safe proxy for a CUDA-capable build. (Linux keeps the working ldd check untouched.)

env_for β€” scoped to win32 (Linux keeps its working explicit-flag UX), when a bare chat (a.gpu is None, no --vram, no --auto-tier) detects a CUDA build and a GPU via nvidia-smi, it now:

  • sets COLI_CUDA=1 + COLI_GPUS=<detected indices>
  • sizes the expert-tier VRAM budget from real free VRAM via the existing build_plan / environment_for_plan machinery (same as --auto-tier β€” no guessed budget, 2 GB reserve honoured)
  • prints [GPU] auto-enabled CUDA Β· <names> Β· <N> GB expert tier

If nvidia-smi is missing from PATH it falls back to CPU with a clear warning (pass --vram N to enable CUDA). --gpu none still forces CPU; explicit --vram/--gpu still win; CUDA_DENSE stays an explicit opt-in (matches --auto-tier).

Verification

On a Windows + RTX 5070 Ti box (this branch):

$ python coli chat --model glm52_i4_g64   # bare, no flags
  [GPU] auto-enabled CUDA Β· NVIDIA GeForce RTX 5070 Ti Β· 13.0 GB expert tier

Resulting env: COLI_CUDA=1, COLI_GPUS=0, CUDA_EXPERT_GB=13.044 (before: all unset, CPU-only). Overrides confirmed: --gpu none β†’ COLI_CUDA=0; --vram 4 β†’ CUDA_EXPERT_GB=4. Engine smoke run prints [CUDA] mode: routed experts only.

Tests: 4 new cases in test_env_defaults.py (CudaAutoEnableTest):

  • test_win32_auto_enables_cuda_when_gpu_present
  • test_win32_falls_back_to_cpu_when_nvidia_smi_missing
  • test_win32_cpu_build_stays_silent
  • test_linux_bare_chat_not_auto_enabled (proves the win32 guard is scoped)

The 4 existing default-I/O tests are guarded to mock cuda_binary() so they stay host-independent. Full Python suite green: env_defaults 8, resource_plan 10, doctor 8, makefile_platform 3, cli_output 3.

Behaviour matrix

Command Before After
coli chat (win, CUDA build + GPU) CPU-only, silent GPU auto-enabled, sized
coli chat (win, CUDA build, no nvidia-smi) CPU-only, silent CPU-only, warns
coli chat (win, CPU build) CPU-only, silent CPU-only, silent (unchanged)
coli chat --gpu none CPU-only CPU-only (unchanged)
coli chat --vram 4 needs make glm CUDA=1 to even start GPU, 4 GB (now works on win)
coli chat (Linux) unchanged unchanged

Out of scope

@woolcoxm

Copy link
Copy Markdown
Contributor Author

Cross-ref for context: this launcher fix only does something useful once #298 (g64 CUDA backend, feat/cuda-fmt4-grouped-int4) lands β€” without it, row_bytes(fmt=4) returns 0 on the grouped-int4 checkpoint and the GPU stays idle regardless of what coli chat enables. The two are non-overlapping (this = c/coli; #298 = backend_cuda.cu / glm.c).

Related branches:

This PR (#363) is the clean standalone dev-based path in case #298 is delayed; #364 is the stacked integration path once #298 merges.

On Windows a bare 'coli chat' (no --gpu/--vram/--auto-tier) ALWAYS ran
CPU-only, even on a CUDA build with a GPU present. Two defects:

1. cuda_binary() returned False on Windows. It detects CUDA by running
   'ldd glm | grep libcudart', which is Linux-only (no ldd on win32) and
   meaningless anyway because the Windows engine links cudart only inside a
   runtime-loaded coli_cuda.dll, not as a libcudart symbol in glm.exe. So
   the --gpu/--vram/--auto-tier gates (which call cuda_binary()) never opened.

2. Even with detection fixed, bare 'coli chat' set no CUDA env: env_for's
   else-branch only enables CUDA when --gpu/--vram is passed. Nothing
   auto-enabled the GPU.

Now: cuda_binary() on non-Linux returns True iff coli_cuda.dll exists next
to glm.exe β€” the exact file backend_loader.c loads from the engine's own
directory, so its presence is a faithful, cheap, DLL-hijack-safe proxy for a
CUDA-capable build. And env_for, scoped to win32 (Linux keeps its working
explicit-flag UX), auto-enables CUDA when a bare chat detects a CUDA build
plus a GPU via nvidia-smi, sizing the expert-tier VRAM budget from real free
VRAM via the existing build_plan/environment_for_plan machinery (same as
--auto-tier, no guessed budget). If nvidia-smi is missing it falls back to
CPU with a clear warning; --gpu none still forces CPU; explicit --vram/--gpu
still win. CUDA_DENSE stays an explicit opt-in (matches --auto-tier).

Verified on a Windows + RTX 5070 Ti box: bare 'coli chat --model <g64>' now
prints '[GPU] auto-enabled CUDA ... 13.0 GB expert tier' and emits
COLI_CUDA=1 / COLI_GPUS=0 / CUDA_EXPERT_GB=13.044 (was: all unset, CPU-only).

Tests: 4 new cases (auto-enable, nvidia-smi-missing fallback, CPU-build
silent, Linux-unchanged) plus the 4 existing default-I/O tests guarded to
mock cuda_binary() so they stay host-independent. Full python suite green
(env_defaults 8, resource_plan 10, doctor 8, makefile_platform 3, cli_output 3).

Out of scope: doctor.cuda_linkage is also POSIX-only and mis-reports on
Windows β€” separate follow-up.
@woolcoxm
woolcoxm force-pushed the fix/win32-coli-chat-cuda-autoenable branch from 669ee03 to 0b05f6a Compare July 20, 2026 15:06
@woolcoxm

Copy link
Copy Markdown
Contributor Author

Rebased onto current dev (e9b3614) β€” MERGEABLE, 0 conflicts, 0 commits behind.

Conflict resolution

One conflict in c/coli's cuda_binary() β€” dev landed a more robust win32 detection (marker-string b"[CUDA] mode: routed experts" in the binary + coli_cuda.dll presence) that supersedes my simpler coli_cuda.dll-only check. Kept dev's version β€” it's a strict improvement (catches the stale-DLL-without-CUDA-build case mine missed). The actual contribution of this PR β€” the env_for auto-enable logic that uses cuda_binary() to turn on CUDA in bare coli chat (lines 240-274, with the [GPU] auto-enabled CUDA message and nvidia-smi-missing fallback) β€” applied cleanly and is intact.

Verification

$ python -m unittest tests.test_env_defaults tests.test_cli_output
test_win32_cpu_build_stays_silent                  ... ok
test_win32_falls_back_to_cpu_when_nvidia_smi_missing ... ok
test_win32_auto_enables_gpu (CudaAutoEnableTest)   ... ok
test_explicit_override_wins                        ... ok
...
Ran 11 tests in 0.203s β€” OK

Including the 3 CudaAutoEnableTest cases (auto-enable, nvidia-smi-missing fallback, CPU-build silent) and the 4 existing default-I/O tests that mock cuda_binary() to stay host-independent.

@JustVugg
JustVugg merged commit f8e0612 into JustVugg:dev Jul 20, 2026
8 checks passed
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.

2 participants