基于TensorRT 3的自动驾驶快速INT8推理
基于TensorRT 3的自动驾驶快速INT8推理
Fast INT8 Inference for Autonomous Vehicles with TensorRT 3
自主驾驶需要安全性,需要一种高性能的计算解决方案来处理极其精确的传感器数据。研究人员和开发人员创建用于自动驾驶的深度神经网络(DNNs)必须优化其网络,以确保低延迟推理和能源效率。由于NVIDIA TensorRT中有了一个新的Python API,这个过程变得更加简单。

Figure 1. TensorRT optimizes trained neural network models to produce deployment-ready runtime inference engines.
TensorRT是一个高性能的深度学习推理优化器和运行时引擎,用于深度学习应用程序的生产部署。开发人员可以优化在TensorFlow或Caffe中训练的模型,以生成内存高效的运行时引擎,从而最大限度地提高推理吞吐量,使深度学习对于延迟关键的产品和服务(如自主驾驶)切实可行。。
最新的TensorRT 3版本引入了一个功能齐全的Python API,使研究人员和开发人员能够使用熟悉的Python代码优化和序列化DNN。使用TySoRRT 3,可以在Python中部署云计算服务,或者在C++中实时应用,例如在英伟达驱动PX AI汽车计算机上运行的自主驱动软件。
在本文中,将向展示如何在主机上使用TensorRT 3 Python API来缓存语义分段网络的校准结果,以便使用INT8 precision进行部署。然后,可以使用校准缓存来优化和部署在驱动PX平台上使用C++ API的网络。
城市景观数据集与全卷积网络The Cityscapes Dataset and Fully Convolutional Network

Figure 2. Sample images from the Cityscapes dataset.
城市景观数据集[Cordts等人。2016]用于城市自主驾驶场景的语义分割。图2显示了数据集中的示例图像。该数据集共有30个不同的类,分为8个不同的类别。为了评估性能,使用了19个类和7个类别,如图3所示。

Figure 3. Classes and categories used in the Cityscapes benchmark, and the IoU (Intersection-over-Union) metric.
对于评估,使用IoU(Intersection over Union)度量,提供两个平均分数,一个用于类,另一个用于类别。

Figure 4. A sample VGG16-based fully convolutional network trained for semantic segmentation.
为了证明TensorRT的能力,设计了一种全卷积网络FCN[Long等人]。基于VGG16,如图4所示。该网络由一个基于VGG16的编码器和两个使用反卷积层实现的上采样层组成。用NVIDIA数字和Caffe在城市景观数据集上训练了[2014年]网络后端。

Figure 5. Sample FCN network output.
该网络设计为获取512×1024的输入图像并生成每像素分类结果,如图5所示。训练后的网络IoU类平均得分为48.4分,IoU类平均得分为76.9分。如果直接使用Caffe和cuDNN在其中一个驱动器PX autochauffer gpu(Pascal)上运行推断,该网络将达到大约242ms的延迟和大约4个图像/秒的吞吐量。在35英里/小时的速度下,242毫秒相当于大约12英尺的行驶距离。这种水平的表现不足以为自动驾驶做出及时的决定。让来看看如何才能做得更好。

图6. DP4A指令:四元点积累加。
作为第一步,使用TensorRT优化网络,使用FP32精度提供了良好的加速。通过使用TensorRT,实现了170毫秒的延迟和大约6个图像/秒的吞吐量。这比Caffe提高了50%,但是TensorRT可以进一步优化网络。
以下各节将演示如何使用TensorRT,在保持原FP32网络良好精度的同时,使用INT8降低的精度来提高该网络的推理性能。
INT8推理和校准
驱动器PX autochauffer中的Pascal dGPU能够执行8位整数4元向量点积(DP4A,见图6)指令,以加速深层神经网络推理。虽然这条新指令提供了更快的计算速度,但在用这种简化的INT8格式表示深度神经网络的权值和激活方面存在着重大挑战。如表1所示,与FP32或FP16相比,INT8可表示值的动态范围和粒度明显受限。

TensorRT提供了一种快速简便的方法来获取在FP32中训练过的模型,并自动转换网络以供部署,INT8的精度降低,精度损失最小。为了实现这一目标,TensorRT使用了一个校准过程,当用有限的8位整数表示逼近FP32网络时,该校准过程将信息损失最小化。有关此算法如何工作的更多信息,请参阅TensorRT GPU技术会议演示的8位推理。
在准备校准数据集时,应在典型的推断场景中捕获预期的数据分布。需要确保校准数据集涵盖所有预期场景,例如晴天、雨天、夜景等。如果正在创建自己的数据集,建议创建单独的校准数据集。校准数据集不应与训练、验证或测试数据集重叠,以避免校准模型仅在这些数据集上正常工作的情况。
让看看如何使用新的TensorRT Python API创建校准缓存。
使用Python API创建校准缓存
随着TensorRT Python API的引入,现在完全可以在Python中实现INT8校准器类。这个例子演示了如何处理图像数据并为校准器提供数据。修改这个示例以支持Python中不同类型的数据和网络应该很简单。
import pycuda.driver as cuda
import pycuda.autoinit
import numpy as np
from PIL import Image
import ctypes
import tensorrt as trt
CHANNEL = 3
HEIGHT = 512
WIDTH = 1024
class PythonEntropyCalibrator(trt.infer.EntropyCalibrator):
def __init__(self, input_layers, stream):
trt.infer.EntropyCalibrator.__init__(self)
self.input_layers = input_layers
self.stream = stream
self.d_input = cuda.mem_alloc(self.stream.calibration_data.nbytes)
stream.reset()
def get_batch_size(self):
return self.stream.batch_size
def get_batch(self, bindings, names):
batch = self.stream.next_batch()
if not batch.size:
return None
cuda.memcpy_htod(self.d_input, batch)
for i in self.input_layers[0]:
assert names[0] != i
bindings[0] = int(self.d_input)
return bindings
def read_calibration_cache(self, length):
return None
def write_calibration_cache(self, ptr, size):
cache = ctypes.c_char_p(int(ptr))
with open('calibration_cache.bin', 'wb') as f:
f.write(cache.value)
return None
PythonEntropyCalibrator类是INT8校准器的Python实现。这个类负责分配CUDA内存并为所有输入层创建绑定。每当调用get_batch()时,会将校准输入数据上载到预先分配的CUDA内存。校准批大小定义了同时处理多少校准图像以收集计算正确比例因子所需的输入分布。校准批大小可以不同于用于推断的最大批大小参数。使用较大的校准批大小通常会加快校准过程,建议使用GPU内存中可以容纳的最大批大小。
class ImageBatchStream():
def __init__(self, batch_size, calibration_files, preprocessor):
self.batch_size = batch_size
self.max_batches = (len(calibration_files) // batch_size) + \
(1 if (len(calibration_files) % batch_size) \
else 0)
self.files = calibration_files
self.calibration_data = np.zeros((batch_size, CHANNEL, HEIGHT, WIDTH), \
dtype=np.float32)
self.batch = 0
self.preprocessor = preprocessor
@staticmethod
def read_image_chw(path):
img = Image.open(path).resize((WIDTH,HEIGHT), Image.NEAREST)
im = np.array(img, dtype=np.float32, order='C')
im = im[:,:,::-1]
im = im.transpose((2,0,1))
return im
def reset(self):
self.batch = 0
def next_batch(self):
if self.batch < self.max_batches:
imgs = []
files_for_batch = self.files[self.batch_size * self.batch : \
self.batch_size * (self.batch + 1)]
for f in files_for_batch:
print("[ImageBatchStream] Processing ", f)
img = ImageBatchStream.read_image_chw(f)
img = self.preprocessor(img)
imgs.append(img)
for i in range(len(imgs)):
self.calibration_data[i] = imgs[i]
self.batch += 1
return np.ascontiguousarray(self.calibration_data, dtype=np.float32)
else:
return np.array([])
ImageBatchStream是一个helper类,负责处理文件I/O、图像大小的缩放、创建要处理的批处理数据、将数据布局重新排序为CHW格式,以及应用预处理器函数(例如减去图像平均值)。
校准结果可以保存到缓存文件中,因此可以创建优化的TensorRT运行时引擎,而无需在目标上重复校准过程。在本例中,生成的文件名是calibration_cache.bin,在write_calibration_cache函数中处理。
一旦准备好校准器类,剩下的过程就可以用TensorRT的新的拉氏体Python模块,旨在抽象出许多低级细节,使数据科学家更容易使用TensorRT。这个包允许添加预处理和后处理函数,并使能够利用现有的Python数据预处理例程。在下面的代码中,函数sub_mean_chw作为预处理步骤处理均值减影,函数color_map处理将输出类ID映射到颜色以可视化输出。
import glob
from random import shuffle
import numpy as np
from PIL import Image
import tensorrt as trt
import labels #from cityscapes evaluation script
import calibrator #calibrator.py
MEAN = (71.60167789, 82.09696889, 72.30508881)
MODEL_DIR = '/data/fcn8s/'
CITYSCAPES_DIR = '/data/Cityscapes/'
TEST_IMAGE = CITYSCAPES_DIR + 'leftImg8bit/val/lindau/lindau_000042_000019_leftImg8bit.png'
CALIBRATION_DATASET_LOC = CITYSCAPES_DIR + 'leftImg8bit/train/*/*.png'
CLASSES = 19
CHANNEL = 3
HEIGHT = 512
WIDTH = 1024
def sub_mean_chw(data):
data = data.transpose((1,2,0)) # CHW -> HWC
data -= np.array(MEAN) # Broadcast subtract
data = data.transpose((2,0,1)) # HWC -> CHW
return data
def color_map(output):
output = output.reshape(CLASSES, HEIGHT, WIDTH)
out_col = np.zeros(shape=(HEIGHT, WIDTH), dtype=(np.uint8, 3))
for x in range (WIDTH):
for y in range (HEIGHT):
out_col[y,x] = labels.id2label[labels.trainId2label[np.argmax(output[:,y,x])].id].color
return out_col
这是将所有代码组合在一起的主要功能。这个tensorrt.lite模块提供高级函数,使用一个名为tensorrt.lite.Engine.
def create_calibration_dataset():
# Create list of calibration images (filename)
# This sample code picks 100 images at random from training set
calibration_files = glob.glob(CALIBRATION_DATASET_LOC)
shuffle(calibration_files)
return calibration_files[:100]
def main():
calibration_files = create_calibration_dataset()
# Process 5 images at a time for calibration
# This batch size can be different from MaxBatchSize (1 in this example)
batchstream = calibrator.ImageBatchStream(5, calibration_files, sub_mean_chw)
int8_calibrator = calibrator.PythonEntropyCalibrator(["data"], batchstream)
# Easy to use TensorRT lite package
engine = trt.lite.Engine(framework="c1",
deployfile=MODEL_DIR + "fcn8s.prototxt",
modelfile=MODEL_DIR + "fcn8s.caffemodel",
max_batch_size=1,
max_workspace_size=(256 << 20),
input_nodes={"data":(CHANNEL,HEIGHT,WIDTH)},
output_nodes=["score"],
preprocessors={"data":sub_mean_chw},
postprocessors={"score":color_map},
data_type=trt.infer.DataType.INT8,
calibrator=int8_calibrator,
logger_severity=trt.infer.LogSeverity.INFO)
test_data = calibrator.ImageBatchStream.read_image_chw(TEST_IMAGE)
out = engine.infer(test_data)[0]
test_img = Image.fromarray(out, 'RGB')
test_img.show()
在城市景观数据集中,有独立的训练、验证和测试集,遵循深度学习的常见做法。然而,这意味着没有单独的校准数据集。因此,可以从训练数据集中随机选择100幅图像用作校准数据集,以说明校准过程的工作情况。正如将看到的,校准算法可以达到良好的精度,只有100个随机图像!
使用包含计算能力为6.1的NVIDIA GPU的系统(例如Quadro P4000、Tesla P4或P40),可以运行INT8优化引擎来验证其准确性。建议运行整个验证数据集,以确保使用降低精度所带来的小精度损失是可接受的。通过使用所有500个验证图像运行Cityscapes评估脚本,发现校准后的INT8模型实现了48.1个平均类IoU和76.8个平均类IoU,而原始FP32精度模型分别为48.4和76.9。
Optimizing
the INT8 Model on DRIVE PX
TensorRT builder实现了一种基于分析的优化,称为内核自动调整。此过程要求在目标设备上优化网络。在这个目标优化阶段,可以使用从主机生成的校准缓存文件生成INT8模型,而不需要校准数据集。需要编写一个实现readCalibrationCache函数的校准器类,以告诉TensorRT使用缓存的结果,如下代码所示。
class Int8CacheCalibrator : public IInt8EntropyCalibrator {
public:
Int8CacheCalibrator(std::string cacheFile)
: mCacheFile(cacheFile) {}
virtual ~Int8CacheCalibrator() {}
int getBatchSize() const override {return 1;}
bool getBatch(void* bindings[], const char* names[], int nbBindings) override {
return false;
}
const void* readCalibrationCache(size_t& length) override
{
mCalibrationCache.clear();
std::ifstream input(mCacheFile, std::ios::binary);
input >> std::noskipws;
if (input.good()) {
std::copy(std::istream_iterator(input),
std::istream_iterator<char>(),
std::back_inserter<char>(mCalibrationCache));
}
length = mCalibrationCache.size();
return length ? &mCalibrationCache[0] : nullptr;
}
private:
std::string mCacheFile;
std::vector<char> mCalibrationCache;
利用TensorRT的INT8推断,该模型现在可以在一个驱动器PX autochauffer的Pascal GPU上以50毫秒的延迟或20个图像/秒的速度运行。图7总结了TensorRT使用FP32和INT8推断获得的性能。

Figure 7. INT8 inference with TensorRT improves inference throughput and latency by about 5x compared to the original network running in Caffe.
可以将优化的引擎序列化到一个文件中进行部署,然后就可以在驱动器PX上部署INT8优化的网络了!
基于TensorRT 3的自动驾驶快速INT8推理的更多相关文章
- 线控性能比拼,MKZ与CRV作为自动驾驶开发平台的全面测评
全球自动驾驶创业公司最主流的测试开发用车是林肯MKZ,这是因为其高性能高精度的线控能力表现,易于使用逆向工程实现改装,以及存在成熟的线控改造服务提供商AS和Dataspeed,共同为自动驾驶初创及辅助 ...
- 基于自动驾驶车辆的NVIDIA-TensorRT推理实时优化
基于自动驾驶车辆的NVIDIA-TensorRT推理实时优化 Optimizing NVIDIA TensorRT Conversion for Real-time Inference on Auto ...
- 基于DRL和TORCS的自动驾驶仿真系统——之环境配置
基于DRL和TORCS的自动驾驶仿真系统 --之环境配置 玩TORCS和DRL差不多有一整年了,开始的摸爬滚打都是不断碰壁过来的,近来在参与CMU的DRL10703课程学习和翻译志愿者工作,也将自己以 ...
- 基于TORCS和Torch7实现端到端连续动作自动驾驶深度强化学习模型(A3C)的训练
基于TORCS(C++)和Torch7(lua)实现自动驾驶端到端深度强化学习模型(A3C-连续动作)的训练 先占坑,后续内容有空慢慢往里填 训练系统框架 先占坑,后续内容有空慢慢往里填 训练系统核心 ...
- julia应用于自动驾驶汽车、机器人、3D 打印、精准医疗、增强现实、基因组学、能源交易、机器学习、金融风控和太空任务设计等多个领域
编程界的新宠 Julia 发布 1.0 正式版本,多种优势集于一身2018-08-14 14:14 公司Julia 的累积下载次数超过 200 万,已被应用于自动驾驶汽车.机器人.3D 打印.精准医疗 ...
- 自动驾驶缺人才?听听David Silver怎么说!
如今自动驾驶在全球范围内的发展势头愈发“凶猛”,该领域人才也一度被视为“香饽饽”. 即使在美国,自动驾驶工程师的起薪也已经突破了25万美元,我国‘“开价”之高更是令人咋舌. 人才.人才.还是人才!重要 ...
- 自动驾驶轻松开发?华为云ModelArts赋能智慧出行
作为战略新兴产业,人工智能已经开始广泛应用于多个领域.近几年,科技公司.互联网公司等各领域的企业纷纷布局自动驾驶.那么,自动驾驶技术究竟发展得如何了?日前,华为云携手上海交通大学创新中心举办的华为云人 ...
- 本科阶段就挑战自动驾驶开发?华为云ModelArts帮你轻松实现!
欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...
- zz自动驾驶多传感器感知的探索1
Pony.ai 在多传感器感知上积累了很多的经验,尤其是今年年初在卡车上开始了新的尝试.我们有不同的传感器配置,以及不同的场景,对多传感器融合的一些新的挑战,有了更深刻的认识,今天把这些经验,总结一下 ...
随机推荐
- Cookie、Session和Token认证
目录 Cookie Session认证机制 Session的一些安全配置 Token认证机制 Token预防CSRF Session认证和Token认证的区别 前言:HTTP是一种无状态的协议,为了分 ...
- SQLServer数据库及注入方法
目录 SQLServer数据库 SQLServer数据库的查询语句 SA权限开启xp_cmdshell获取主机权限 盲注SQLServer数据库 SQLServer数据库 SQL Server数据库是 ...
- Matlab学生账号创建激活使用
软件介绍 MATLAB主要用于数值分析.数值和符号计算.工程与科学绘图.控制系统的设计与仿真.数字图像处理.数字信号处理.通讯系统设计与仿真.财务与金融工程,是一款商业数学软件.MATLAB拥有丰富的 ...
- PhpStorm个性化设置推荐
预览 字体 字体使用jetbrains的mono,前往下载:如何安装,字体安装完成之后Restart,可在PhpStorm settings中搜索 font 进行启用 mono 字体 主题 主题推荐使 ...
- Linux下为Calibre书库打中文目录名与文件名补丁
本文由来 临近下班突然看到知乎上有篇文章是给Calibre打中文目录与文件名补丁的,想起我之前为啥放弃Calibre的--存进书库里书的名称都变成了拼音!手动找起来或者搜索工具找起来太麻烦了(有时想不 ...
- Java中实现SAX解析xml文件到MySQL数据库
大致步骤: 1.Java bean 2.DBHelper.java 3.重写DefaultHandler中的方法:MyHander.java 4.循环写数据库:SAXParserDemo.java ① ...
- 2019c#将PDF转图片
两种方法: 第一种是用O2S.Components.PDFRender4NET 大家可以去网上查找无水印版本 但是有的时候带颜色的字就变空白了 不知道为什么 第二种是用PdfiumViewer 这种方 ...
- SE_Work4_软件案例分析
项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 要求:分析软件案例 个人博客作业-软件案例分析 班级 005 这个作业在哪个具体方面帮助我实现目标 分析对比一类软件,学会规划分析软件的 ...
- Java匿名对象导致的内存泄漏
这几天与在某群与群友讨论了Runnable匿名对象导致内存泄漏的相关问题,特此记录一下. 示例代码如下: package com.memleak.memleakdemo; public class L ...
- Linux使用gcc编译时设置编码格式
我们编写 C 程序时,可以使用 ANSI 编码,或是 UTF-8 编码:在编译程序时,可以使用以下的选项告诉编译器: -finput-charset=GB2312 -finput-charset=UT ...