卷积操作的GPU粗粒度并行实现及测试
一、 算法基本思想:
1、 GPU中的一个线程产生一个卷积结果,有多少个结果就使用多少个Block;
2、 矩阵和卷积核存放在共享内存中,卷积结果存放在全局内存中;
3、 支持10000以内任意维度的二维矩阵,卷积核最大支持16x16。
4、 支持任意多幅图像的批处理。
二、 实验平台:
CPU:Intel(R) Xeon(R) E5-2650 0 @2.00GHz 16核 32线程
GPU:NVIDIA Tesla C2070(见下表)
RAM Memory:64G
Operating System:64bit Win7。
尺寸规格 | 9.75英寸PCIe x16规格 |
Tesla GPU的数量 | 1 |
CUDA核心数量 | 448 |
CUDA核心频率 | 1.15 GHz |
双精度浮点性能(峰值) | 515 Gflops |
单精度浮点性能(峰值) | 1.03 Tflops |
专用存储器总容量* Tesla C2050 |
3GB GDDR5 |
存储器频率 | 1.5 GHz |
存储器接口 | 384位 |
存储器带宽 | 144 GB/秒 |
功耗 Tesla C2050 | 238W热设计功耗 |
系统接口 | PCIe x16 Gen2 |
散热解决方案 | 主动式风扇散热器 |
显示器支持 Dual-Link DVI-I |
|
软件开发工具 | CUDA C/C++/Fortran、OpenCL以及DirectCompute工具包。 |
三、 CPU和GPU耗时比较
说明:在CPU实现中,不做任何优化,卷积操作使用基本的四层循环形式。为了程序了通用性,在GPU内部做了很多的条件测试,比较耗时。这个是初始版,可以做进一步优化,比如一些字节对齐等。
测试时间说明:使用clock()进行测试,精度为0.001秒(1ms),GPU测试的总时间包括函数调度开销、GPU启动开销、设备内存的申请释放开销、数据传输开销和计算开销等,并且测试了数据的预处理和后处理的时间消耗。CPU只有函数调度开销和计算开销。
误差说明:CPU和GPU均使用float型数组存储数据,矩阵和卷积核数据随机初始化,并对CPU和GPU卷积结果作比较,测试卷积的有效性。
初步分析:
A. CPU和GPU卷积结果误差为0,表明GPU实现是有效的。
B. 矩阵和卷积核较小时,CPU性能较好。矩阵和卷积核较大时,GPU性能较高,体现出GPU的并行性,能快速处理大规模、高吞吐量的数据。当数据量不是很大时,GPU耗时主要是启动开销,即设备内存的分配开销。
C. GPU上,一个线程产生一个卷积结果,在线程内部是串行的,卷积核越大,单个卷积结果越耗时。
为了减少访问全局内存的次数,运算前,矩阵和卷积核拷贝到Block内部的共享内存中。
使用二维Block,一个Block内部16x16个线程,产生多少个卷积结果就使用多少个Block,因此固定卷积核,改变矩阵大小,运行时间基本不变,当矩阵过大时,使用的Block数量过多时,运算时间受限于GPU硬件中支持的SM和Block数量。(考虑卷积程序的通用性,数据拷贝时使用了比较多的条件测试和分支操作,性能受一定影响)。
D. CPU上是简单的串行运算,受矩阵和卷积核大小影响较大。
E. 当矩阵两个维度都超过10000时,CPU运算出现指针异常,可能是矩阵较大时(550MB左右),数据存储时不再连续,指针溢出。所以无法测试。
Matrix Size | Number | Kernel | CPU(s) | CPU2GPU | GPU-Kernel | GPU2CPU |
5x4 | 1 | 5x4 | <1ms | <1ms | <1ms | <1ms |
12x9 | 1 | 5x4 | <1ms | <1ms | <1ms | <1ms |
1 | 5x4 | <1ms | <1ms | <1ms | <1ms | |
118x29 | 1 | 5x4 | <1ms | <1ms | <1ms | <1ms |
138x59 | 1 | 5x4 | <1ms | <1ms | <1ms | <1ms |
158x159 | 1 | 5x4 | 0.003 | <1ms | 0.001 | <1ms |
558x559 | 1 | 5x4 | 0.044 | 0.001 | 0.001 | <1ms |
1128x1159 | 1 | 5x4 | 0.157 | 0.002 | 0.004 | 0.001 |
2128x2159 | 1 | 5x4 | 0.442 | 0.007 | 0.012 | 0.007 |
5128x5159 | 1 | 5x4 | 2.394 | 0.038 | 0.068 | 0.035 |
18128x4159 | 1 | 5x4 | 6.866 | 0.111 | 0.193 | 0.114 |
10128x11159 | 1 | 5x4 | 10.074 | 0.160 | 0.288 | 0.142 |
|
|
|
|
| 15.54Gflops | 1.427GBps |
5x4 | 1 | 14x15 | ~ | ~ | ~ | ~ |
12x9 | 1 | 14x15 | ~ | ~ | ~ | ~ |
18x19 | 1 | 14x15 | <1ms | <1ms | <1ms | <1ms |
118x29 | 1 | 14x15 | <1ms | <1ms | <1ms | <1ms |
138x59 | 1 | 14x15 | <1ms | 0.001 | <1ms | <1ms |
158x159 | 1 | 14x15 | 0.024 | <1ms | <1ms | <1ms |
558x559 | 1 | 14x15 | 0.354 | <1ms | 0.006 | 0.001 |
1128x1159 | 1 | 14x15 | 1.400 | 0.002 | 0.023 | 0.002 |
2128x2159 | 1 | 14x15 | 3.839 | 0.007 | 0.082 | 0.007 |
5128x5159 | 1 | 14x15 | 22.856 | 0.042 | 0.475 | 0.035 |
11128x4159 | 1 | 14x15 | 38.172 | 0.079 | 0.833 | 0.061 |
10128x11159 | 1 | 14x15 | 122.679 | 0.203 | 2.614 | 0.358 |
|
|
|
|
| 23.23Gflops | 382.6MBps |
5x4 | 15 | 14x15 | ~ | ~ | ~ | ~ |
12x9 | 15 | 14x15 | ~ | ~ | ~ | ~ |
18x19 | 15 | 14x15 | 0.001 | <1ms | <1ms | <1ms |
118x29 | 15 | 14x15 | 0.041 | <1ms | 0.001 | <1ms |
138x59 | 15 | 14x15 | 0.097 | <1ms | 0.002 | <1ms |
158x159 | 15 | 14x15 | 0.372 | 0.001 | 0.007 | <1ms |
558x559 | 15 | 14x15 | 4.943 | 0.006 | 0.084 | 0.006 |
1128x1159 | 15 | 14x15 | 15.851 | 0.030 | 0.353 | 0.028 |
2128x2159 | 15 | 14x15 | 57.699 | 0.097 | 1.247 | 0.084 |
3158x3059 | 15 | 14x15 | 121.152 | 0. 201 | 2.624 | 0.192 |
5128x5159 | 15 | 14x15 | 指针溢出 | |||
11128x4159 | 15 | 14x15 | ||||
10128x11159 | 15 | 14x15 | ||||
|
|
|
|
| 23.01Gflops | 362.9MBps |
进一步分析:
从上表可知,最高吞吐率为1.427GBps,PCAIE总线的带宽为5GBps,还有一定的空间。单精度浮点数乘法的最高有效计算性能为23.23Gflops,官方文档上标示的最高单精度浮点性能为1Tflops,差别较大,分析原因如下:
A. CPU传输给GPU的数据是一维数组,而在GPU内部是按二维进行运算的,在存取数据是需要做很多的地址计算操作。
B. 由于卷积特有的性质,数据有很多的重复性,将大图像分割成很多小的图像块时,需要考虑边界问题,并且为了保证程序的通用性,支持任意的图像和卷积核大小,以及支持任意多幅图像的批处理,GPU中,将数据拷贝到共享内存之前,做了比较多的条件测试,时间消耗比较大。这个地方可以通过在CPU进行边界扩展等预处理,进一步提高GPU运算性能。
C. 线程内部计算单个卷积结果时,使用了一个二维循环,当卷积核较大时,运算时间呈指数型增长。
总结:
写一个GPU程序简单,写一个高效的GPU程序难,而写一个高效的通用性的GPU程序,更难,需要考虑方方面面的东西。目前版本的程序,仅仅具有简单的通用性,因为使用基本的数据结构保存数据,当数据量达到500MB时,很容易出现问题,而且计算效率也不是很高。
下周工作计划:
(1) 在CPU中做一些数据的预处理,考虑字节对齐,边界填充等,尽量减少GPU内部的条件测试。考虑将单个的卷积操作拆开,实现细粒度并行,提高单个卷积结果的计算效率。
(2) 学习三维Block,将一幅图像放在第一和第二维度上,批处理图像放在第三个维度,减少后处理计算量,增加批处理图像的卷积计算性能。
(3) 考虑反卷积运算的并行化。考虑将CUDA卷积程序与matlab版的CNN结合,进行交叉编译,提高CNN的运算效率。