Search code examples
pythonarrayscupy

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() when using cupy array


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

Solution

  • 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.