Hello all.
I have spent a little time, helped with Claude in VS Code, connected through a WSL Ubuntu on my Windows machine, to have my old NVIDIA TITAN BLACK work well. Python 3 didn’t work well, gcc compiler version was too recent, lots of problems that Claude mastered through 4-5 days of debugging, one command at a time after my current work.
If useful for anyone, here is the result successful config.
By the way, a TAR upload for the project including compiled whl is available here :
mega.nz/file/BcsHEKab
With key = 6_9bGyOYvDOEoxmV9QXNwZvw0lJUTkOUMG2HppvWSYo
Checksum :
sha256sum torch-1.12.0a0+git664058f-cp310-cp310-linux_x86_64.whl
# has to result to : 1e8b423910dcf33b9286f27180066aeda0d1dda1ae2a0e0ebb273c1ce4b1c931
PyTorch built from source with CUDA for Kepler (GTX Titan Black, sm_35) on WSL2 Ubuntu 24.04 — success writeup
Compiled PyTorch 1.12.1 from source with TORCH_CUDA_ARCH_LIST=3.5 for a GTX Titan Black (Kepler, sm_35) under WSL2 / Ubuntu 24.04. Official PyPI wheels (1.12.1+cu113, +cu102) do NOT work anymore — Kepler kernels dropped from official builds (CUDA error: no kernel image is available for execution on the device). Only fix: compile from source. Working .whl produced and validated: torch.cuda.is_available() == True, matmul on GPU OK.
Working version matrix
| Component | Version | Notes |
|---|---|---|
| GPU | GTX Titan Black | Kepler, compute capability 3.5 |
| Driver | 470.256.02 | R470 legacy branch — last to support Kepler. Do not upgrade. |
| OS | Ubuntu 24.04 (noble), WSL2 | |
| CUDA toolkit | 10.2 | Installed via runfile, not apt |
| Host compiler | GCC 8.5.0 | Via conda-forge (miniforge), no root needed |
| Linker | System ld 2.42 |
GCC8-conda’s own ld (2.36.1) too old for RELR relocations in glibc 2.39 |
| Python | 3.10.20 | venv, PyTorch 1.12.1 doesn’t support 3.12 (Ubuntu 24.04 default) |
| cmake | 3.22.6 | Newer cmake 4.x breaks on protobuf’s old cmake_minimum_required |
| ninja | 1.13.0 | |
| numpy (build+runtime) | 2.2.6 | Needed 1-line source patch, see below |
| PyTorch source | tag v1.12.1, commit 664058f | USE_NCCL=0, USE_DISTRIBUTED=0 (single GPU, NCCL build system ignores host compiler override) |
Output: torch-1.12.0a0+git664058f-cp310-cp310-linux_x86_64.whl, ~159MB, 9925 files.
Build environment (exported before any cmake/build command)
export CC=/home/user/gcc8-wrapper/gcc
export CXX=/home/user/gcc8-wrapper/g++
export CUDA_HOME=/usr/local/cuda-10.2
export CUDACXX=/usr/local/cuda-10.2/bin/nvcc
export CUDAHOSTCXX=/home/user/gcc8-wrapper/g++
export LD_LIBRARY_PATH=/usr/local/cuda-10.2/extras/CUPTI/lib64:/usr/local/cuda-10.2/lib64:$LD_LIBRARY_PATH
export TORCH_CUDA_ARCH_LIST="3.5"
export USE_CUDA=1
export USE_NCCL=0
export USE_DISTRIBUTED=0
export MAX_JOBS=8
Note: when reconfiguring with cmake .., pass BOTH -DCUDA_HOST_COMPILER= (PyTorch’s own var) AND -DCMAKE_CUDA_HOST_COMPILER= (native CMake var) → both must point to the gcc8 wrapper. One without the other is not enough.
Problems hit and fixed
1. CUDA 10.2 rejects host compiler > GCC 8
#error -- unsupported GNU version! in host_config.h. --allow-unsupported-compiler doesn’t exist in nvcc 10.2 (only from CUDA 11.x). Ubuntu 24.04 has no gcc-8 in apt → installed GCC 8.5.0 via conda-forge (relocatable, no root).
2. conda-forge GCC8’s linker too old for glibc 2.39 (RELR)
Wrapper script forces gcc8 to use the system linker via -B/usr/bin.
3. cuBLAS silently missing after CUDA 10.2 runfile install
Runfile install (no root) failed to copy cuBLAS. Extracted manually from the runfile, copied with sudo cp into /usr/local/cuda-10.2/targets/x86_64-linux/lib/.
4. pyconfig.h multiarch not found (~915/4514 objects)
/usr/include/python3.10/pyconfig.h:3:12: fatal error: x86_64-linux-gnu/python3.10/pyconfig.h: No such file or directory
Root cause: conda-forge gcc8’s target triplet is x86_64-conda-linux-gnu, its own sysroot doesn’t include Ubuntu’s real /usr/include. --sysroot=/ alone breaks other headers in cascade. Fix: wrapper adds -isystem /usr/include only when compiling a file that references python3.10 (avoid touching the ~750 already-compiled objects against the conda sysroot).
5. numpy 2.x ABI break in tensor_numpy.cpp (~29/3512 on torch_python target)
tensor_numpy.cpp:341:34: error: 'PyArray_Descr' has no member named 'elsize'
numpy 2.0 made PyArray_Descr->elsize private. PyTorch 1.12.1 predates that. Fix: descr->elsize → PyDataType_ELSIZE(descr) (macro from npy_2_compat.h, already transitively included, no extra #include needed). This is the same fix upstream PyTorch later applied.
6. libcupti.so.10.2 not found at link time (blocked at 3128/3210, near the end)
undefined reference to `cuptiEventGroupGetAttribute@libcupti.so.10.2'
Real wheel libs (libtorch.so, libtorch_cpu.so, libtorch_cuda.so) had already linked fine — only gtest test binaries were blocked. Cause: libcupti.so.10.2 lives in extras/CUPTI/lib64, a subfolder never in LD_LIBRARY_PATH. Kineto (profiler, USE_KINETO) links against it by SONAME only. Fix: add /usr/local/cuda-10.2/extras/CUPTI/lib64 to LD_LIBRARY_PATH. No cmake reconfigure needed.
Runtime dependency notes (this wheel is NOT manylinux-portable)
No auditwheel vendoring was done — the wheel dynamically depends on absolute paths from the build machine:
| Library | Required path | Source |
|---|---|---|
libcudart.so.10.2, libcublas.so.10, libcublasLt.so.10, libcufft.so.10, libcurand.so.10, libcusparse.so.10, libnvToolsExt.so.1 |
/usr/local/cuda-10.2/lib64/ |
CUDA 10.2 toolkit |
libcupti.so.10.2 |
/usr/local/cuda-10.2/extras/CUPTI/lib64/ |
CUDA 10.2 CUPTI |
libstdc++.so.6, libgcc_s.so.1, libgomp.so.1 |
conda-forge GCC 8.5.0 runtime, not Ubuntu system libs | miniforge gcc8 env |
To reuse the wheel elsewhere: Python 3.10 (cp310 tag), Kepler GPU + R470 driver, CUDA 10.2 toolkit (incl. CUPTI subfolder), the 3 GCC8 runtime .so files, numpy 2.2.6 (untested below 2.x), and:
export LD_LIBRARY_PATH=/usr/local/cuda-10.2/extras/CUPTI/lib64:/usr/local/cuda-10.2/lib64:/path/to/gcc8/lib:$LD_LIBRARY_PATH
Validation
import torch
torch.cuda.is_available() # True
torch.cuda.get_device_name(0) # 'NVIDIA GeForce GTX TITAN Black'
torch.cuda.get_device_capability(0) # (3, 5)
# matmul on GPU: OK
Benign noise to ignore in nvidia-smi on this setup: WARNING: infoROM is corrupted, ERR! on fan/temp/power — known WSL2 telemetry limitation, not a hardware fault.