2015-06-14 7 views
4

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

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

Вот мой основной пример, основанный на этом documentation.

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 хорошо оптимизирован, но я ожидал анаконды официальный пример, чтобы быть хорошим. Я использую питон 3.4.3 и получил ошибки с помощью этих двух помогая LIBS: http://www.cs.toronto.edu/~tijmen/gnumpy.html и https://github.com/rctn/gpupy

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

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

===

РЕЗУЛЬТАТЫ

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

Благодаря @rth для recommendint удивительной библиотеки scikits.cuda

Available functions

Некоторые ориентиры (Проверено с помощью анаконды МКЛ, так 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

Обратите внимание, что копирование данных с и из графического процессора является дорогостоящим. Поэтому 'gpuarray.to_gpu' должен находиться внутри раздела с таймированием, а затем я полагаю, что время GPU будет немного выше. – rth

+0

Глядя на ваши тайминги, я подозреваю, что culinalg.dot работает асинхронно, т. Е. Вам нужно синхронизировать(), в противном случае графический процессор все еще вычисляет во время вашего отчета «GPU:». С вашими размерами, я получаю улучшение в 5 раз на GPU (Tesla K40, работает в 600 мс без передачи данных) по сравнению с CPU (MKL, 28 ядер). В отличие от вашей установки, я использую numbapro.cudalib.Blas и do numba.cuda.synchronize(). –

ответ

3

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

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

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

+0

ну, нет функции dgemm в numbapro cublas (http://docs.continuum.io/numbapro/cudalib.html), некоторые похожие имена, но они имеют дело с диагональными матрицами, и это не то, что мне нужно. Я попробовал scikits.cuda, но опять же, как ранее отмечали libs (например, gpupy), есть неподдерживаемый python3 http://scikit-cuda.readthedocs.org/en/latest/install.html#installation-dependencies. Похоже, мне нужно использовать python 2 в любом случае, python 3 все еще сырой в 2015 году ... – budmitr

+0

@Apfel См. 'Numbapro.cudalib.cublas.Blas.gemm' в вашей ссылке комментариев: это должно работать. 'd' в' dgemm' означает 'double', поэтому они, вероятно, сбросили его. Нет причин, по которым он не будет работать с python 3. Помимо некоторых исключений, большинство серьезных модулей поддерживают как 3.x, так и 2.7 на данный момент. – rth

+1

ну, после того, как я протестировал scikits.cuda на python 2.7. Я счастлив, как сумасшедший. Он превосходит numpy в отличном ключе с очень симпатичным синтаксисом, как чистый numpy. Эта библиотека имеет активную поддержку и больше, она превосходит gpupy, который я тестировал раньше. Также доступно количество доступных математических функций (http://scikit-cuda.readthedocs.org/en/latest/reference.html#reference). Большое спасибо! это то, что я искал. Единственное, что python 3 сейчас непригодным для использования – budmitr

Смежные вопросы