Source code for mantidimaging.core.utility.cuda_check
# Copyright (C) 2022 ISIS Rutherford Appleton Laboratory UKRI
# SPDX - License - Identifier: GPL-3.0-or-later
import subprocess
from logging import getLogger
from typing import Tuple
LOG = getLogger(__name__)
NVIDIA_SMI = "nvidia-smi"
LOCATE = "locate"
EXCEPTION_MSG = "Error when attempting to run"
def _read_from_terminal(command: str) -> str:
"""
Runs a terminal command and returns the output.
"""
return subprocess.check_output(command + "; exit 0", shell=True, stderr=subprocess.STDOUT).decode("ascii")
def _cuda_is_present() -> bool:
"""
Checks if nvidia-smi is on the system + working, and that the libcuda files can be located.
"""
nvidia_smi_working = libcuda_files_found = True
try:
nvidia_smi_output = _read_from_terminal(NVIDIA_SMI)
if "Driver Version" not in nvidia_smi_output:
nvidia_smi_working = False
LOG.error(nvidia_smi_output)
except Exception as e:
LOG.error(f"{EXCEPTION_MSG} {NVIDIA_SMI}: {e}")
nvidia_smi_working = False
try:
if _read_from_terminal(f"{LOCATE} --regex '^/usr/(lib|lib64)/(.*?)/libcuda.so'") == "":
libcuda_files_found = False
LOG.error("Search for libcuda files returned no results.")
except Exception as e:
LOG.error(f"{EXCEPTION_MSG} {LOCATE}: {e}")
libcuda_files_found = False
return nvidia_smi_working and libcuda_files_found
[docs]
def not_found_message() -> Tuple[str, str]:
"""
Generates a message that can be displayed if a working CUDA installation isn't found.
"""
cuda_not_found_msg = "Working CUDA installation not found."
return cuda_not_found_msg, cuda_not_found_msg + " Will only use gridrec algorithm for reconstruction.",
[docs]
class CudaChecker:
_instance = None
_cuda_is_present = False
def __new__(cls):
"""
Creates a singleton for storing the result of the Cuda check.
"""
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._cuda_is_present = _cuda_is_present()
return cls._instance
[docs]
@classmethod
def cuda_is_present(cls) -> bool:
"""
Returns the shared cuda check result.
"""
return cls._cuda_is_present
[docs]
@classmethod
def clear_instance(cls):
"""
Resets the instance. Used for making sure mocks don't leak in tests.
"""
cls._instance = None