медленное индексирование медленно - PullRequest
0 голосов
/ 03 мая 2020

Я пытаюсь выполнить операции с большим массивом типа 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)

1 Ответ

1 голос
/ 03 мая 2020

В третьем случае 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)
...