индексация cupy идет медленно

Я пытаюсь выполнять операции с большим массивом чашек размером 16000. Я считаю, что математические операции, такие как сложение, выполняются довольно быстро, но индексация с использованием булевых масок относительно медленная. Например, следующий код:

import cupy as cp
arr = cp.random.normal(0, 1, 16000)
%timeit arr * 5
%timeit arr > 0.4
%timeit arr[arr > 0.4] = 0

дает мне вывод:

28 µs ± 950 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
26.5 µs ± 1.61 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
104 µs ± 2.6 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Есть ли причина, по которой окончательная индексация выполняется как минимум в два раза медленнее? Я предположил, что умножение должно быть медленнее, чем установка элементов массива.

Обновление: это неверно для индексации numpy. Изменив массив cupy на numpy, я получаю:

6.71 µs ± 373 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
4.42 µs ± 56.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
5.39 µs ± 29.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

person Arani    schedule 02.05.2020    source источник


Ответы (1)


В третьем случае cupy составляет результат с помощью последовательности операций: cupy_greater, cupy_copy, inclusive_scan_kernel, inclusive_scan_kernel, add_scan_blocked_sum_kernel, CUDA memcpy DtoH (возможно, чтобы указать количество элементов, которые необходимо обнулить), CUDA memset (возможно, чтобы установить массива в ноль) и, наконец, cupy_scatter_update_mask (возможно, чтобы расставить нули по своим местам).

Это значительно более сложная последовательность, чем arr*5, которая, кажется, запускает одну cupy_multiply под капотом. Возможно, вы добьетесь большего успеха с cupy определяемым пользователем ядром. :

import cupy as cp
clamp_generic = cp.ElementwiseKernel(
        'T x, T c',
        'T y',
        'y = (y > x)?c:y',
        'clamp_generic')
arr = cp.random.normal(0, 1, 16000)
clamp_generic(0.4, 0, arr)
person Robert Crovella    schedule 02.05.2020
comment
Спасибо - это решило это. Запуск «timeit» на «clamp_generic» дает мне всего 6,12 мкс ± 149 нс на цикл. - person Arani; 03.05.2020