diff --git a/c/Makefile b/c/Makefile index e794d4b..b04cf63 100644 --- a/c/Makefile +++ b/c/Makefile @@ -105,10 +105,30 @@ INSTALL ?= install # clean. See backend_loader.c and README "cuda-dll" below. CUDA ?= 0 CUDA_DLL ?= 0 +ifneq ($(IS_WIN),) +# the CUDA installer sets CUDA_PATH system-wide (e.g. C:\Program Files\NVIDIA +# GPU Computing Toolkit\CUDA\v13.2); fall back to it before the POSIX default. +# NVCC defaults to plain `nvcc` from PATH: CUDA_PATH contains spaces, which the +# unquoted recipe checks cannot survive — and the cuda-dll recipe already +# requires an MSVC environment (vcvars64) on PATH, so requiring the CUDA bin +# directory too is symmetric. The installer adds it by default. +CUDA_HOME ?= $(subst \,/,$(CUDA_PATH)) +NVCC ?= nvcc +else CUDA_HOME ?= /usr/local/cuda NVCC ?= $(CUDA_HOME)/bin/nvcc +endif CUDA_ARCH ?= native +ifneq ($(IS_WIN),) +# nvcc's host compiler on Windows is MSVC cl.exe: the GCC-style +# -Xcompiler=-Wall,-Wextra is rejected ("D8021 invalid numeric argument +# '/Wextra'"), which made `make cuda-dll` unbuildable as shipped. -W3 is +# the MSVC warning level (dash form, NOT /W3: MSYS make would mangle the +# slash-form into a filesystem path). +NVCCFLAGS ?= -O3 -std=c++17 -arch=$(CUDA_ARCH) -Xcompiler=-W3 +else NVCCFLAGS ?= -O3 -std=c++17 -arch=$(CUDA_ARCH) -Xcompiler=-Wall,-Wextra +endif ifeq ($(IS_WIN),) PYTHON ?= python3 else @@ -169,7 +189,7 @@ backend_loader.o: backend_loader.c backend_cuda.h compat.h # compiler, required by nvcc on Windows) into coli_cuda.dll. Run this from a # shell that has the MSVC environment set (e.g. after vcvars64.bat, or from a # "x64 Native Tools Command Prompt"). COLI_CUDA_BUILDING_DLL enables -# __declspec(dllexport) so the 11 API symbols are exported. +# __declspec(dllexport) so the 15 API symbols are exported. cuda-dll: backend_cuda.cu backend_cuda.h @command -v $(NVCC) >/dev/null 2>&1 || { echo "nvcc not found: set CUDA_HOME or NVCC" >&2; exit 1; } @command -v cl >/dev/null 2>&1 || { echo "cl.exe (MSVC) not in PATH — run vcvars64.bat first" >&2; exit 1; } diff --git a/c/glm.c b/c/glm.c index 8b061db..498a927 100644 --- a/c/glm.c +++ b/c/glm.c @@ -1497,7 +1497,12 @@ static void expert_host_release(Model *m, ESlot *s){ if(s->fslab) compat_munlock(s->fslab,(size_t)s->fslab_cap*sizeof(float)); #endif int64_t bytes=qt_bytes(&s->g)+qt_bytes(&s->u)+qt_bytes(&s->d); - free(s->slab); free(s->fslab); s->slab=NULL; s->fslab=NULL; s->slab_cap=s->fslab_cap=0; + /* slab is posix_memalign'd: on Windows that is _aligned_malloc, and plain + * free() corrupts the CRT heap (0xC0000374) — same bug the compat.h audit + * fixed at the original expert_load site. fslab is plain malloc/falloc + * on the CPU path, so its free() stays plain (Metal path frees it before + * re-alloc and never reaches here with an aligned fslab on _WIN32). */ + compat_aligned_free(s->slab); free(s->fslab); s->slab=NULL; s->fslab=NULL; s->slab_cap=s->fslab_cap=0; QT *q[3]={&s->g,&s->u,&s->d}; for(int k=0;k<3;k++){ q[k]->qf=NULL; q[k]->q8=NULL; q[k]->q4=NULL; q[k]->s=NULL; } m->resident_bytes-=bytes; if(m->resident_bytes<0) m->resident_bytes=0; diff --git a/c/tests/test_backend_cuda.cu b/c/tests/test_backend_cuda.cu index 58ef250..a9eb48f 100644 --- a/c/tests/test_backend_cuda.cu +++ b/c/tests/test_backend_cuda.cu @@ -5,6 +5,14 @@ #include #include +#ifdef _WIN32 +/* MSVC has no POSIX setenv/unsetenv */ +static int setenv(const char *name, const char *value, int overwrite) { + (void)overwrite; return _putenv_s(name, value); +} +static int unsetenv(const char *name) { return _putenv_s(name, ""); } +#endif + static int close_enough(const float *got, const float *want, int n) { for (int i = 0; i < n; i++) { if (std::fabs(got[i] - want[i]) > 1e-4f) {