笔者从 2012 年初开始接触 GPU 编程,2014 年上半年开始接触 Caffe,可以毫不谦虚地说是“一天天看着 Nvidia GPU 和 Caffe 长大的”。
Nvidia GPU 架构经历了 Fermi、Kepler、Maxwell、Pascal(都是著名物理学家:特斯拉、费米、开普勒、麦克斯韦、帕斯卡、还未发布的 Volta 伏打……),硬件版本号从 1.x 到现在的 6.x,CUDA Toolkit 从 3.x 到现在 8.x,cuDNN 也从 v1 升级到 v5.1。
Caffe 也伴随着 Nvidia GPU 硬件和软件升级不断调整,与时俱进,经典的 CNN 网络 AlexNet (Caffe 重新实现的版本称为 CaffeNet)计算速度也不断刷新。另外,Caffe 也在努力支持新模型(VGG,GoogLeNet,ResNet……)。
本文是一篇历史回顾文章,可能很多试验已经不再适合读者的环境(如果你买了 GTX 1080 、1080 Ti 或 Titan X Pascal,就不要想着安装低于 8.0 版本的 CUDA 了,会坑)。我会做两个试验,分别考察软件、硬件变迁给 CNN 计算速度带来的影响。
两个试验中的 CNN 模型均使用 CaffeNet,输入 batch size 固定为 128。模型 prototxt 文件内容如下(从 $CAFFE_ROOT/models/bvlc_reference_caffenet/deploy.prototxt 修改得到):
name: "CaffeNet" layer { name: "data" type: "Input" top: "data" input_param { shape: { dim: 128 dim: 3 dim: 227 dim: 227 } } } ……后面内容保持不变
将上述 prototxt 文件保存为 caffenet-for-benchmark.prototxt。
运行如下命令进行 CNN 计时,可以得到 forward/backward 时间:
$ cd $CAFFE_ROOT $ ./build/tools/caffe.bin time -model caffenet-for-benchmark.prototxt -gpu 0
本文将上述计算时间折算为每秒处理多少张图片(images/s)。算法为:
Benchmark #1 = BatchSize * iterations / ForwardTime
Benchmark #2 = BatchSize * iterations / (ForwardTime + BackwardTime)
其中 ForwardTime、BackwardTime 单位均为秒,Caffe time 程序中 iterations 默认值为 50,因此上面公式简化为:
Benchmark #1 = 128 * 50 / ForwardTime = 6400 / ForwardTime
Benchmark #2 = 128 * 50 / (ForwardTime + BackwardTime) = 6400 / (ForwardTime + BackwardTime)
【试验 1】
第一个试验固定使用 Tesla K40m 硬件,通过切换不同版本 CUDA 和 cuDNN 来测试 CaffeNet Forward/Backward 速度。另外提供了 Caffe Native 方法( im2col + gemm,CPU/GPU )作为 BaseLine 实现。其中 CPU 版本 Caffe 使用了 OpenBLAS-0.2.14,CPU 型号为 Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz,16 个物理核。
试验结果如下图所示:
具体数值如下:
【试验 1 结论】
(1)K40m 上不使用 cuDNN 加速库时,跑 AlexNet 前向计算可达 521 images/s,前向+反向计算约 266 images/s。
(2)K40m 上使用 cuDNN 加速库,跑 AlexNet 前向计算最高可达 > 1200 images/s,前向+反向计算最高可达 >550 images/s。
(3)K40m 上使用 cuDNN v3, v4, v5 跑 AlexNet 性能差别不大。
(4)K40m GPU 跑 AlexNet 前向计算相比 CPU E5-2650v2 速度提升了 19 ~ 45 倍,前向+反向计算速度提高了 17~36 倍。
(5)cuDNN 相比 Caffe Native GPU 实现有 1.7 ~ 2.3 倍速度提升。
(6)从 cuDNN v1 到 v5,通过纯软件优化,速度仅有 1.3 倍提升。
【注】
(1) K40m 时钟默认为 745 MHz,测试出来的计算速度会比上述结果低一些,可以通过下面两个命令(需要 root 权限执行)开启最高运行时钟:
$ nvidia-smi -pm 1 $ nvidia-smi -ac 3004,875
第二条命令不能随便设置数值。不同型号 GPU 支持的运行时钟频率不同,读者应查阅官方硬件管理手册。
(2) 完成上述测试的 CUDA 版本有差异。
- cuDNN v1, v2 需要 CUDA 6.5;
- cuDNN v3 需要 CUDA 7.0 ;
- cuDNN v4 需要 CUDA 7.5;
- cuDNN v5 需要 CUDA 8.0;
GPU 驱动版本固定为 375.20,实践证明高版本的 GPU 驱动可以支持低版本 CUDA,但反过来不一定成立。
(3) 完成上述测试的 Caffe 版本有些许不同。
cuDNN v5
https://github.com/bvlc/caffe,branch master,commit e687a71fac81718d40d4e0e98d29eab34f784b5b(20170307 版本)
cuDNN v3 & v4:
https://github.com/bvlc/caffe,branch master,commit 559758d0c5c5906633174d392b89c0a7a88dc9f9(20160302 版本)
cuDNN v2:
https://github.com/bvlc/caffe,branch master,commit de7b0bf7db0d5fb8f840e03f40e099d9eefaaacc(20150814 版本)
cuDNN v1:
https://github.com/bvlc/caffe,branch tutorial,20140909 版本。
在 Caffe 根目录下,执行 git show 可以显示代码 commit 、merge、贡献者、日期等信息。
$ git show commit 559758d0c5c5906633174d392b89c0a7a88dc9f9 Merge: 37d1f91 666da79 Author: Jon Long <[email protected]> Date: Wed Mar 2 16:23:14 2016 -0800 Merge pull request #3716 from ttdt/master Use six library to ensure pycaffe.py python3 compliance
【试验 2 】
第二个试验固定使用 CUDA 8.0 + cuDNN 5.1,通过切换不同硬件来测试 CaffeNet Forward/Backward 速度。测试方法与试验 1 完全相同。
首先看下不同硬件的绝对处理能力。为了方便,我们只做 CaffeNet Forward 计算。
看到这张图,一部分读者估计会泪奔,辛辛苦苦在 K40m 上优化程序,速度提升了 1.x 倍,结果黄教主一发布新卡,速度提升 X 倍……
绝对性能中,P100 和 P40 遥遥领先,其架构细节可以见上一篇文章《Pascal 架构详解》。
另外我们还要关注另一个性能指标,即每瓦的处理能力,这在一些功耗敏感的应用中颇为重要。
这张图估计要另一部分读者泪奔。。。一向以性能-功耗比著称的 FPGA 厂商,要硬着头皮研发新一代产品(Stratix 10,UltraScale+)才能赶上了。
Tesla P4 功耗仅 75 W,单精度处理能力标称 5.5 TFLOPS, int8 计算能力更是高达 22 TFLOPS,目前可以秒杀市面上任何一款 FPGA。注意我们试验中均使用 32 bit 浮点,笔者曾试过 int8 版本相对 32 bit 浮点版本要有至少 3.5X 加速。限于篇幅,不再展开。
【试验 2 结论】
(1) K40m 的绝对性能,每瓦性能在本文提到的所有 Nvidia GPU 中都是垫底的。而一些论文常常先拿软柿子捏。
(2)Maxwell 架构(M40、Titan X Maxwell)相比 Kepler 架构(K40m)绝对性能提升 2.4 倍,每瓦性能提升 2.27 倍。
(3)Pascal 架构(P40, P100)相比 Maxwell 架构(M40、Titan X Maxwell)绝对性能提升 1.5 ~ 1.6 倍,每瓦性能提升 1.6 倍。
(4)Pascal 架构的 Tesla P4 每瓦性能比同系列的 P40, P100, GTX 1080 提升 1.6 倍,是目前每瓦性能最高的处理器。如果使用 int8 数值类型进行计算,每瓦性能还有 3 倍以上提升。
下表为本文提到的所有 Nvidia GPU 硬件详情。
值得注意的是 Tesla P100 的双精度处理能力最强,标称 4.7 TFLOPS,实测达到 4.6 TFLOPS 。另外支持半精度(FP16)计算,实测 FP16 计算能力为 FP32 的 1.8 倍。K40m 双精度计算能力为 1.4 TFLOPS,仅次于 Tesla P100。其他型号 GPU 的双精度计算能力都很弱(< 0.5 TFLOPS)。因此,K40m 也并非“一无是处”。
【写在最后】
问题1:为什么不用 GoogLeNet 这类较新的模型?
答:因为第一个试验中用到早期 Caffe 和 cuDNN,不支持 GoogLeNet,无法给出结果。
问题2:为什么 cuDNN 后面几个版本在 K40m 上速度没有改进?
答:后面几个版本的 cuDNN 主要特性放在对新硬件架构的支持,针对旧的架构的优化可能已经停止。
问题3:为什么没有 Titan X Pascal、GTX 1080 Ti……等 GPU 上的测试结果?
答:手头没有。如果有壕赞助,笔者愿意在本文中更新。也欢迎具备条件的读者将评测结果反馈给笔者。