I'm writing a module that will use CuPy (an implementation of the Numpy and Scipy APIs using CUDA) for fast analysis of data my workplace works with, but I want the functions to be usable on computers that don't have access to CuPy. I was considered just doing something like:
try:
import cupy as np
import cupyx.scipy as scipy
except ModuleNotFoundError:
import numpy as np
import scipy
But this doesn't really work for a few reasons. First, it only covers the case that cupy isn't installed, but not that cupy is installed but CUDA isn't working or the GPU can't be detected for whatever reason. Also, cupy isn't a perfect drop-in replacement for numpy, for example when passing a cupy array to a non-cupy function that takes a numpy array, you need to call .get() as cupy generates an error instead of doing implicit conversion to numpy.
Is the best way just to add a "use_gpu" parameter to every function, and then have if statements checking that parameter and doing the numpy or cupy specific code where necessary? So for example:
import numpy # Sometimes we want to use a numpy function even if CuPy is available
try:
import cupy as np
except ModuleNotFoundError:
import numpy as np
print("CuPy not available, only use_gpu=False will work")
import pandas as pd
def some_function(arg1, arg2, use_gpu=True):
"""Just some example function doing something arbitrary."""
x = np.func1(arg1)
y = np.func2(arg2)
res = np.hstack(x, y)
if use_gpu:
return pd.DataFrame(res.get())
else:
return pd.DataFrame(res)
Is there a more elegant way to do this?