python与C++的效率区别

解释执行:由解释器根据输入的数据当场执行而不生成任何的目标程序。
编译执行:先将源代码编译成目标语言(例如机器语言)之后,通过连接程序连接到生成的目标程序进行执行。
python和C++
python是一种脚本语言,是解释执行的,不需要经过编译,所以很方便快捷,且能够很好地跨平台,写一些小工具小程序特别合适。

而C++则是一种需要编译后运行语言,在特定的机器上编译后在特定的机上运行,运行效率高,安全稳定。但编译后的程序一般是不跨平台的。

首先,python东西比C++多,经过了更多层,python中甚至连数字都是object 。
其次,python是解释执行的,和物理机CPU之间多了解释器这层,而C++是编译执行的,直接就是机器码,编译的时候编译器又可以进行一些优化。
因此在运行效率上,C++要远好于python。

Python 运行效率为何低

参考:

当我们提到一门编程语言的效率时:通常有两层意思,第一是开发效率,这是对程序员而言,完成编码所需要的时间;另一个是运行效率,这是对计算机而言,完成计算任务所需要的时间。编码效率和运行效率往往是鱼与熊掌的关系,是很难同时兼顾的。不同的语言会有不同的侧重,python语言毫无疑问更在乎编码效率,life is short,we use python。

从上图可以看出,不同的case,python比C++慢了几倍到几十倍。

对比原因

第一:python是动态语言
一个变量所指向对象的类型在运行时才确定,编译器做不了任何预测,也就无从优化。举一个简单的例子: r = a + b。 a和b相加,但a和b的类型在运行时才知道,对于加法操作,不同的类型有不同的处理,所以每次运行的时候都会去判断a和b的类型,然后执行对应的操作。而在静态语言如C++中,编译的时候就确定了运行时的代码。
另外一个例子是属性查找,关于具体的查找顺序在《python属性查找》中有详细介绍。简而言之,访问对象的某个属性是一个非常复杂的过程,而且通过同一个变量访问到的python对象还都可能不一样(参见Lazy property的例子)。而在C语言中,访问属性用对象的地址加上属性的偏移就可以了。

第二:python是解释执行,但是不支持JIT(just in time compiler)。虽然大名鼎鼎的google曾经尝试Unladen Swallow 这个项目,但最终也折了。

第三:python中一切都是对象,每个对象都需要维护引用计数,增加了额外的工作。

第四:python GIL,GIL是Python最为诟病的一点,因为GIL,python中的多线程并不能真正的并发。如果是在IO bound的业务场景,这个问题并不大,但是在CPU BOUND的场景,这就很致命了。所以笔者在工作中使用python多线程的情况并不多,一般都是使用多进程(pre fork),或者在加上协程。即使在单线程,GIL也会带来很大的性能影响,因为python每执行100个opcode(默认,可以通过sys.setcheckinterval()设置)就会尝试线程的切换,具体的源代码在ceval.c::PyEval_EvalFrameEx。

第五:垃圾回收,这个可能是所有具有垃圾回收的编程语言的通病。python采用标记和分代的垃圾回收策略,每次垃圾回收的时候都会中断正在执行的程序,造成所谓的顿卡。infoq上有一篇文章,提到禁用Python的GC机制后,Instagram性能提升了10%。感兴趣的读者可以去细读。

模型部署

python需要编译么 python需要编译执行吗_c++


模型部署框架则有英伟达推出的TensorRT,谷歌的Tensorflow和用于ARM平台的tflite,开源的caffe,百度的飞浆,腾讯的NCNN。其中基于GPU和CUDA的TensorRT在服务器,高性能计算,自动驾驶等领域有广泛的应用。

在服务器端部署深度学习模型通常采用 TensorRT 来进行;在手机端部署深度学习模型通常采用 NCNN 或者 MNN 进行;在英特尔 NNP 芯片上部署深度学习模型,就会用到 OpenVINO。

ONNXRuntime整体概览理解

参考:https://zhuanlan.zhihu.com/p/346544539 ONNXRuntime是微软推出的一款推理框架,用户可以非常便利的用其运行一个onnx模型,进行推理和训练。一般而言,先把其他的模型转化为onnx格式的模型,然后进行session构造,模型加载与初始化和运行。其推理时采用的数据格式是numpy格式,而不是tensor张量,当然onnxruntime可以才GPU上也可以在CPU上运行。

主要是对模型图进行优化,同时基于特定的硬件加速器把模型图切分为更小的子图,使用onnxruntime核心进行计算算子的优化

ONNXRuntime是微软推出的一款推理框架,用户可以非常便利的用其运行一个onnx模型。ONNXRuntime支持多种运行后端包括CPU,GPU,TensorRT,DML等。可以说ONNXRuntime是对ONNX模型最原生的支持。

虽然大家用ONNX时更多的是作为一个中间表示,从pytorch转到onnx后直接喂到TensorRT或MNN等各种后端框架了= =,但这并不能否认ONNXRuntime是一款非常优秀的推理框架(微软出品,必属精品)。而且由于其自身只包含推理功能(1.2版本,最新的ONNXRuntime甚至已经可以训练,可见微软在其上面的野心还是有的),对比主流框架源码看起来没有那么复杂难懂,通过阅读其源码可以非常清晰的理解深度学习框架的一些核心功能原理(op注册,内存管理,运行逻辑等)。接下来的一系列文章尝试对ONNXRuntime的源码进行阅读学习,对理解深度学习框架的工作原理还是很有帮助的。

tensorrt

TensorRT是英伟达公司针对自家的GPU产品开发的一个神经网络加速库。它只用于模型在GPU上的推理加速,不支持CPU,一般也不会用于模型的训练。TensorRT加速效果还是比较明显的,一般都是加速几倍、几十倍甚至上百倍。为何它能加速呢?

python需要编译么 python需要编译执行吗_深度学习_02


1、Precision Calibration

精度校准——训练时由于梯度等对于计算精度要求较高,但是inference阶段可以利用精度较低的数据类型加速运算,降低模型的大小,例如FP16,int8,从而加速模型推理速度。

2、Layer & Tensor fusion
层和张量融合——TensorRT中将多个层的操作合并为同一个层,这样就可以一定程度的减少kernel launches和内存读写。比如把主流神经网络的conv、BN、Relu三个层融合为了一个层;把维度相同的张运算组合成另一个大的张量运算。每一层的运算操作都是由GPU完成的——GPU通过启动不同的CUDA(Compute unified device architecture)核心来完成计算的,CUDA核心计算张量的速度是很快的,但是往往大量的时间是浪费在CUDA核心的启动和对每一层输入/输出张量的读写操作上面,这造成了内存带宽的瓶颈和GPU资源的浪费。

3、Kernel Auto-Tuning
计算核心自动调整——TensorRT可以针对不同的算法,不同的网络模型,不同的GPU平台,进行 CUDA核的调整,以保证当前模型在特定平台上以最优性能计算。

4、 Dynamic Tensor Memory
动态张量显存——每个tensor的使用期间,TensorRT会为其指定显存,避免显存重复申请,减少内存占用和提高重复使用效率。

5、Multi-Stream Execution
并行处理多流输入——这个就是GPU底层优化,理解不了。

6、 Time Fusion
时间融合——使用动态生成的算子优化循环神经网络。

以上对为何能加速进行了简单的介绍,详细的原理很难有比较深刻的理解。总体就是量化——降低数据精度、cuda kernel 智能化计算、动态显存管理以及模型结构和张量融合突破GPU带宽瓶颈。

部署框架

无论用什么框架训练的模型,推荐转为onnx格式,方便部署。

支持onnx模型的框架如下:

TensorRT:英伟达的,用于GPU推理加速。注意需要英伟达GPU硬件的支持。
OpenVino:英特尔的,用于CPU推理加速。注意需要英特尔CPU硬件的支持。
ONNXRuntime:微软,亚马逊 ,Facebook 和 IBM 等公司共同开发的,可用于GPU、CPU
OpenCV dnn:OpenCV的调用模型的模块
pt格式的模型,可以用Pytorch框架部署。

推理效率上:TensorRT>OpenVino>ONNXRuntime>OpenCV dnn>Pytorch

由于电脑只有CPU,因此研究下OpenVino、ONNXRuntime、OpenCV dnn的C++使用。

目前市场上应用最广泛的部署工具主要有以下几种:腾讯公司开发的移动端平台部署工具——NCNN;Intel公司针对自家设备开开发的部署工具——OpenVino;NVIDIA公司针对自家GPU开发的部署工具——TensorRT;Google针对自家硬件设备和深度学习框架开发的部署工具——MediaPipe;由微软、亚马逊 、Facebook 和 IBM 等公司共同开发的开放神经网络交换格式——ONNX(Open Neural Network Exchange)。除此之外,还有一些深度学习框架有自己的专用部署服务:比如TensorFlow自己提供的部署服务:TensorFlow Serving、TensorFlow Lite,pytorch自己提供的部署服务:libtorch。

汇总表格

模型 公司 应用场景
onnxruntime 微软 onnx的原生推理框架,通用性好
TensorRT Nvidia 与Nvidia的GPU结合的最好
OpenVIVO Intel 针对Intel平台优化最大
Tengine OPEN AI LAB 边缘设备端
ncnn 腾讯 移动设备端
mnn 阿里 移动设备端
tflite Google 移动设备端

详细介绍

onnxruntime:onnxruntime是微软推出的一款推理框架,用户可以非常便利的用其运行一个onnx模型。onnxruntime支持多种运行后端,包括CPU、GPU、TensorRT、DML等。

TensorRT:TensorRT是一个高性能的深度学习推理优化器,可以为深度学习应用提供低延迟、高吞吐率的模型部署。TensorRT可用于对超大规模数据中心、嵌入式平台或自动驾驶平台进行推理加速。TensorRT现在已经能支持TensorFlow、caffe、mxnet、pytorch等几乎所有的深度学习框架,将TensorRT和Nvidia的GPU结合起来,能在几乎所有的框架中进行快速和高效的部署推理。

OpenVIVO:OpenVIVO是英特尔针对自家硬件平台开发的一套深度学习工具库,包含推理库、模型优化等一些列与深度学习模型部署相关的功能。OpenVIVO是一个比较成熟且仍在快速发展的推理库,提供的demo和sample都很充足,上手比较容易,可以用来快速部署开发,尤其是Intel的硬件平台上性能超过了大部分的开源库。

Tengine:Tengine是OPEN AI LAB(开放智能)推理的AI推理框架,致力于解决AIoT应用场景下多厂家多种类的边缘AI芯片与多样的训练框架、算法模型之间的相互兼容适配,同时提升算法在芯片上的运行性能,将从云端完成训练后的算法高效迁移到异构的边缘智能芯片上执行,缩短AI应用开发与部署周期,助力加速AI产业化落地。

ncnn:ncnn是一个为手机端极致优化的高性能神经网络前向计算框架。ncnn从设计之初深刻考虑手机端的部署和应用。无第三方依赖、跨平台,手机端cpu的速度快于目前所有已知的开源框架。目前已在腾讯多款应用中使用,如QQ、Qzone、微信等。

mnn:mnn是一个高效、轻量的深度学习框架。它支持深度模型推理与训练,尤其在端侧的推理与训练性能在业界处于领先地位。目前mnn已经在阿里巴巴的手机淘宝、天猫、优酷、钉钉、闲鱼等20多个app中使用,覆盖直播、短视频、搜多推荐、商品图像搜索、互动营销、券已发放、安全风控等70多个场景。

tflite:TensorFlowLite是Google在2017年5月推出的轻量级机器学习解决方案,主要针对移动端设备和嵌入式设备。针对移动端设备特点,TensorFlow Lite是用来诸多技术对内核进行了定制优化,预熔激活,量子化内核。

使用TensorRT部署pytorch模型,本质上onnx只是一个中间模型,最终部署还需要把中间模型转换成自己框架支持的格式

一、整体流程概览

  1. 使用pytorch训练模型,生成*.pth文件
  2. 将*.pth转换成onnx模型
  3. 在tensorrt中加载onnx模型,并转换成trt的object
  4. 在trt中使用第三步转换的object进行推理