Cupy медленнее чем NumPy - PullRequest
       20

Cupy медленнее чем NumPy

0 голосов
/ 04 июля 2018

Я пытался ускорить мой код на python с помощью cupy, а не numpy. Проблема в том, что при использовании cupy мой код стал значительно медленнее. Может быть, я немного наивен в этой проблеме.

Может быть, кто-нибудь может найти узкое место в моем коде:

import cupy as np
import time as ti

def f(y, t):
    y_ = np.zeros(2 * N_1*N_2) # n: e-6, c: e-5
    for i in range(0, N_1*N_2):
        y_[i] = y[i + N_1*N_2] # n: e-7, c: e-5 or e-6
    for i in range(N_1*N_2):
        sum = -4*y[i] # n: e-7, c: e-7 after some statements e-5
        if (i + 1 in indexes) and (not (i in indi)):
            sum += y[i+1] # n: e-7, c: e-7 after some statements e-5
        if (i - 1) in indexes and (i % N_1 != 0):
            sum += y[i-1] # n: e-7, c: e-7 after some statements e-5
        if i + N_1 in indexes:
            sum += y[i+N_1] # n: e-7, c: e-7 after some statements e-5
        if i - N_1 in indexes:
            sum += y[i-N_1] # n: e-7, c: e-7 after some statements e-5
        y_[i + N_1*N_2] = sum

    return y_

def k_1(y, t, h):
    return np.asarray(f(y, t)) * h

def k_2(y, t, h):
    return np.asarray(f(np.add(np.asarray(y) , np.multiply(1/2 , k_1(y, t, h))), t + 1/2 * h)) * h

# k_2, k_4 look just like k_2, may be with an 1/2 here or there

# some init stuff is happening here

while t < T_end:
    # also some magic happening here which is just data saving
    y = np.asarray(y) + 1/6*(k_1(y, t, m) + 2*k_2(y, t, m) + 2*k_3(y, t, m) + k_4(y, t, m))
    t += m

EDIT Я попытался сравнить мой код, и вот некоторые результаты, которые можно увидеть как комментарий в коде. Каждый номер остается на одной строке. Единицами являются секунды. n: Numpy, c: CuPy, я в основном даю приблизительную оценку порядка. Дополнительно я протестировал

np.multiply # n: e-6, c: e-5

и

np.add # n: e-5 or e-6, c: 0.005 or e-5

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Ваш код не медленный, потому что numpy медленный, а потому что вы вызываете многие (python) функции, а вызовы функций (и итерации и доступа к объектам и в основном ко всему в python) медленны в python. Таким образом, cupy не поможет вам (но, вероятно, повредит производительности, потому что он должен выполнять больше настроек, например копировать данные в gpu). Если вы можете сформулировать свой алгоритм, чтобы использовать меньше функций Python (векторизация, как в другом ответе), это значительно ускорит ваш код (вам, вероятно, не нужен cupy).

Вы также можете взглянуть на numba , которая компилирует ваш код с помощью llvm в нативный код. Если вы это сделаете, обязательно прочитайте некоторую документацию и используйте nopython=True, в противном случае вы переключите медленный код чашки только с медленным кодом Numba.

0 голосов
/ 04 июля 2018

Ваш пример кода не работает, поскольку вы нигде не определили N_1, N_2, indexes и indi. Кроме того, ваши комментарии в коде, похоже, не помогают другим понять, что происходит. Ваш код, вероятно, не выиграет от numba / cupy, поскольку вы не векторизовали операции в своем коде. Списки, вероятно, будут такими же быстрыми, как и пустые массивы, в том виде, в котором ваш код работает в данный момент.

Если вы избавитесь от циклов for и измените

y_ = np.zeros(2 * N_1*N_2)
for i in range(0, N_1*N_2):
    y_[i] = y[i + N_1*N_2] 

до

n = N1*N2
y_ = np.zeros(2*n)
y_[:n] = y[n:2*n]

и т. Д., Вы существенно ускорите свой код.

...