不同获取方式下TensorFlow(Keras)-CPU性能差异

前言

作为算(diao)法(bao)工作者,最常用的工具之一就是深度学习框架,在众多框架之中,TensorFlow及其高层封装Keras是非常受欢迎,也是绝对用户数最多的。同时,在深度学习的研究中,GPU是必不可少的,因为它能够加速训练与推理,带来速度上质的飞越,显卡的档次从根本上决定了速度提升幅度。然而,很少有人关注其在CPU上的性能问题,尽管在CPU上只能跑一些小模型,才能把训练时间缩小到可接受范围内。然而,安装或获取TensorFlow的途径有很多种,是否会明显影响TensorFlow在CPU上的性能表现呢?本文探讨了不同安装或获取途径下TensorFlow(Keras)上的性能差异。时间有限,可能有些不严谨或不合理的地方,仅供参考,欢迎评论区提出建议!

研究环境与对象

软硬件环境

  • 系统:Ubuntu 18.04 LTS,非虚拟机
  • 处理器:Intel Core i5-8250U @ 1.6 GHz 四核八线程
  • 内存:8.00 GB
  • Python版本:3.6,基于Anaconda 5.2.0

研究对象

  • 4种获取方式下的TensorFlow,版本1.12
    • pip install tensorflow==1.12.0:直接使用pip安装
    • pip install intel-tensorflow==1.12.0: 使用pip安装针对Intel CPU优化过的tensorflow(使用了MKL-DNN)
    • conda install tensorflow==1.12.0: 直接使用conda安装
    • 源码安装:本地编译谷歌开源的TensorFlow源码生成whl文件,再进行pip安装,参考:https://blog.csdn.net/qq_30262201/article/details/101900979

分别以以上4种获取方式下的TensorFlow作为backend安装Keras,版本2.2.4,由于Keras只是对TensorFlow的高层封装,真正决定其性能的仍然是低层的TensorFlow。

  • 运行例程:keras官方mnist例程:https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py ,运行时不借助任何IDE,直接在控制台中调用python3 mnist_cnn.py
  • 评判标准:修改以上例程中的epoch为10,分别在4种TensorFlow的获取方式,batch_size为16,32,64,128的情况下训练CNN网络,取跑完每个epoch的平均时间进行比较。为最大程度保证每个组合条件下各方面的一致性,每修改完一次参数,都要重新运行代码,而不是通过循环修改batch_size或其他参数。

实验结果与分析

pip install intel-tensorflow==1.12.0

为什么先说这个呢?因为这个变种的TensorFlow需要一些配置才能达到最优性能。主要是设定TensorFlow的device_count、intra_op_parallelism_threads和inter_op_parallelism_threads,几个参数的说明可参考https://blog.csdn.net/rockingdingo/article/details/55652662。在我们的环境中,CPU是物理四核的,结合试验,发现device_count和intra_op_parallelism设定为4时可以达到最优性能,再将后两者增大已经无法明显提升速度;而例程模型只是一个简单的序列式CNN,不存在独立的path,结合试验,发现inter_op_parallelism_threads设定为1是最好的,即在以上的例程前面的导包(import …) 部分加入以下代码:

from keras import backend as K
import tensorflow as tf
config = tf.ConfigProto(device_count={"CPU": 4}, # limit to num_cpu_core CPU usage
                inter_op_parallelism_threads = 1, 
                intra_op_parallelism_threads = 4,
                log_device_placement=False)

sess = tf.Session(config=config)
K.set_session(sess) # 设定keras的session使设置能真正生效

同时为了对比设置前后的影响,还对默认情况下的速度做了测试,即去除上述的config和keras session设定。最终的结果如下图所示:
在这里插入图片描述
其中:

  • seconds / epoch(default) 表示在默认配置下不同batch_size时,每个epoch的平均耗时,单位为秒;
  • seconds / epoch(config) 表示经过上述的device_count、intra_op_parallelism_threads和inter_op_parallelism_threads配置后,不同batch_size时每个epoch的平均耗时。
  • 柱状图上的数字就是具体的秒数。

可见经过多线程配置,Intel TensorFlow的性能是有一个明显提升的,大约为20%~30%,batch越大提升比例越大。为了方便与其他3种获取方式对比,这里取keras官方mnist例程默认的batch_size=128情况下,默认与配置两种方式中最快的结果,这里就是56.363 s / epoch,下面几个都遵循这个规则。

  • 注意有小坑:Intel TensorFlow卸载时要pip uninstall intel-tensorflow,而不是pip uninstall tensorflow!!!(尽管在pip list中只能看到tensorflow)否则会导致卸载不干净,再安装时会有安装不上的情况!!!如果真遇到这种情况(错误使用了pip uninstall tensorflow卸载导致后续安装不上tensorflow)去pip安装包路径下,比如anaconda的包路径一般是…/anaconda/lib/site-packages/下(如果是在某个虚拟环境下,那就是…/anaconda/envs/虚拟环境名/lib/site-packages/下),删除所有带intel tensorflow和tensorflow的文件夹,应该就可以了。

pip install tensorflow==1.12.0

此种方式是最方便快捷的,应该也是最常用的。pip会直接拉取镜像中适合当前系统和版本的TensorFlow whl文件,并更新其依赖的包,最后安装TensorFlow。整个过程都是自动的,如果不是本身环境有问题,成功率极高,没什么特别的坑。同样的,做跟上述intel tensorflow一模一样的实验,得到结果:
在这里插入图片描述
与上述的intel tensorflow有两点不同:

  • 随着batch增大,每个epoch耗时减小程度不如intel tensorflow明显
  • 经过多线程配置(seconds/epoch(config)),耗时相比默认反而增大了

推测出现上述情况的原因是由于未使用MKL-DNN,普通tensorflow对多线程的优化不够好。根据上面的规则,还是取batch_size=128下的最快速度,这里是90.984 s / epoch。而intel-tensorflow的时间是56.363 s / epoch,可见:

  • batch较大时,使用intel-tensorflow比普通pip安装的tensorflow明显更快,在这里的例程中,batch_size=128时可比普通pip安装的tensorflow快 (90.984-56.363) / 90.984~ 38%左右;batch_size=64时快(94.238 - 72.032) / 94.238 ~23%左右。
  • batch较小时,intel tensorflow的优势就无法体现了。比如batch_size=32时,intel-tensorflow的时间是101.755 s /epoch,与普通tensorflow的101.149 s / epoch 持平。batch_size=16时,intel-tensorflow甚至要明显慢于普通tensorflow。

conda install tensorflow==1.12.0

之前早就看到过有文章说,使用conda安装的tensorflow具有更快的速度。conda安装命令也很简单,直接输入conda install tensorflow==1.12.0就好了,剩下的就交给conda完成。进行跟上面相同的实验,得到结果:
在这里插入图片描述
果然,conda安装的tensorflow在性能上的优势十分明显,而且经过多线程配置后还可以更快一点。**batch_size=128时,最快速度为44.877s / epoch,比intel-tensorflow快了 (56.363 - 44.877) / 56.363~ 20%左右,比普通pip安装的tensorflow快了 (90.984 - 44.877) / 90.984 ~ 51%左右,相当于速度提升了1倍!**而batch_size=64时也比普通tensorflow快了44%左右。
那这种方式有什么缺点呢?还是在于conda本身,使用门槛比pip要高不少。而且conda install的速度一般比较慢,尤其是在你长时间没有更新过时,每次安装会更新一大批有必要和没必要的包,等待时间比较长。而且,这个过程也容易出问题,说不定就把你前期辛辛苦苦配的环境更新的面目全非,甚至可以改掉你的主Python版本(这个我遇到过,都是泪…) ,从而带来新的问题。感觉应该可以通过配置抑制该问题的产生,不过还是那句话,这样门槛就高了,方便性打了折扣。所以,如果真的要使用conda获取tensorflow以得到更高的性能,建议在配环境之初就装好,不要再轻易更新或改动,其他包如果不是特别有必要用conda,尽量使用pip来管理。

源码安装tensorflow

如果是通过以上几种方式安装的tensorflow,相信对这句警告不陌生:

I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2

这个"was not compiled to use:"后面包括但不限于AVX2,SSE等一系列字母缩写。如果你去百度原因,很容易就知道这是因为没有使用源码编译安装,没有针对你本地的CPU进行“优化”导致的。轻度强迫症患者可以通过配置tensorflow的日志级别屏蔽该警告,而像本人这样的重度强迫症患者,又加上要探究源码编译安装到底能不能带来性能提升,此种掩耳盗铃式的解决方案显然不能接受!于是乎,找到了一篇参考博客,一步步来编译和安装:https://blog.csdn.net/qq_30262201/article/details/101900979 …,殊不知,使用源码编译安装是个体力活:

  • 环节多:git clone源码,bazel安装,tensorflow配置,bazel编译…
  • 坑多:原始git clone 网速慢,clone一个史诗级代码量的tensorflow工程耗时可想而知;tensorflow编译需要拉取的依赖包众多,加上“墙”的缘故,极易下载失败,重复下载是无法解决的;也有可能因为bazel或g++的版本冲突导致失败,不过幸好我没遇到。更多的可参考下面这个博客,里面也有一些解决方法:https://blog.csdn.net/surtol/article/details/97638399 (里面那个搭建本地Nginx服务器解决依赖包无法拉取的问题,仅在.bzl文件中添加本地下载地址是不够的,很有可能通不过sha256码校验而无法编译,这时要看报错信息中实际文件的sha256码是什么,同时把.bzl文件中的"sha256"字段修改为实际的sha256码)
  • 耗资源多:当然也是因为我的笔记本比较弱鸡,bazel编译足足花了近3个小时,整个过程中CPU占用100%,内存全部耗尽,要不是我设定的内存交换区(swap)比较大,编译就崩溃了。

总之,费尽千辛万苦,终于成功源码安装,实验!出结果:

在这里插入图片描述

**总体趋势跟普通pip安装的tensorflow差不多。batch_size=128时默认情况下更快,为76.648s / epoch,相比普通pip安装快了 (90.984 - 76.648) / 90.984 ~ 16%;**相比intel-tensorflow和conda tensorflow都明显要慢。也就是说,有点费力不讨好的意思了。不过可以聊以慰藉的是,上面说的警告真的没有了,很干净,一下子治好了多年的强迫症!

总结

一张表说明问题:

在这里插入图片描述

建议:

普通pip安装TF:适合初学者学习和入门,速度无要求
intel-TF:使用intel CPU,大batch情况下比较推荐,CPU越高档(核数越多)越推荐
conda-TF:速度要求较高,初始环境配置时推荐安装
源码安装TF:如果不是有特殊需求不推荐

最后:

能上Nvidia的显卡还是上,其实我的笔记本上有一个Nvidia MX150的超弱鸡显卡,才384个CUDA核心,2G显存。跑相同的keras mnist例程,速度就可以达到17 s / epoch;之前我在自己的GTX 1070Ti显卡上也跑过这个例程,有2432个CUDA核心,8G显存,速度可以达到 4s / epoch;恐怕更高档的显卡速度会更恐怖。所以,哪怕是弱鸡的显卡,对CPU的性能也是碾压的,中高端的显卡更是跟CPU的速度不在同一个世界。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值