1.3.4. 目标文件系统
1.3.4.1. 固件
OpenCL固件包括预封装的DSP TIDL库(带有硬编码内核)和遵循定制加速器模型的EVE TIDL库。OpenCL固件在Linux引导后立即下载到DSP和M4/EVE:
- dra7-ipu1-fw.xem4 -> /lib/firmware/dra7-ipu1-fw.xem4.opencl-monitor
- dra7-dsp1-fw.xe66 -> /lib/firmware/dra7-dsp1-fw.xe66.opencl-monitor
- dra7-dsp2-fw.xe66 -> /lib/firmware/dra7-dsp2-fw.xe66.opencl-monitor
1.3.4.2. 用户空间组件
用户空间TIDL组件包含在文件夹/usr/share/ti/tidl 及其子文件夹中。子文件夹名称和说明如下:
Sub folder Description of content
examples test(文件到文件的例子),imagenet分类,图像分割和SSD多盒例子在这里。一个基于imagenet的矩阵GUI例子,在tidl_classification文件夹中。
utils 用于导入模型和仿真的ARM 32位二进制文件,以及用于运行示例导入工具操作的配置文件。
viewer 导入模型解析器和点图创建器。输入是TIDL模型,输出是.dot文件,可以使用点工具(x86)转换成PNG或PDF格式。
tidl_api TIDL API实现的来源。
1.3.5. 输入数据格式
当前版本主要用于2D输入。最常见的二维输入张量是彩色图像。格式必须与模型培训时使用的格式相同。通常,这遵循BGR平面交错格式(OpenCV中常见)。也就是说,第一个二维数组是蓝色平面,第二个是绿色平面,最后是红色平面。
但是,完全有可能仅输入两个平面:例如,一个具有激光雷达距离测量的平面和第二个具有照明的平面。这假设在训练期间使用了相同的格式。
1.3.6. 输出数据格式
•图像分类
在输出端有1D向量,每个类一个字节(log(softmax))。如果模型有100个类,输出缓冲区将有100字节长,如果模型有1000个类,输出缓冲区将有1000字节长
• 图像分割
输出缓冲区是2D缓冲区,通常是WxH(输入图像的宽度和高度)。每个字节是输入图像中像素的类索引。通常,类的计数是一个或两个几十(但必须少于255).
• 目标检测
输出缓冲区是一个元组列表,包括:类索引、边界框(4个参数)和可选的概率度量.
1.3.7. 导入过程
导入过程分两步完成.
•第一步是解析模型参数和网络拓扑,并将其转换为TIDL Lib可以理解的自定义格式。
•第二步通过找出每一层的激活范围来校准动态量化过程。这是通过调用模拟(使用本机C实现)来实现的,模拟估计对量化过程很重要的初始值。假设输入帧之间有很强的时间相关性,这些值随后会按帧更新。
在导入过程中,一些层将合并为一个TIDL层(例如卷积层和ReLU层)。这样做是为了进一步利用EVE架构,该架构允许免费执行某些操作。可以使用TIDL网络查看器检查转换(但等效)网络的结构。
我们提供了一个工具(Linux x86或ARM Linux端口)来导入在PC机上使用caffe框架或tensor flow框架训练的模型和参数,该工具通过导入配置文件接受各种参数,并生成模型和参数文件,代码将使用TIDL库跨多个EVE和DSP核心执行。导入配置文件位于{TIDL_install_path}/test/testvecs/config/import中
1.3.7.3. 导入工具跟踪
在转换过程中,导入工具生成轨迹,报告检测到的层及其参数(最后几列表示输入张量维度和输出张量维度)。
Processing config file ./tempDir/qunat_stats_config.txt !
0, TIDL_DataLayer , 0, -1 , 1 , x , x , x , x , x , x , x , x , 0 , 0 , 0 , 0 , 0 , 1 , 3 , 224 , 224 ,
1, TIDL_BatchNormLayer , 1, 1 , 1 , 0 , x , x , x , x , x , x , x , 1 , 1 , 3 , 224 , 224 , 1 , 3 , 224 , 224 ,
2, TIDL_ConvolutionLayer , 1, 1 , 1 , 1 , x , x , x , x , x , x , x , 2 , 1 , 3 , 224 , 224 , 1 , 32 , 112 , 112 ,
3, TIDL_ConvolutionLayer , 1, 1 , 1 , 2 , x , x , x , x , x , x , x , 3 , 1 , 32 , 112 , 112 , 1 , 32 , 56 , 56 ,
4, TIDL_ConvolutionLayer , 1, 1 , 1 , 3 , x , x , x , x , x , x , x , 4 , 1 , 32 , 56 , 56 , 1 , 64 , 56 , 56 ,
5, TIDL_ConvolutionLayer , 1, 1 , 1 , 4 , x , x , x , x , x , x , x , 5 , 1 , 64 , 56 , 56 , 1 , 64 , 28 , 28 ,
6, TIDL_ConvolutionLayer , 1, 1 , 1 , 5 , x , x , x , x , x , x , x , 6 , 1 , 64 , 28 , 28 , 1 , 128 , 28 , 28 ,
7, TIDL_ConvolutionLayer , 1, 1 , 1 , 6 , x , x , x , x , x , x , x , 7 , 1 , 128 , 28 , 28 , 1 , 128 , 14 , 14 ,
8, TIDL_ConvolutionLayer , 1, 1 , 1 , 7 , x , x , x , x , x , x , x , 8 , 1 , 128 , 14 , 14 , 1 , 256 , 14 , 14 ,
9, TIDL_ConvolutionLayer , 1, 1 , 1 , 8 , x , x , x , x , x , x , x , 9 , 1 , 256 , 14 , 14 , 1 , 256 , 7 , 7 ,
10, TIDL_ConvolutionLayer , 1, 1 , 1 , 9 , x , x , x , x , x , x , x , 10 , 1 , 256 , 7 , 7 , 1 , 512 , 7 , 7 ,
11, TIDL_ConvolutionLayer , 1, 1 , 1 , 10 , x , x , x , x , x , x , x , 11 , 1 , 512 , 7 , 7 , 1 , 512 , 7 , 7 ,
12, TIDL_PoolingLayer , 1, 1 , 1 , 11 , x , x , x , x , x , x , x , 12 , 1 , 512 , 7 , 7 , 1 , 1 , 1 , 512 ,
13, TIDL_InnerProductLayer , 1, 1 , 1 , 12 , x , x , x , x , x , x , x , 13 , 1 , 1 , 1 , 512 , 1 , 1 , 1 , 9 ,
14, TIDL_SoftMaxLayer , 1, 1 , 1 , 13 , x , x , x , x , x , x , x , 14 , 1 , 1 , 1 , 9 , 1 , 1 , 1 , 9 ,
15, TIDL_DataLayer , 0, 1 , -1 , 14 , x , x , x , x , x , x , x , 0 , 1 , 1 , 1 , 9 , 0 , 0 , 0 , 0 ,
Layer ID ,inBlkWidth ,inBlkHeight ,inBlkPitch ,outBlkWidth ,outBlkHeight,outBlkPitch ,numInChs ,numOutChs ,numProcInChs,numLclInChs ,numLclOutChs,numProcItrs ,numAccItrs ,numHorBlock ,numVerBlock ,inBlkChPitch,outBlkChPitc,alignOrNot
2 72 64 72 32 28 32 3 32 3 1 8 1 3 4 4 4608 896 1
3 40 30 40 32 28 32 8 8 8 4 8 1 2 4 4 1200 896 1
4 40 30 40 32 28 32 32 64 32 7 8 1 5 2 2 1200 896 1
5 40 30 40 32 28 32 16 16 16 7 8 1 3 2 2 1200 896 1
6 40 30 40 32 28 32 64 128 64 7 8 1 10 1 1 1200 896 1
7 40 30 40 32 28 32 32 32 32 7 8 1 5 1 1 1200 896 1
8 24 16 24 16 14 16 128 256 128 8 8 1 16 1 1 384 224 1
9 24 16 24 16 14 16 64 64 64 8 8 1 8 1 1 384 224 1
10 24 9 24 16 7 16 256 512 256 8 8 1 32 1 1 216 112 1
11 24 9 24 16 7 16 128 128 128 8 8 1 16 1 1 216 112 1
Processing Frame Number : 0
最终输出(基于配置文件中提供的校准原始图像)存储在保留名称的文件中:stats_tool_out.bin。此文件的大小应与输出类计数相同(在分类的情况下)。例如,对于imagenet 1000类,它必须是1000字节大。除了final blob之外,所有中间结果(单个层的激活)都存储在./tempDir文件夹中(在调用import的文件夹中)。以下是具有中间激活的文件的示例列表:
• trace_dump_0_224x224.y <- This very first layer should be identical to the data blob used in desktop Caffe (during validation)
• trace_dump_1_224x224.y
• trace_dump_2_112x112.y
• trace_dump_3_56x56.y
• trace_dump_4_56x56.y
• trace_dump_5_28x28.y
• trace_dump_6_28x28.y
• trace_dump_7_14x14.y
• trace_dump_8_14x14.y
• trace_dump_9_7x7.y
• trace_dump_10_7x7.y
• trace_dump_11_7x7.y
• trace_dump_12_512x1.y
• trace_dump_13_9x1.y
• trace_dump_14_9x1.y
1.3.7.4. 在图层组之间拆分图层
为了同时使用DSP和EVE加速器,可以使用层组的概念将网络分成两个子图。在EVE上可以执行多个层组,在DSP上可以执行另一个层组。第一组的输出(在EVE上运行)将用作DSP的输入。
这可以通过以下方式实现(提供Jacinto11网络的示例):
# Default - 0
randParams = 0
# 0: Caffe, 1: TensorFlow, Default - 0
modelType = 0
# 0: Fixed quantization By tarininng Framework, 1: Dynamic quantization by TIDL, Default - 1
quantizationStyle = 1
# quantRoundAdd/100 will be added while rounding to integer, Default - 50
quantRoundAdd = 25
numParamBits = 8
# 0 : 8bit Unsigned, 1 : 8bit Signed Default - 1
inElementType = 0
inputNetFile = "../caffe_jacinto_models/trained/image_classification/imagenet_jacintonet11v2/sparse/deploy.prototxt"
inputParamsFile = "../caffe_jacinto_models/trained/image_classification/imagenet_jacintonet11v2/sparse/imagenet_jacintonet11v2_iter_160000.caffemodel"
outputNetFile = "./tidl_models/tidl_net_imagenet_jacintonet11v2.bin"
outputParamsFile = "./tidl_models/tidl_param_imagenet_jacintonet11v2.bin"
sampleInData = "./input/preproc_0_224x224.y"
tidlStatsTool = "./bin/eve_test_dl_algo_ref.out"
layersGroupId = 0 1 1 1 1 1 1 1 1 1 1 1 2 2 2 0
conv2dKernelType = 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
输入和输出层属于层组0。层组1分配给EVE,层组2分配给DSP。
第二行(conv2dKernelType)指示计算是稀疏(0)还是密集(1)。
转换后,我们可以可视化网络:
tidl_viewer -p -d ./j11split.dot ./tidl_net_imagenet_jacintonet11v2.bin
dot -Tpdf ./j11split.dot -o ./j11split.pdf
下图(第1组在EVE上执行,第2组在DSP上执行):
层组1的输出与层组2的输入缓冲区共享(公共),因此没有额外的缓冲区复制开销。由于这种缓冲区分配,EVE和DSP的顺序操作是必要的。
1.3.7.5. 计算所需理论GMAC
对于计算最密集的层(卷积层和完全连接层),这可以预先计算。每个卷积层都有一定数量的输入和输出特征映射(2D张量)。输入特征映射用卷积核卷积(通常是3x3,但也有5x5,7x7…)。所以mac的总数可以计算为:Height_input_map x Width_input_map x N_input_maps x N_output_maps x size_of_kernel。
E.g. for 112x112 feature map, with 64 inputs, 64 outputs and 3x3 kernels, we need:
112x112x64x64x3x3 MAC operations = 4624229916 MAC operations
同样,对于全连接层,N_inputs和N_outputs的MAC操作总数为
E.g. N_inputs = 4096 and N_outputs = 1000,
Fully Connected Layer MAC operations = N_inputs * N_outputs = 4096 * 1000 = 4096000 MAC operations
显然,卷积层的工作负载明显更高。
1.3.7.6. 映射到EVE功能
每个EVE内核每周期可以执行16个MAC操作。累积的结果存储在40位累加器中,可以在存储到本地存储器之前进行桶移位。另外,EVE还可以免费进行ReLU操作,因此经常会将卷积层或全连接层与ReLU层合并。
为了支持这些操作,需要到本地内存的宽路径。来自外部DDR内存的并发传输使用专用的EDMA引擎执行。所以,当EVE进行卷积运算时,它总是同时访问已经存在于高速本地内存中的激活和权重。
一层或两层是在EVE本地RISC CPU上实现的,主要用于矢量引擎和EDMA的编程。在这些极少数情况下,EVE CPU被用作完全可编程但速度较慢的计算引擎。SoftMax层使用通用CPU实现,并且比DSP或A15实现慢得多。由于SoftMax层是终端层,建议在A15(在用户空间)或使用DSP(layergroup2,如JDetNet示例中实现的)上执行SoftMax。
1.3.8. 查看器工具
查看器工具对导入的网络模型进行可视化。更多详情请访问https://software-dl.ti.com/mctools/esd/docs/tidl-api/viewer.html 以下是一个命令行示例:
root@am57xx-evm:/usr/share/ti/tidl/examples/test/testvecs/config/tidl_models# tidl_viewer
Usage: tidl_viewer -d <dot file name> <network binary file>
Version: 01.00.00.02.7b65cbb
Options:
-p Print network layer info
-h Display this help message
root@am57xx-evm:/usr/share/ti/tidl/examples/test/testvecs/config/tidl_models# tidl_viewer -p -d ./jacinto11.dot ./tidl_net_imagenet_jacintonet11v2.bin
# Name gId #i #o i0 i1 i2 i3 i4 i5 i6 i7 o #roi #ch h w #roi #ch h w
0, Data , 0, -1 , 1 , x , x , x , x , x , x , x , x , 0 , 0 , 0 , 0 , 0 , 1 , 3 , 224 , 224 ,
1, BatchNorm , 1, 1 , 1 , 0 , x , x , x , x , x , x , x , 1 , 1 , 3 , 224 , 224 , 1 , 3 , 224 , 224 ,
2, Convolution , 1, 1 , 1 , 1 , x , x , x , x , x , x , x , 2 , 1 , 3 , 224 , 224 , 1 , 32 , 112 , 112 ,
3, Convolution , 1, 1 , 1 , 2 , x , x , x , x , x , x , x , 3 , 1 , 32 , 112 , 112 , 1 , 32 , 56 , 56 ,
4, Convolution , 1, 1 , 1 , 3 , x , x , x , x , x , x , x , 4 , 1 , 32 , 56 , 56 , 1 , 64 , 56 , 56 ,
5, Convolution , 1, 1 , 1 , 4 , x , x , x , x , x , x , x , 5 , 1 , 64 , 56 , 56 , 1 , 64 , 28 , 28 ,
6, Convolution , 1, 1 , 1 , 5 , x , x , x , x , x , x , x , 6 , 1 , 64 , 28 , 28 , 1 , 128 , 28 , 28 ,
7, Convolution , 1, 1 , 1 , 6 , x , x , x , x , x , x , x , 7 , 1 , 128 , 28 , 28 , 1 , 128 , 14 , 14 ,
8, Convolution , 1, 1 , 1 , 7 , x , x , x , x , x , x , x , 8 , 1 , 128 , 14 , 14 , 1 , 256 , 14 , 14 ,
9, Convolution , 1, 1 , 1 , 8 , x , x , x , x , x , x , x , 9 , 1 , 256 , 14 , 14 , 1 , 256 , 7 , 7 ,
10, Convolution , 1, 1 , 1 , 9 , x , x , x , x , x , x , x , 10 , 1 , 256 , 7 , 7 , 1 , 512 , 7 , 7 ,
11, Convolution , 1, 1 , 1 , 10 , x , x , x , x , x , x , x , 11 , 1 , 512 , 7 , 7 , 1 , 512 , 7 , 7 ,
12, Pooling , 1, 1 , 1 , 11 , x , x , x , x , x , x , x , 12 , 1 , 512 , 7 , 7 , 1 , 1 , 1 , 512 ,
13, InnerProduct , 1, 1 , 1 , 12 , x , x , x , x , x , x , x , 13 , 1 , 1 , 1 , 512 , 1 , 1 , 1 , 1000 ,
14, SoftMax , 1, 1 , 1 , 13 , x , x , x , x , x , x , x , 14 , 1 , 1 , 1 , 1000 , 1 , 1 , 1 , 1000 ,
15, Data , 0, 1 , -1 , 14 , x , x , x , x , x , x , x , 0 , 1 , 1 , 1 , 1000 , 0 , 0 , 0 , 0 ,
输出文件是jacinto11.dot,可以在Linux x86上转换为PNG或PDF文件,使用(例如):
dot -Tpdf ./jacinto11.dot -o ./jacinto11.pdf
• 指向JDetNet中的层组,描述如何将图划分为两个组,创建EVE最优组和DSP最优组
1.3.9. 仿真工具
我们提供PLSDK ARM文件系统仿真工具和Linux x86仿真工具。这是精确位仿真,所以仿真工具的输出应该与A5749或AM57xx目标的输出相同。请将此工具仅作为方便工具使用(例如,在没有目标EVM的设置上测试模型)。
仿真工具也可用于验证转换模型的准确性(FP32与8位实现)。它可以在x86上利用更多的内核并行运行(模拟工具是单线程实现)。由于位精确仿真,仿真工具的性能不能用来预测目标执行时间,但可以用来验证模型的准确性。
一个配置文件的例子,它包括处理帧数的规范,输入图像文件(带有一个或多个原始图像),输入图像文件的数值格式(有符号或无符号),跟踪文件夹和模型文件:
rawImage = 1
numFrames = 1
inData = "./tmp.raw"
inElementType = 0
traceDumpBaseName = "./out/trace_dump_"
outData = "stats_tool_out.bin"
netBinFile = "./tidl_net_imagenet_jacintonet11v2.bin"
paramsBinFile = "./tidl_param_imagenet_jacintonet11v2.bin"
如果需要处理多个图像,可以使用下面(或类似)脚本:
SRC_DIR=$1
echo "#########################################################" > TestResults.log
echo "Testing in $SRC_DIR" >> TestResults.log
echo "#########################################################" >> TestResults.log
for filename in $SRC_DIR/*.png; do
convert $filename -separate +channel -swap 0,2 -combine -colorspace sRGB ./sample_bgr.png
convert ./sample_bgr.png -interlace plane BGR:sample_img_256x256.raw
./eve_test_dl_algo.out sim.txt
echo "$filename Results " >> TestResults.log
hd stats_tool_out.bin | tee -a TestResults.log
done
仿真工具./eve_test_dl_algo.out 使用单个命令行参数调用:
./eve_test_dl_algo.out sim.txt
模拟配置文件包括要执行的网络模式列表,在这种情况下,只有一个:tild_config_j11.txt 列表以“0”结尾:
1 ./tidl_config_j11_v2.txt
0
模拟工具使用的样例配置文件(tidl_config_j11_v2.txt):
rawImage = 1
numFrames = 1
preProcType = 0
inData = "./sample_img_256x256.raw"
traceDumpBaseName = "./out/trace_dump_"
outData = "stats_tool_out.bin"
updateNetWithStats = 0
netBinFile = "./tidl_net_model.bin"
paramsBinFile = "./tidl_param_model.bin"
SRC_DIR中所有图像的结果将被定向到TestResults.log,并且可以在Caffe-Jacinto桌面执行中进行测试.
1.3.10. 模型移植步骤概述
•在使用桌面框架(Caffe或TF)创建模型之后,有必要验证模型的准确性(使用桌面框架上的推理:Caffe/Caffe-Jacinto或TensorFlow)。
•使用上述导入程序导入最终模型(对于Caffe-Jacinto,在“稀疏”阶段结束时)
•使用仿真工具验证准确性(使用比第一步中使用的更小的测试数据集)精度下降(相对于第一步)不应太大(百分之几)。
•使用基于TIDL API的程序和导入的模型在目标上测试网络。