【问题标题】:How to properly use anaconda accelerate for GPU如何正确使用 anaconda 加速 GPU
【发布时间】:2015-08-30 06:49:45
【问题描述】:

我正在尝试使用 anaconda 加速来快速计算矩阵。我从非常基本的示例开始:将 2 个矩阵相乘。

我的目标是以某种方式获得比通常的 numpy.dot 更好的 GPU 乘法

这是我的基本示例,基于 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实现已经很好地优化了,但是我希望anaconda官方的例子很好。我正在使用 python 3.4.3 并在使用这两个帮助库时出错:http://www.cs.toronto.edu/~tijmen/gnumpy.htmlhttps://github.com/rctn/gpupy

我应该说使用 gpupy 我在 python 2.7 上成功加速。

所以我的问题是:如何通过使用 GPU 获得比 numpy-CPU 更好的矩阵乘法? anaconda 官方示例有什么问题,是否有一个允许以 numpy 方式使用 GPU 的 python3 工作库?

===

结果

很遗憾,python 3没有简单好办法,改用2.7吧

感谢@rth 推荐了很棒的库scikits.cuda

Available functions

一些基准测试(使用 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

【问题讨论】:

  • 请注意,将数据复制到 GPU 和从 GPU 复制数据的成本很高。所以gpuarray.to_gpu应该在timed部分里面,然后我想GPU时间会高一点。
  • 查看您的时间,我怀疑 culinalg.dot 正在异步运行,即您需要 synchronize(),否则 GPU 在您的打印“GPU:”语句期间仍在计算。与您的尺寸相比,与 CPU(MKL,28 核)相比,我在 GPU(Tesla K40,运行时间为 600 毫秒,没有数据传输)上获得了约 5 倍的改进。与您的设置相反,我使用的是 numbapro.cudalib.Blas 并执行 numba.cuda.synchronize()。

标签: numpy python-3.4 anaconda numba-pro


【解决方案1】:

您应该了解为经典线性代数运算提供高度优化的例程的 BLAS 实现。使用gemm 函数执行稠密矩阵的乘法。

  • 例如,如果针对优化的 BLAS 实现(OpenBLAS、ATLAS、MKL 等)进行编译,numpy 中的矩阵乘法将得到显着改进。
  • 对于 GPU,NVIDIA 提供了 cuBLAS 实现。根据这个answer,可以使用scikits.cuda 模块使用numpy 数组调用它。您正在使用的Anaconda accelerate 还提供与 cuBLAS 的直接绑定。

顺便说一句,如果您想对矩阵乘法的 CPU 和 GPU 性能进行基准测试,您还应该指定 Numpy 用于 CPU 计算的 BLAS,因为结果可能相差一个数量级(请参阅this benchmark)。

【讨论】:

  • 嗯,numbapro cublas (docs.continuum.io/numbapro/cudalib.html) 中没有 dgemm 函数,一些类似的名称,但它们处理对角矩阵,这有点不是我需要的。我尝试了 scikits.cuda,但同样,正如前面提到的库(如 gpupy),python3 scikit-cuda.readthedocs.org/en/latest/… 不受支持。看来我无论如何都需要使用 python 2,python 3 在 2015 年仍然是原始的......
  • @Apfel 请参阅您的 cmets 链接中的 numbapro.cudalib.cublas.Blas.gemm:应该可以。 d in dgemm 代表 double 所以他们可能放弃了它。它没有理由不能与 python 3 一起使用。除了少数例外,大多数严重的模块目前都支持 3.x 和 2.7。
  • 好吧,在我在 python 2.7 上测试了 scikits.cuda 之后,我高兴得像个疯子。它确实以非常可爱的语法超越了 numpy,就像纯 numpy 一样。这个库有积极的支持,而且它确实优于我之前测试过的 gpupy。可用数学函数的数量也不错 (scikit-cuda.readthedocs.org/en/latest/reference.html#reference)。万分感谢!这有点像我想要的。唯一的问题是python 3暂时无法使用
  • 你是对的,install.rst 声明“包的某些部分可能不适用于 Python 3”。仍然应该总体支持 Python 3,如果您在scikits.cuda 的 Python3 中遇到特定函数的问题,可能值得在github 中打开一个错误,以便有人可以修复它。
猜你喜欢
  • 2012-04-24
  • 2017-08-19
  • 1970-01-01
  • 2018-12-09
  • 1970-01-01
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 2016-10-13
相关资源
最近更新 更多