Installing Pytorch with Python 3.10 for CUDA on NVIDIA TITAN BLACK

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.