Skip to content

GPU/CUDA on Windows: works, with rough edges (rpath warning, non-portable search-paths, cblas unverified) #4

Description

@netdur

Summary

The vendor/cuda package works on Windows (x86_64-pc-windows-msvc) today — verified end-to-end on an RTX 2060 + CUDA Toolkit 11.7: a C+ program built against the package linked cudart/cublas and at runtime printed CUDA devices: 1. The FFI bindings are plain C symbols (cudaMalloc, cublasSgemm, …) identical across platforms, so no binding changes are needed.

This issue tracks the rough edges that make the Windows GPU experience require manual steps, plus a couple of small DX improvements. None block usage; they're polish toward "works out of the box."

Verified on Windows

  • Build: clanglld-link resolves -lcudart -lcublas against …\CUDA\vX.Y\lib\x64
  • Runtime: loads cudart64_*.dll / cublas64_*.dll (CUDA installer puts %CUDA_PATH%\bin on PATH) ✅
  • cuda/runtime::device_count() correctly reports the GPU ✅

Rough edges / proposed improvements

(a) cpc emits ELF-only -Wl,-rpath on Windows

[link] search-paths makes build_project push both -L<dir> and -Wl,-rpath,<dir> for every entry (two sites in cpc/src/main.rs). PE/Windows has no rpath — the DLL must be on PATH at run time — so lld-link prints:

lld-link: warning: ignoring unknown argument '-rpath'

Harmless, but noisy. Proposed: gate the -Wl,-rpath,<dir> push behind if !cfg!(windows) (keep -L<dir> on all platforms).

(b) [link] search-paths is not portable across SDK layouts

A search-path is an absolute, OS-specific string. NVIDIA's lib dir differs by platform:

  • Linux: /usr/local/cuda/lib64
  • Windows: %CUDA_PATH%\lib\x64 (version-specific, e.g. …\CUDA\v11.7\lib\x64)

So a single manifest can't serve both without hand-editing. Proposed: support ${VAR} env-var expansion in [link] search-paths (resolved in manifest.rs before the absolute/relative join). Then a package can ship a portable manifest, e.g.:

[link]
libs         = ["cudart", "cublas"]
search-paths = ["/usr/local/cuda/lib64", "${CUDA_PATH}/lib/x64"]

Non-existent dirs are harmless to -L, so listing both lets the same manifest work on Linux and Windows. (Unset ${VAR} → empty string.)

(c) vendor/cuda manifest + README are Unix-centric

vendor/cuda/Cplus.toml hardcodes search-paths = ["/usr/local/cuda/lib64"] and the README's rpath note ("no LD_LIBRARY_PATH needed") only describes the ELF runtime story. On Windows the user must (1) edit the path to …\lib\x64 and (2) rely on %CUDA_PATH%\bin being on PATH at run time (there's no rpath equivalent — binaries aren't self-contained). Proposed: once (b) lands, ship the cross-platform search-paths above and add a short "Windows" note to the README (lib path + DLLs-on-PATH at runtime).

(d) vendor/cblas Windows status unverified

vendor/cblas is the documented CPU fallback (docs/GPU.md). It hasn't been verified to build/link on Windows (OpenBLAS/MKL lib naming + search-paths likely hit the same (b)/(c) issues). Proposed: verify it builds against an OpenBLAS install on Windows; fold any findings back here.

Out of scope (per docs/GPU.md)

No Vulkan/DirectML/OpenCL — the SDK-consumer position keeps CUDA (NVIDIA) + Metal (Apple) + cblas/accelerate (CPU). For NVIDIA-on-Windows, CUDA is the complete and correct path; it already works.

Environment used for verification

  • GPU: NVIDIA GeForce RTX 2060 (driver 581.83)
  • CUDA Toolkit 11.7 (CUDA_PATH set), cudart.lib at …\CUDA\v11.7\lib\x64
  • Host: Windows 11, x86_64-pc-windows-msvc, clang 22

Context: follow-up to the Windows port (#3).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions