作者:Gu, Jianjun
点击访问Caffe学习笔记 第一部分 - Windows*下BVLC Caffe的安装与配置
clCaffe编译与配置
Intel clCaffe (https://github.com/01org/caffe)是利用基于Intel Skylake及以后的处理器核显(即Gen9架构以上)做硬件加速的一个修改版。如果你当前机器是基于Nvdia显卡,请用NV cuda加速版本;如果你的显卡是AMD的,请check out 官方BVLC caffe的opencl分支。
clCaffe的编译
安装编译所需要的软件
- Visual Studio 2015
- Anaconda + Python 64位版本 https://www.anaconda.com
- cmake-3.9.3-win64-x64 https://cmake.org/
- Git-2.14.2-64-bit https://git-scm.com/
- Intel SDK for OpenCL for Windows* https://software.intel.com/zh-cn/intel-opencl
- 最新的Intel 显卡驱动 https://www.intel.com/content/www/cn/zh/support/products/80939/graphics-drivers.html
配置Windows*的环境变量
为了避免等会CMAKE生成编译脚本的时候找不到一些依赖关系,有的没的路径都加一些,包括Cmake, Git, Ananconda以及Python的路径。(环境变量的配置同上篇文章的2.2部分 )
下载和编译Intel clCaffe工程
clCaffe的编译过程和caffe基本类似。不同的是clCaffe所需的caffe-builder的libraries目录是放在clCaffe自己目录的build目录下,同时额外多下载编译了一些支持openCL运行的开源项目。为了简单起见,这里参考了一个开源项目里的编译脚本https://github.com/liyuming1978/caffe_example/blob/master/install_scripts/Windows_install/build-clcaffe.cmd
首先先创建一个clcaffe-windows的目录,下面提供了一个简单的编译脚本build-clcaffe.cmd(为了简化clCaffe的编译过程,这里直接提供了完整的编译脚本,不再解释脚本里每一步的具体目的,有兴趣的开发者可以自己研究修改脚本来满足自己的需求),在clcaffe-windows目录下创建并且执行这个批处理脚本文件。这个脚本是根据我自己的环境 Win10+VS2015+Python3.6写的,如果你的开发环境跟我的不同,比如是python2.7或者3.5,需要按照脚本里的注释做相应的修改。
@echo off @setlocal EnableDelayedExpansion echo must install openclsdk,python(anaconda),git,cmake,vs 2015 for desktop ::设置python所在路径, 基于python3, ::如果编译环境是python2, 需要修改下面print()这句话,按照python2的语法格式修改 for /f "delims=" %%t in ('python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"') do set py_path_str=%%t ::下载并编译clCaffe所需要的一些依赖项目 cd %~sdp0 git clone https://github.com/dlfcn-win32/dlfcn-win32 cd dlfcn-win32 cmake -G "Visual Studio 14 2015 Win64" . cmake --build . --config Release cd %~sdp0 ::git clone https://github.com/ptillet/isaac.git (isaac build wrong, please use intel isaac) git clone https://github.com/intel/isaac.git cd isaac mkdir build cd build cmake -G "Visual Studio 14 2015 Win64" .. cmake --build . --config Release ::下载clCaffe的项目 cd %~sdp0 git clone https://github.com/01org/caffe.git cd caffe git checkout inference-optimize git pull git clone https://github.com/viennacl/viennacl-dev.git ::下面这部分是拷贝自己编译的caffe-builder的libraries到clCaffe的目录里,同时编译时需要 ::修改WindowsDownloadPrebuiltDependencies.cmake,注释掉对应的网络下载和解压缩代码 ::防止WindowsDownloadPrebuiltDependencies.cmake脚本报找不到网上对应的caffe-builder包, :: 如果编译环境是python2.7或者3.5, 可以注释掉下面这段代码, 编译脚本会自动从网上下载预编译好的依赖库 cd %~sdp0 cd caffe mkdir build cd .\build mkdir libraries cd .. xcopy C:\work\caffe-builder-1.1.0\build_v140_x64\libraries .\build\libraries /s /h /c /y ::设置编译参数,开始编译clCaffe cd %~sdp0 cd caffe set BUILD_PYTHON=1 set BUILD_PYTHON_LAYER=1 set USE_INTEL_SPATIAL=1 set USE_GREENTEA=1 set USE_ISAAC=1 set RUN_TESTS=0 set RUN_INSTALL=1 set PYTHON_VERSION=3 call scripts\build_win.cmd echo "clCaffe compile done"
注意事项:
编译过程中会报一次错,错误为找不到caffe/proto/caffe.pb.h
这个错误不是本机编译环境的问题,而是因为这个项目还不完善,在Windows*下编译项目的顺序有些问题。在Windows*下在编译pretune_convert.vcxproj的时候,这个caffe.pb.h还没有生成。
解决办法也很简单,直接再执行一遍build-clcaffe.cmd中下图的这部分脚本即可。
::设置编译参数,开始编译clCaffe cd %~sdp0 cd caffe set BUILD_PYTHON=1 set BUILD_PYTHON_LAYER=1 set USE_INTEL_SPATIAL=1 set USE_GREENTEA=1 set USE_ISAAC=1 set RUN_TESTS=0 set RUN_INSTALL=1 set PYTHON_VERSION=3 call scripts\build_win.cmd
最终编译结束了
接下来要把编译出的一些动态库拷贝到caffe\build目录下,具体请参考下面的编译脚本build-install.cmd。
if not exist "%~sdp0\caffe\build\install\" ( echo do not find caffe build )else ( :: copy lib and include copy /y %~sdp0\dlfcn-win32\Release\dl.dll %~sdp0\caffe\build\install\bin copy /y %~sdp0\isaac\build\lib\Release\isaac.dll %~sdp0\caffe\build\install\bin copy /y %~sdp0\dlfcn-win32\Release\dl.dll %~sdp0\caffe\build\install\python\caffe copy /y %~sdp0\isaac\build\lib\Release\isaac.dll %~sdp0\caffe\build\install\python\caffe copy /y %~sdp0\dlfcn-win32\Release\dl.dll %~sdp0\caffe\build\tools\Release copy /y %~sdp0\isaac\build\lib\Release\isaac.dll %~sdp0\caffe\build\tools\Release copy /y %~sdp0\caffe\build\libraries\lib\boost_python-vc140-mt-1_61.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\boost_system-vc140-mt-1_61.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\boost_thread-vc140-mt-1_61.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\boost_filesystem-vc140-mt-1_61.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\boost_regex-vc140-mt-1_61.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\boost_chrono-vc140-mt-1_61.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\boost_date_time-vc140-mt-1_61.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\boost_atomic-vc140-mt-1_61.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\glog.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\gflags.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\libprotobuf.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\caffehdf5_hl.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\caffehdf5.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\caffezlib.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\lmdb.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\leveldb.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\snappy_static.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\lib\libopenblas.dll.a %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\x64\vc14\lib\opencv_highgui310.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\x64\vc14\lib\opencv_videoio310.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\x64\vc14\lib\opencv_imgcodecs310.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\x64\vc14\lib\opencv_imgproc310.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\caffe\build\libraries\x64\vc14\lib\opencv_core310.lib %~sdp0\caffe\build\install\lib copy /y %~sdp0\isaac\build\lib\Release\isaac.lib %~sdp0\caffe\build\install\lib copy /y %OPENCL_LIBRARIES% %~sdp0\caffe\build\install\lib copy /y %PYTHON_LIBRARY% %~sdp0\caffe\build\install\lib xcopy %~sdp0\caffe\build\libraries\include %~sdp0\caffe\build\install\include /s /h /c /y move /y %~sdp0\caffe\build\install\include\boost-1_61\boost %~sdp0\caffe\build\install\include\boost mkdir %~sdp0\caffe\build\install\include\viennacl xcopy %~sdp0\caffe\viennacl-dev\viennacl %~sdp0\caffe\build\install\include\viennacl /s /h /c /y mkdir %~sdp0\caffe\build\install\include\CL xcopy %~sdp0\caffe\viennacl-dev\CL %~sdp0\caffe\build\install\include\CL /s /h /c /y mkdir %~sdp0\caffe\build\install\include\3rdparty xcopy %~sdp0\caffe\include\3rdparty %~sdp0\caffe\build\install\include\3rdparty /s /h /c /y echo "copy done" )
运行
运行一下clCaffe项目自带的examples里的00-classification的代码来验证一下clCaffe是否能够正常运行,我们也可以由此看到clCaffe和BVLC caffe的运行流程上的一些不同
首先在C盘的根目录下建一个clcaffe_cache的目录,然后在这个clcaffe_cache的目录下建一个viennacl的子目录。
同时在Windows*的环境变量里加入VIENNACL_CACHE_PATH = c:\clcaffe_cache\viennacl
接下来看看电脑上的可使用的GPU设备的ID号,等下运行caffe的时候需要告诉caffe用哪个GPU设备。
打开Windows* 命令行控制台应用(command console),进入clcaffe-windows\caffe\build\tools\Release目录,执行
C:\work\clcaffe-windows\caffe\build\tools\Release>caffe.exe device_query
看一下输出,
可以看到我的电脑上有2个GPU设备,
Device id:0 是Intel HD Graphics 630核显
Device id:1 是CPU模拟的GPU设备
接着针对00-classification用的caffe模型,我们先生成一下caffe运行这个model所需要cache文件。(如果事先不生产cache文件,这个cache也会在caffe第一次运行caffe model的时候自动生成,但是会导致程序第一次运行时的运行时间过长)
打开Windows* 命令行控制台应用(command console),进入clcaffe-windows\caffe\build\tools\Release目录,执行
C:\work\clcaffe-windows\caffe\build\tools\Release>caffe.exe time -gpu 0 -phase TEST --model ..\..\..\models\bvlc_reference_caffenet\deploy.prototxt
- 这个models\bvlc_reference_caffenet\deploy.prototxt就是用到的模型文件
Caffe会基于这个models来评估一个运行这个模型最快的opencl算法,并且把评估结果写到Cache文件里去。
准备工作终于结束了,下面跑一下00-classification例子吧
打开anaconda的命令行,进入clcaffe\caffe的examples目录,运行jupyter notebook
在打开的notebook中打开caffe自带的例子 00-calssification.ipynb
这是用一个训练好的Caffe模型来预测动物图片的例子,图片默认是使用Caffe项目里examples\image\cat.jpg。
先修改第2步中caffe的路径,将路径指向clcaffe
再修改第4步中的caffe运行模式,注释掉set_mode_cpu(),加上set_device(0),set_mode_gpu(),caffe接下来会把模型放到device id为0的GPU设备上。根据前面的caffe device_query的输出,id 0为本机的核显。
一路Shift+Enter运行下去,看到第8步predicted输出
predicted class is: 281
第9步输出
output label: n02123045 tabby, tabby cat
预测结果是猫,说明clcaffe已经正确编译而且能运行了。
大功告成。
使用clCaffe的一些注意事项
- clCaffe只支持Gen9及以上的Intel核显,即Intel Skylake架构及以后的微处理器的核显。
- 生成caffe cache时建议预先用无权重系数模型来生产cache,不要在caffe第一次运行你自己的代码时on-the-fly的生成cache,容易造成GPU运行出错。(这个bug正在修复中)
- Clcaffe在创建基于GPU的net模型时,这个net会基于set_device([GPU Device ID])传进去的那个GPU device ID创建。所以接下来这个net模型无法通过set_device()来切换另一个GPU硬件,如果想切换到另一个GPU上运行,必须通过set_device([GPU Device ID])设定一个新GPU Device,再重新定义一个新Net模型。
- Windows*下clCaffe对python支持不好,python程序在退出时会异常。在Linux下无此问题。所以建议正式代码用C++来调用caffe,同时C++接口可以定义fp16的caffe模型,获得更高的性能。
Intel clCaffe核显带来的性能提升
接下来在我的两台PC机上分别运行一下基于CPU的BVLC caffe和基于GPU加速的clCaffe,看看在日常的学习生产硬件平台上(台式机和笔记本)运行caffe,核显加速能带来多少性能的提升。测试方法为在默认的Windows*10系统且安装了常用的办公软件及开发软件的环境下(不关闭任何默认打开的后台服务),利用前面用到的caffe自带的例子 00-classification,在代码的第11步,测试net.forward()的运行时间(如下图所示)。我们基于这个测试时间来做一个简单的性能对比。
基于Intel Core i5-7440HQ移动处理器的性能测试
CPU信息
CPU版本net.forward()运行时间
GPU信息
GPU版本net.forward()运行时间
性能提升
1560ms/309ms = 5.05倍
基于Intel Core i7-6700 桌面处理器的性能测试
CPU信息
CPU版本net.forward()运行时间
GPU信息
GPU版本net.forward()运行时间
性能提升
1370ms/262ms = 5.23倍
两个测试平台数据对比分析
- 在Caffe的CPU实现上,Caffe模型的预测时间取决于CPU的核心数量和主频率
net.forward()时间对比
1560ms/1370ms = 1.14倍
CPU频率对比
3.4GHz/2.8GHz=1.21倍 - 在Caffe的GPU实现上,Caffe模型的预测时间主要取决于Net模型的复杂度和GPU的主频。
net.forward()时间对比
309ms/262ms = 1.18倍
GPU频率对比
1.15GHz/1GHz=1.15倍 - 相同硬件平台上CPU实现和GPU实现对比,GPU版本的处理速度领先于CPU版本5倍以上
net.forward()时间对比
平台1:1560ms/309ms = 5.05倍
平台2:1370ms/262ms = 5.23倍
结论
在人工智能领域,利用Intel核显GPU做硬件加速,在Caffe上做图像预测(Inference)时可以带来比纯CPU版本Caffe高达5倍以上的性能提升。这种使用场景特别适合使用Intel的低端桌面处理器,移动处理器,以及凌动处理器平台的IOT设备、Edge设备及家庭电脑上,在这种低功耗、低CPU性能的情况下可以利用Intel集成GPU大大提高这些硬件平台的AI预测速度。
后记
本文介绍的clCaffe并没有获得其最佳性能。要想让clCaffe获得最佳性能,我们还需要对模型进行优化(clCaffe采用的是模型融合),并采用FP16来进行推理。
模型融合(Model Fusion)意思是说在神经网络内,一些层可以合并在一起计算。通常情况下,我们可以将BatchNorm,Scale,Relu层合并进入Conv层。模型融合的好处是降低了数据读取的次数,因为在推理过程中除了运算,数据读写也占用了大量的时间。
FP16也称之为半精度浮点,一般浮点数为4字节(FP32),FP16顾名思义为2字节,大部分现代GPU中设计了FP16的运算单元, 相对FP32可以获得1.3~2倍数的性能提升。在clCaffe中可以创建Half类型的网络, 当这样的网络加载FP32的模型时,内部会自动转换成FP16的模型进行计算,速度可以进一步提升(但是,目前只能使用c/c++代码才能创建FP16网络)。
有关clCaffe的模型融合以及FP16推理相关的内容,将会在下一篇博文介绍。你也可以在这里https://github.com/liyuming1978/caffe_example找到更多的如何更好使用clCaffe的相关信息。