Как правильно использовать Anaconda Accelerate для GPU

Я пытаюсь получить быстрые вычисления матриц с ускорением анаконды. Я начал с очень простого примера: умножить 2 матрицы.

Моя цель - каким-то образом получить GPU-умножение, которое лучше обычного numpy.dot

Вот мой основной пример, основанный на этой документации.

from numbapro import guvectorize
from numpy import arange

@guvectorize(['void(float32[:,:], float32[:,:], float32[:,:])'], '(m,n),(n,p)->(m,p)', target='gpu')
def matmul(A, B, C):
    m, n = A.shape
    n, p = B.shape
    for i in range(m):
        for j in range(p):
            C[i, j] = 0
            for k in range(n):
                C[i, j] += A[i, k] * B[k, j]

import numpy as np
import time

for dim in [50, 100, 200]:
    rnd = np.random.RandomState(0)
    a = rnd.rand(dim, dim).astype(np.float32)
    b = rnd.rand(dim, dim).astype(np.float32)
    resgpu = np.zeros_like(a)

    start = time.time()
    rescpu = np.dot(a, b)
    print('CPU:', time.time() - start)

    start = time.time()
    resgpu = matmul(a, b)
    print('GPU:', time.time() - start)

    print(np.allclose(rescpu, resgpu))
    print(np.allclose(resgpu, rescpu))

Результаты слишком плохие: GPU невероятно медленнее, чем CPU

CPU: 0.00011801719665527344
GPU: 0.05677294731140137
True
True
CPU: 0.00011205673217773438
GPU: 0.3881375789642334
True
True
CPU: 0.00038933753967285156
GPU: 3.018171787261963
True
True

Конечно, я понимаю, что внутренняя реализация numpy хорошо оптимизирована, но я ожидал, что официальный пример anaconda будет хорошим. Я использую Python 3.4.3 и получил ошибки при использовании этих двух вспомогательных библиотек: http://www.cs.toronto.edu/~tijmen/gnumpy.html и https://github.com/rctn/gpupy

Я должен сказать, что с gpupy у меня было успешное ускорение на Python 2.7.

Итак, мой вопрос: как я могу получить умножение матриц лучше, чем numpy-CPU, используя GPU? Что не так с официальным примером Anaconda, и если есть рабочая библиотека для python 3, которая позволяет использовать GPU в тупик?

===

РЕЗУЛЬТАТЫ

К сожалению, нет простого и хорошего способа для Python 3, используйте 2.7 вместо

Спасибо @rth за рекомендацию поразительной библиотеки scikits.cuda

Доступные функции

Некоторые тесты (протестированы с использованием Anaconda MKL, поэтому NumPy тоже быстро)

dim = 10000
rnd = np.random.RandomState(0)
a = rnd.rand(dim, dim).astype(np.float32)
b = rnd.rand(dim, dim).astype(np.float32)
a_gpu = gpuarray.to_gpu(a)
b_gpu = gpuarray.to_gpu(b)

start = time.time()
rescpu = np.dot(a, b)
print 'CPU:', time.time() - start

start = time.time()
resgpu = culinalg.dot(a_gpu, b_gpu)
print 'GPU:', time.time() - start

resgpu = resgpu.get()
print np.allclose(rescpu, resgpu)
print np.allclose(resgpu, rescpu)

И результаты

CPU: 16.4765479565
GPU: 0.000520944595337

1 ответ

Решение

Вы должны взглянуть на реализации BLAS, которые предоставляют высоко оптимизированные подпрограммы для классических операций линейной алгебры. Умножение плотных матриц выполняется с gemm функция.

  • Например, умножение матриц в numpy значительно улучшается, если он скомпилирован с оптимизированной реализацией BLAS (OpenBLAS, ATLAS, MKL и т. д.).
  • Для графических процессоров NVIDIA предоставляет реализацию cuBLAS. Согласно этому ответу, он может быть вызван с использованием массивов scikits.cuda модуль. Anaconda ускоряет то, что вы используете, также обеспечивает прямую привязку к cuBLAS.

Кстати, если вы хотите сравнить производительность процессора и графического процессора для умножения матриц, вы должны также указать BLAS, используемый Numpy для вычислений процессора, так как результаты могут отличаться на порядок (см. Этот тест).

Другие вопросы по тегам