diff --git a/httomo/cli.py b/httomo/cli.py index c35099ddc..cefee2830 100644 --- a/httomo/cli.py +++ b/httomo/cli.py @@ -16,7 +16,7 @@ from httomo.runner.pipeline import Pipeline from httomo.sweep_runner.param_sweep_runner import ParamSweepRunner from httomo.transform_layer import TransformLayer -from httomo.utils import log_exception, mpi_abort_excepthook +from httomo.utils import log_exception, log_once, mpi_abort_excepthook from httomo.yaml_checker import validate_yaml_config from httomo.runner.task_runner import TaskRunner from httomo.ui_layer import UiLayer, PipelineFormat @@ -312,21 +312,22 @@ def _set_gpu_id(gpu_id: int): try: import cupy as cp - gpu_count = cp.cuda.runtime.getDeviceCount() + if cp.cuda.is_available(): + gpu_count = cp.cuda.runtime.getDeviceCount() - if gpu_id != -1: - if gpu_id not in range(0, gpu_count): - raise ValueError( - f"GPU Device not available for access. Use a GPU ID in the range: 0 to {gpu_count} (exclusive)" - ) + if gpu_id != -1: + if gpu_id not in range(0, gpu_count): + raise ValueError( + f"GPU Device not available for access. Use a GPU ID in the range: 0 to {gpu_count} (exclusive)" + ) - cp.cuda.Device(gpu_id).use() - - httomo.globals.gpu_id = gpu_id - - except ImportError: - pass # silently pass and run if the CPU pipeline is given + cp.cuda.Device(gpu_id).use() + else: + log_once("CuPy is installed but the GPU device is inaccessible. Only CPU pipelines would work.") + httomo.globals.gpu_id = gpu_id + except ImportError as e: + log_exception(f"CuPy is not installed {e}. Only CPU pipelines would work.") def set_global_constants( out_dir: Path, diff --git a/httomo/method_wrappers/generic.py b/httomo/method_wrappers/generic.py index 766299fc0..a79ba2ae7 100644 --- a/httomo/method_wrappers/generic.py +++ b/httomo/method_wrappers/generic.py @@ -326,7 +326,7 @@ def execute(self, block: T) -> T: block = self._run_method(block, args) block = self._postprocess_data(block) - if xp.get_array_module(block.data).__name__ == "cupy": + if gpu_enabled: self._gpu_time_info.kernel = t.elapsed else: self._gpu_time_info.kernel = 0 diff --git a/httomo/method_wrappers/rotation.py b/httomo/method_wrappers/rotation.py index cf1f4a05a..172b27af3 100644 --- a/httomo/method_wrappers/rotation.py +++ b/httomo/method_wrappers/rotation.py @@ -2,11 +2,9 @@ from httomo.method_wrappers.generic import GenericMethodWrapper from httomo.runner.method_wrapper import MethodParameterDictType from httomo.runner.methods_repository_interface import MethodRepository -from httomo.utils import catchtime, log_once, xp +from httomo.utils import catchtime, log_once, xp, gpu_enabled from httomo_backends.methods_database.query import Pattern - - import numpy as np from mpi4py import MPI from mpi4py.MPI import Comm @@ -209,7 +207,8 @@ def _run_method(self, block: T, args: Dict[str, Any]) -> T: self._gpu_time_info.host2device += t.elapsed if not self.cupyrun: with catchtime() as t: - sino_slice = xp.asnumpy(sino_slice) + if gpu_enabled: + sino_slice = xp.asnumpy(sino_slice) self._gpu_time_info.device2host += t.elapsed args["ind"] = 0 args[self.parameters[0]] = sino_slice[:, xp.newaxis, :] diff --git a/httomo/sweep_runner/param_sweep_runner.py b/httomo/sweep_runner/param_sweep_runner.py index 336fa397b..3d1d61f93 100644 --- a/httomo/sweep_runner/param_sweep_runner.py +++ b/httomo/sweep_runner/param_sweep_runner.py @@ -20,9 +20,6 @@ from httomo.runner.gpu_utils import get_available_gpu_memory, gpumem_cleanup from httomo.preview import PreviewConfig, PreviewDimConfig from httomo.runner.dataset_store_interfaces import DataSetSource -from httomo_backends.methods_database.packages.backends.httomolibgpu.supporting_funcs.prep.phase import ( - _calc_memory_bytes_for_slices_paganin_filter, -) class ParamSweepRunner: @@ -312,12 +309,17 @@ def _preview_modifier( def _slices_to_fit_memory_Paganin(source: DataSetSource) -> int: """ Estimating the number of vertical slices that can fit on the device for running the Paganin method. + This function assumes that it is running on the GPU-enabled machine For the Paganin method, the filter kernel width can vary. Therefore, we aim to use the tallest possible vertical preview that the current device can accommodate. If the kernel width exceeds the height of the vertical preview, some deviations are expected between the sweep-run results and the results obtained from processing the full dataset. """ + from httomo_backends.methods_database.packages.backends.httomolibgpu.supporting_funcs.prep.phase import ( + _calc_memory_bytes_for_slices_paganin_filter, + ) + available_memory = get_available_gpu_memory(10.0) angles_total = source.aux_data.angles_length det_X_length = source.chunk_shape[2]