利用Matlab快速在Jetson平台上开发产品

NV Blog
197 0 2019-10-02

本文讨论应用程序开发人员如何使用MATLAB在NVIDIA Jetson Nano开发工具包等硬件上构建产品原型和部署深度学习算法。在之前,我们已经探讨了如何在MATLAB中设计和训练深度学习网络,以及如何从深度学习算法中生成优化的CUDA代码。

在与深度学习工程师的工作经验中我们经常看到他们在使用真实硬件进行原型制作时会遇到挑战,因为他们必须手动整合整个应用程序代码,如接口硬件上的传感器,或与必要的工具链集成的硬件上部署并运行应用程序。如果算法没有预期的行为,或者没有达到预期的性能,他们就必须回到自己的工作平台上调试潜在的原因。

这篇文章分享了应用程序开发人员如何在真实的硬件上部署、验证和验证他们的MATLAB算法,比如NVIDIA Jetson平台:

-使用来自Jetson board的实时数据来提高算法的鲁棒性

-使用半实物仿真进行验证和性能分析

-在Jetson板上部署独立的应用程序

使用NVIDIA Jetson与MATLAB

MATLAB通过NVIDIA硬件支持包简化了NVIDIA硬件的原型化和部署。它为互动工作流程和独立执行提供简单的api,让你可以:

-直接从MATLAB连接到硬件,并在来自硬件的传感器数据上测试您的应用程序

-将独立应用程序部署到Jetson板

-在将独立应用程序部署到Jetson板之前调试任何问题

这些工作流程步骤如下图所示:

图1:演示了工作流的三个步骤

它的支持包支持英伟达Jetson TK1, Jetson TX1, Jetson TX2, Jetson Xavier和Jetson Nano开发工具包。它还支持NVIDIA Drive平台。下面的图2显示了使用这些api与使用MATLAB的NVIDIA硬件一起工作的伪代码:


% builtin APIs to connect to Jetson hardware
hwobj= jetson('jetsonnano','username','password');
 
% APIs to fetch sensor data and run inference in MATLAB for validation
input_img=hwobj.webcam.snapshot;
output=InferenceFunction(input_img);
 
% Generate code and configure it to run in hardware in loop mode
codegen('-config',cfg,'InferenceFunction','-args',{test_img},'-report');
 
%Run the inference on the hardware and verify 
output_new=InferenceFunction_pil(input_img);
compare(output, output_new);


图2:使用MATLAB处理Jetson平台的api

缺陷检测的例子
让我们考虑一个用于缺陷检测的工业自动化应用程序,它来自我们的一个客户,该客户使用GPU Coder来部署他们的深度学习应用程序,以使用Jetson开发工具包来检测制造部件中的异常。我们将考虑一个类似的应用作为一个例子,并开发一个深度学习算法来检测制造的螺母和螺栓的缺陷,但这自然扩展到其他应用领域,如工业设备的预测维修等。

图3:每月自动检测130万个锥齿轮来检测汽车零部件的异常

我们选择了一个12层的系列网络,如图6中的Deep network Designer app所示,用于这个图像分类任务。预处理函数myNDNet_Preprocess:

使用rgb2gray函数将原始输入图像从RGB转换为灰色

使用bwareaopen函数识别感兴趣的区域

利用imcrop函数将灰度图像裁剪到四个感兴趣的区域

最后使用imresize函数将裁剪后的区域调整为网络的输入大小

predict函数对每个裁剪的区域进行分类,并输出每个类的概率得分——OK或NG(表示不好)。

然后,后处理函数使用insertObjectAnnotation函数和适当的标签通过比较概率分数来注释原始图像中感兴趣的区域。

图6:MATLAB中的Deep Network Designer App

一旦您在测试图像数据集上测试了您的算法,您就可以从MATLAB直接连接到Jetson板上的Jetson板上的算法原型。对于本例,我们选择了Jetson Nano板,正如您在图7中所看到的,一旦您使用插件支持包连接到该板,它还会检查以确保安装了所有必需的软件包。现在,您可以通过调用MATLAB中webcam对象的snapshot方法,对从连接到Jetson Nano的webcam捕获的图像测试您的算法,如下图所示:


>> hwobj=jetson('Device_address','username’,'password’);
Checking for CUDA availability on the Target...
Checking for 'nvcc' in the target system path...
Checking for cuDNN library availability on the Target...
Checking for TensorRT library availability on the Target...
Checking for prerequisite libraries is complete.
Gathering hardware details...
Gathering hardware details is complete.
 Board name        : NVIDIA Jetson TX1
 CUDA Version      : 10.0
 cuDNN Version     : 7.3
 TensorRT Version  : 5.0
 Available Webcams :  
 Available GPUs    : NVIDIA Tegra X1
>> img=hwobj.webcam.snapshot;
>>
图7:连接到Jetson平台并将输入图像从webcam读入MATLAB的api



一旦我们读取了连接到Jetson Nano的摄像头的图像输入,我们就可以在MATLAB中测试我们的应用程序。在本例中,我们必须为bwareaopen函数调整连接像素的数量参数,以校准来自相机的图像。这是一个典型的用例,用于验证算法的健壮性,并在生成代码和部署应用程序之前排除任何问题,因为通常传感器输入的数据可能与训练和测试数据不完全相同。

接下来,我们从应用程序中生成CUDA代码,正如在webinar中详细解释的那样,您可以通过配置代码生成配置对象来生成优化的CUDA源代码或静态库或可执行文件。图8显示了用于生成针对Jetson Nano的静态库的配置对象。codegen命令使用配置对象生成优化的CUDA代码,然后使用Jetson板上的nvcc编译器将其编译成静态库。我们还启用了PIL验证模式和CodeExecutionProfiling选项为真。这将使我们能够将数据从硬件上的应用程序传递到MATLAB。我们将在下一节详细讨论这个问题。


cfg = coder.gpuConfig('lib');
cfg.DeepLearningConfig = coder.DeepLearningConfig('tensorrt');
cfg.Hardware = coder.hardware('NVIDIA Jetson');

cfg.VerificationMode='PIL';
cfg.CodeExecutionProfiling = true;

cfg.Hardware.DeviceAddress=’jetson-nano';
cfg.Hardware.Username=’username’;
cfg.Hardware.Password='password’;

codegen('-config',cfg,'targetFunction','-args',{img_test},'-report');
图8:代码生成配置对象。


我们代码生成完成后,您可以生成如图9所示的代码跟踪报告,通过将生成的代码映射到MATLAB代码来理解生成的代码。生成的代码利用GPU的计算能力,不仅加速深度学习推理,而且加速整个应用程序,包括预处理和后处理逻辑。图9突出显示了右侧CUDA代码与MATLAB中的predict函数对应的部分,您可以看到相应的内核调用和cudaMemcpy调用。


图9:代码生成报告,跟踪生成的CUDA内核到相应的MATLAB代码

接下来,我们将通过半实物仿真来验证算法和生成的代码的等价性。半实物仿真是一种常见的方法,用于在MATLAB中仿真的较大应用程序的环境中测试硬件上生成的代码。硬件支持包api使您能够在Jetson Nano上运行可执行文件,并与MATLAB进行通信。然后可以使用MATLAB中的测试数据作为输入,并将可执行文件的输出与MATLAB中的预期输出进行比较。这不仅允许您比较算法的等价性,而且可执行文件中的插装挂钩还允许您获得应用程序运行时性能的度量。我们使用PIL对大约150张测试图像进行推理,在Jetson Nano上观察到大约18个fps的推理速度。这并不是对Jetson上运行时性能的准确度量,因为收集分析数据需要额外的工具开销,但是可以很好地估计预期的运行时性能。

图10:来自Jetson Nano的应用程序的代码执行概要

事实上,我们运行了一个快速测试来比较我们的应用程序在Jetson Xavier和Jetson Nano之间的性能。这很容易实现,只需将参数更改为Jetson API,以连接到正确的Jetson板。然后,我们使用类似的API来生成在Raspberry Pi上运行的c++代码,您可以看到图11中的比较。

图11:基于PIL执行profile的推理速度对比。

最后,只需更新代码生成配置,就可以将算法部署为独立的应用程序。

cfg = coder.gpuConfig (exe);

此外,我们还更新了应用程序,以便直接从webcam读取输入,并在连接到Jetson的输出显示器上显示输出图像。支持包生成必要的代码来与连接到Jetson Nano上的摄像机进行接口,避免了手工编码或集成的需要,使工程师能够在无缝的工作流程中从算法开发到快速原型设计再到部署。 


hwobj = jetson;
w = webcam(hwobj);
d = imageDisplay(hwobj);

结论:

在这个博客中,我们分享了如何在MATLAB的NVIDIA Jetson平台上原型化和部署深度学习算法。在从开发到硬件部署的过程中,工作流极大地简化了设计迭代和调试。如果您有兴趣进一步研究NVIDIA硬件支持包,请查看下面的附加资源。

  1. NVIDIA Jetson Support from GPU Coder
  2. Deploy and Run Sobel Edge Detection with I/O on NVIDIA Jetson