Использование операций с массивами NumPy с @guvectorize от Numba - PullRequest
0 голосов
/ 24 мая 2018

В последнее время я экспериментировал с Numba, и вот что я до сих пор не могу понять:

В обычной функции Python с массивами NumPy вы можете сделать что-то вроде этого:

# Subtracts two NumPy arrays and returns an array as the result
def sub(a, b):
    res = a - b
    return res

Но когда вы используете декоратор @guvectorize от Numba, вот так:

# Subtracts two NumPy arrays and returns an array as the result
@guvectorize(['void(float32[:], float32[:], float32[:])'],'(n),(n)->(n)')
def subT(a, b, res):
    res = a - b

Результат даже не правильный.Хуже того, есть случаи, когда он жалуется на «Неправильное использование [математического оператора] с [параметрами]»

Я сбит с толку.Даже если я попробую это:

# Subtracts two NumPy arrays and returns an array as the result
@guvectorize(['void(float32[:], float32[:], float32[:])'],'(n),(n)->(n)')
def subTt(a, b, res):
    res = np.subtract(a,b)

Результат по-прежнему неверен.Учитывая, что предполагается, что это поддерживаемая математическая операция , я не понимаю, почему она не работает.

Я знаю, что стандартный способ такой:

# Subtracts two NumPy arrays and returns an array as the result
@guvectorize(['void(float32[:], float32[:], float32[:])'],'(n),(n)->(n)')
def subTtt(a, b, res):
    for i in range(a.shape[0]):
        res[i] = a[i] - b[i]

и это работает, как и ожидалось.

Но что не так с моим путем?

P / S Это просто тривиальный пример, чтобы объяснить мою проблему, я нена самом деле планируем использовать @guvectorize только для вычитания массивов: PP / P / SI подозревают, что это как-то связано с тем, как массивы копируются в память gpu, но я не уверен ... P / P / P / S Это выглядело уместно, но функция здесь работает только на один поток справа ...

1 Ответ

0 голосов
/ 25 мая 2018

Правильный способ написать это:

@guvectorize(['void(float32[:], float32[:], float32[:])'],'(n),(n)->(n)')
def subT(a, b, res):
    res[:] = a - b

Причина, по которой вы пытались не сработать, заключается в ограничении синтаксиса python, не относящегося к numba.

name = expr связывает значение имени с expr, оно никогда не может изменить исходное значение имени, как вы могли бы, например, с помощью ссылок на c ++.

name[] = expr вызовов (по сути), name.__setitem__, который может быть использован для изменения имени, как в случае с пустыми массивами, пустой фрагмент [:] относится ко всему массиву.

...