加速矩阵运算:GPU vs CPU

8
我想知道GPU计算能够帮助我加速模拟的速度有多大的提升。
我的代码的关键部分是矩阵乘法。基本上,代码看起来像以下Python代码,使用1000阶矩阵和长循环。
import numpy as np
m_size = 1000
sim_length = 50

a = np.random.rand(m_size, m_size)
b = np.random.rand(m_size, m_size)

for j in range(sim_length):
    result = np.dot(a,b)

注意:我的矩阵是密集的,大多数是随机的,并且循环使用cython编译。
我天真的想法是有两个因素:
  • 更多的并行线程(当前为1个线程的顺序,GPU为100个线程的顺序?)--> 速度提升约100倍?[来源已经过时,来自2011年]
  • 较低的处理器频率(目前为3Ghz,GPU通常为2Ghz)--> 忽略
我预计这种观点太天真了,那么我错过了什么?

1
我建议如果你的GPU支持的话,一个很好的起点是PyCUDA。这是一个非常棒的库,我过去曾经和numpy一起使用它。 - sethmlarson
3个回答

14

矩阵乘法性能

如果你使用numpy,那么你可能正在使用其中一个BLAS库作为计算后端,比如ATLAS、OpenBLAS、MKL等。当你使用最快的MKL时,你可以在这里找到最近的性能基准,比较了最近的Nvidia GPU K40m和Intel Xeon 12核E5-2697 v2 @ 2.70GHz之间的性能差异。

https://developer.nvidia.com/cublas

其中,K40m比12线程E5-2697快6倍。考虑到MKL在多核CPU上的良好扩展性,K40m比1线程E5-2697快约72倍。此外,请注意,1000维几乎是充分利用GPU和CPU的下限。矩阵大小越小,在GPU上的性能降低可能越明显。

如果你使用较慢的numpy BLAS后端,比如GNU许可证的ATLAS。你可以在这里找到MKL和ATLAS之间的比较。

https://software.intel.com/en-us/intel-mkl/benchmarks#DGEMM-ATLAS

其中,MKL比ATLAS快2~4倍。

对于Nvidia GPU,唯一广泛使用的后端是CUDA的cuBLAS,因此性能不会像ATLAS vs. MKL那样有很大差别。

数据传输

正如@janbrohl所说,主机RAM和GPU设备内存之间的数据传输是影响整体性能的重要因素。这里有一个数据传输速度的基准测试。

CUDA - how much slower is transferring over PCI-E?

根据矩阵大小,你实际上可以计算出计算和数据传输的绝对时间。这可以帮助你更好地评估性能。

为了最大化GPU的性能,您可能需要重新设计程序以最小化数据传输,将所有计算操作移至GPU,而不仅限于矩阵乘法。


7

一般来说,GPU在高度并行的简单任务(这是它们的设计目的)中比CPU快得多,比如乘法大矩阵,但使用GPU计算存在一些问题:

  • 在正常RAM和图形RAM之间传输数据需要时间
  • 加载/启动GPU程序需要一些时间

因此,虽然乘法本身可能快100(或更多)倍,但您可能会遇到实际上速度提升更小甚至减慢的情况。

与CPU相比,GPU存在更多的问题,例如分支代码的严重减速,必须手动处理缓存等,这使得为GPU编写快速程序非常具有挑战性。


5
使用OpenCL API,在一台1280核心的HD7870(甚至不是主流桌面级别的GPU)上尝试了8k X 8k乘以8k X 8k,用时约为0.99秒,这意味着大约进行了5400亿次加法和5400亿次乘法,也就是说1.1 Tflops(其广告中峰值值的%40)。高端桌面级CPU的峰值只有0.2-0.3 Tflops(不包括其集成的GPU)。因此,最好的CPU在性能、功耗效率和性价比方面都无法达到低中端GPU的水平。
性能的关键选项:
- 将计算分为32x32或48x48的块(每个计算单元有一组线程,每个线程计算块的一部分或列/行的所有块的总和) - 使用指数级更快的方法,如Strassen算法。 - 管道化读取、写入和计算操作,使连续的迭代有益地堆叠。 - 为硬件差异进行优化 - 使用具有1到4个选项的库

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接