Return True when an NVIDIA GPU is present and usable. Primary probe: nvidia-smi -L (subprocess). Fallback: /proc/driver/nvidia/gpus/ sysfs (Linux only) -- handles the case where nvidia-smi is present but the subprocess fails (PATH gap, timeout, driver initialisation race). If either
()
| 816 | |
| 817 | |
| 818 | def _has_usable_nvidia_gpu() -> bool: |
| 819 | """Return True when an NVIDIA GPU is present and usable. |
| 820 | |
| 821 | Primary probe: nvidia-smi -L (subprocess). |
| 822 | Fallback: /proc/driver/nvidia/gpus/ sysfs (Linux only) -- handles the |
| 823 | case where nvidia-smi is present but the subprocess fails (PATH gap, |
| 824 | timeout, driver initialisation race). If either probe confirms an |
| 825 | NVIDIA GPU the function returns True so _has_rocm_gpu() is blocked. |
| 826 | |
| 827 | CUDA_VISIBLE_DEVICES set to "" or "-1" hides every NVIDIA device (mixed |
| 828 | AMD+NVIDIA hosts steering work to the AMD card); neither probe honours |
| 829 | that env var, so check it first and report the GPU as not usable. Unset |
| 830 | means all devices visible. |
| 831 | """ |
| 832 | cvd = os.environ.get("CUDA_VISIBLE_DEVICES") |
| 833 | if cvd is not None and cvd.strip() in ("", "-1"): |
| 834 | return False |
| 835 | exe = shutil.which("nvidia-smi") |
| 836 | if exe: |
| 837 | try: |
| 838 | result = subprocess.run( |
| 839 | [exe, "-L"], |
| 840 | stdout = subprocess.PIPE, |
| 841 | stderr = subprocess.DEVNULL, |
| 842 | text = True, |
| 843 | timeout = 10, |
| 844 | ) |
| 845 | if result.returncode == 0 and "GPU " in result.stdout: |
| 846 | return True |
| 847 | except Exception: |
| 848 | pass |
| 849 | # Fallback: the NVIDIA driver exposes one subdirectory per GPU under |
| 850 | # /proc/driver/nvidia/gpus/ on Linux regardless of nvidia-smi state. |
| 851 | if sys.platform != "win32": |
| 852 | try: |
| 853 | gpu_dir = "/proc/driver/nvidia/gpus" |
| 854 | if os.path.isdir(gpu_dir) and os.listdir(gpu_dir): |
| 855 | return True |
| 856 | except OSError: |
| 857 | pass |
| 858 | return False |
| 859 | |
| 860 | |
| 861 | def _detect_amd_gfx_codes() -> list[str]: |
no test coverage detected
searching dependent graphs…