I have a code which I got from Numpy repeat for 2d array
Below one works fine with numpy array but throws
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() when using with cupy arrays.
For the line ret_val[mask] = cp.repeat(arr.ravel(), rep.ravel()
I have tried to use logical operations already existing in cupy but they still throw errors.
def repeat2dvect(arr, rep):
lens = cp.array(rep.sum(axis=-1))
maxlen = lens.max()
ret_val = cp.zeros((arr.shape[0], int(maxlen)))
mask = (lens[:,None]>cp.arange(maxlen))
ret_val[mask] = cp.repeat(arr.ravel(), rep.ravel())
return ret_val
Conguratulations on the first contribution to the StackOverflow :)
I replicated the error with the following code:
import cupy as cp
arr = cp.array([5, 1, 4], 'float32')
rep = cp.array([3, 2], 'int32')
result = cp.repeat(arr, rep)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
This error message is kind of misleading: the reason why this code doesn't work is something quite different.
In short, you can't pass cp.ndarray
as the second argument of cp.repeat()
.
Why? That's because the shape of result
is determined based on the value of that argument.
If it were an ndarray
, it would be problematic in CuPy (but not in NumPy) because the value of the array is in the GPU. In order to determine the output shape, CuPy would have to wait for the GPU to finish all of the queued computations, and then transfer the value to CPU. That would simply spoil the benefit of asynchronous computation. CuPy intentionally prohibits such operation.
In your particular case, you could for example manually convert rep
to np.ndarray
(by ret.get()
) or calculate rep
as np.ndarray
from the beginning.