Coverage for src / quber / utils / cuda_runtime.py: 85%
20 statements
« prev ^ index » next coverage.py v7.14.0, created at 2026-09-23 22:14 -0400
« prev ^ index » next coverage.py v7.14.0, created at 2026-09-23 22:14 -0400
1"""
2Eagerly preload the CUDA 12 runtime shared libraries bundled by the
3`nvidia-*-cu12` wheels so that `onnxruntime-gpu`'s `CUDAExecutionProvider`
4can resolve them via `dlopen`.
6Why this exists
7---------------
8`onnxruntime-gpu` (>=1.26.0) is built against CUDA 12. On hosts running
9CUDA 13 (driver 580+) the system loader cannot find `libcublasLt.so.12`,
10`libcudnn.so.9`, etc. — and `CUDAExecutionProvider` silently falls back
11to CPU. The `nvidia-*-cu12` pip wheels install the libraries under
12`<site-packages>/nvidia/<pkg>/lib/`, but the dynamic linker does not
13search those paths by default and the wheels do not register them.
15`ctypes.CDLL(path, RTLD_GLOBAL)` at import time makes the libraries'
16symbols available to subsequent `dlopen` calls from onnxruntime, without
17requiring callers to export `LD_LIBRARY_PATH`.
19This is best-effort: a CPU-only environment without the `nvidia-*-cu12`
20wheels installed will skip the preload silently. RapidOCR will then run
21on CPU as before — extraction still works, just slower.
22"""
24from __future__ import annotations
26import ctypes
27import sys
28from pathlib import Path
30_CUDA_LIB_SONAMES = (
31 "libcublasLt.so.12",
32 "libcublas.so.12",
33 "libcurand.so.10",
34 "libcufft.so.11",
35 "libcudart.so.12",
36 "libcudnn.so.9",
37)
40def preload_cuda_runtime_libs() -> list[str]:
41 """Preload CUDA 12 sonames from the `nvidia-*-cu12` pip wheels.
43 Returns the list of soname strings that were successfully loaded.
44 Silent on missing wheels (CPU-only environments) and on individual
45 `OSError`s during `dlopen`.
46 """
47 site_packages = (
48 Path(sys.prefix)
49 / "lib"
50 / f"python{sys.version_info.major}.{sys.version_info.minor}"
51 / "site-packages"
52 )
53 nvidia_root = site_packages / "nvidia"
54 if not nvidia_root.is_dir():
55 return []
57 loaded: list[str] = []
58 for soname in _CUDA_LIB_SONAMES:
59 for path in nvidia_root.rglob(soname):
60 try:
61 ctypes.CDLL(str(path), mode=ctypes.RTLD_GLOBAL)
62 loaded.append(soname)
63 break
64 except OSError:
65 continue
66 return loaded