C++、python、CUDA性能分析--矩阵乘法

网上看到一个分析python、Numpy、C++、cuda、cuBLAS做矩阵运算性能的帖子,我觉得非常好。所以,就自己动手实测了一下。这才有了这篇文章。就算是给需要的朋友做个参考吧。


****************************原帖内容****************************

前言

矩阵乘法非常适合在GPU上并行运行,但是使用GPU并行后能获得多大的性能提升?本文将通过一些实验分析CUDA程序的性能。

测试环境

本文使用台式机(DIY)作为测试机,相关配置如下:

型号 DIY
CPU Intel G2030 3.0GHz
主存 8GB
GPU GeForce GTX 750Ti
OS Windows 7 64bit
CUDA CUDA 8.0

带宽测试

使用CUDA Toolkit提供的示例程序bandwidthTest测试可分页内存(Pageable)和锁页内存(Page-lock or Pinned)的带宽,测试结果如下:

C++、python、CUDA性能分析--矩阵乘法_第1张图片

从上图可以看出,锁页内存对带宽的提升是非常大的,所以当一个程序的性能瓶颈是数据传输时,就应该考虑是否应该使用锁页内存。当然,使用锁页内存是有代价的——该内存空间不能换页,当大量使用时会导致内存耗尽而是程序崩溃。

矩阵乘法性能对比

测试了5个不同版本的矩阵乘法的性能:numpy、C++、CUDA无优化(CUDA1)、CUDA使用共享内存优化(CUDA2)、cuBLAS,由于原生Python版本的程序实在太慢了,故放弃之。CUDA和cuBLAS版本的矩阵乘法可以从CUDA Toolkit提供的示例程序matrixMul、matrixMulCUBLAS找到,当然需要做一些修改。5个版本的测试结果如下:

C++、python、CUDA性能分析--矩阵乘法_第2张图片
C++、python、CUDA性能分析--矩阵乘法_第3张图片
C++、python、CUDA性能分析--矩阵乘法_第4张图片

从上图可以看到,3个GPU版本的性能都比CPU(C++)版本高,尤其是在数据量变大的时候,如当数据量大于1024*1024时,C++版本的运行时间急剧上升。对比不使用共享内存和使用共享内存优化的版本可以看到,在数据量小的时候两个版本看不出差异,而当数据量越来越大的时,性能差异就很明显。使用共享内存优化的版本明显优于不优化的版本,这是因为从全局内存访问数据是非常慢的,而共享内存就相对快多了,当所有的线程都重复从全局内存读取数据势必导致全局内存总线拥堵,而且内存访问也不能合并,导致大量线程被挂起,从而降低性能。共享内存是程序员可以控制的高速缓存,应该可能地应用它以优化程序的性能。另外,使用cuBLAS似乎比自己实现一个算法的性能更高,这是因为这些库都是拥有丰富编程和优化经验的高级程序员编写的,所以当考虑自己实现一个算法的时候先看看是否有现成的库可以使用,有时候费力并不一定讨好 :D。

比较戏剧性的是Numpy,它的表现完全出乎我的意料,居然戏剧性地接近了比GPU版本的性能,关于原因还有待研究。这也告诉我们,使用Python时遇到数学计算还是尽量使用Numpy而不是python的math。当然如果你的计算机配备GPU或多核CPU(貌似现代GPU都是多核的)也可以考虑Numba加速Python程序,参考使用Python写CUDA程序。

结语

本文主要记录了本人测试CUDA程序性能的结果,并对结果进行了分析,从测试结果和分析可以为并行程序和优化性能带来一些启示。

本文完整代码可在Github上下载。


**************************以上为原贴内容(主机是我自己的台式机配置)****************************


下面两张图是我实测运行代码后的图片,基本情况符合原贴的分析。

C++、python、CUDA性能分析--矩阵乘法_第5张图片

第一张图如上所示。这张图分为三部分:

左上方是使用了Numpy库函数的python程序运行结果(“In [2]: run matrixMul.py”上面);

左下方是没有使用Numpy库的python程序运行结果(“In [2]: run matrixMul.py”下面),实在是太慢了,程序还没跑完就被我强行终止了;

右侧是C++程序运行结果。

这三种实现形式相比较而言Numpy的优势太明显了。C++比不用Numpy要快大约一个数量级,而使用Numpy比C++要快大约两个数量级。

C++、python、CUDA性能分析--矩阵乘法_第6张图片

第二张图是使用VS2012+CUDA8.0编译环境运行的cuda程序。我们把图中的矩阵运算时间写下来:

Matrix<256,256>,Time=3.398 ms;

Matrix<512,512>,Time=26.641 ms;

Matrix<768,768>,Time=88.807 ms;

Matrix<1024,1024>,Time=208.846 ms;

Matrix<1280,1280>,Time=406.837 ms;

Matrix<1536,1536>,Time=702.161 ms;

Matrix<1792,1792>,Time=1114.958 ms;

由于CUDA和Numpy比C++快太多,我们这里就比较CUDA和Numpy的运行时间。

说实话,看到运行结果后我还是很吃惊的。因为我认为GPU用CUDA做矩阵运算一定比CPU执行的python要快。万没想到Numpy在CPU上竟然跑的比CUDA在GPU上还要快。我认为这是因为一方面例程的矩阵运算量还不够大,体现不出GPU的真正实力;另一方面CUDA没有使用cuBLAS优化。不管怎么讲Numpy的表现非常亮眼。这是因为Numpy包是用C语言开发,本来效率就很高,又经过二十年的不停优化(Numpy的前身是1995年就开始开发的一个用于数组运算库)。所以我们以后用python进行科学计算一定要使用Numpy包。

*************************************************END****************************************************


原帖地址:http://www.cnblogs.com/5long/p/cuda_matrix_performance.html

你可能感兴趣的:(Python,GPU)