5. 编译仿真性能分析使用指南

名词解释

名词

说明

Knight

清微骑士工具链英文名称

CGRA

粗粒度可重构阵列处理器

RNE

可重构神经网络加速引擎

FSPM

CGRA芯片内部数据缓存

WSPM

CGRA芯片权重数据缓存

MSPM

CGRA芯片量化参数缓存

DDR

CGRA芯片外部数据缓存

DMA

直接存储器访问功能

RCCN

可重构矩阵计算功能

RCVT

可重构向量计算功能

RDMA

读DMA功能

WDMA

写DMA功能

5.1. 简介

本文档主要介绍清微骑士工具链 Knight 在模型编译、模拟和性能分析方面的功能及使用方法。内部涉及到的相关模块简介如下:

  • Knight编译器 Knight-Compiler :编译转换量化模型,产生芯片执行的指令配置文件。

  • Knight模拟器 Knight-Simulator :用于仿真神经网络在芯片上推理计算过程,输出计算层的结果。

  • Knight性能分析器 Knight-Profiling :用于分析神经网络在芯片上执行时间和存储开销,并给出分析报告。

5.2. 开发流程

pipeline

  1. 用户模型通过Knight量化工具得到网络量化模型。

  2. 使用Knight编译器编译网络量化模型,生成模拟器和芯片部署文件,分别包含指令文件和权重文件。

  3. Knight模拟器加载模型部署文件,输出网络推理结果,用于功能验证。

  4. Knight性能分析器加载模型部署文件,分析模型完成计算的时间,用于模型性能预估。

  5. Knight模拟库供用户在PC端调用编写自己的应用程序,从而实现模拟运行结果。

  6. Knight运行时库供用户在PC端交叉编译时调用,从而实现板端运行。

5.3. Knight编译器

5.3.1. 概述

Knight 编译器用于加载量化模型,生成芯片配置指令文件和权重参数文件。

5.3.2. 编译步骤

编译步骤如下:

pipeline

步骤说明

加载及解析网络模型

1.通常网络模型中的算子需要经过Knight量化工具量化后,Knight编译器才能识别并正常编译,部分算子除外。

2.识别格式是protobuf定义的特定文件格式。

优化网络结构

1.层合并:例如Convolution+BN。

2.层替换:例如某些层可以通过卷积替换提高硬件的计算效率。

3.层分割:例如限于硬件资源,某些层需要按照channel划分为多次计算。

分配计算资源

基于硬件的存储资源及网络结构分配地址信息。

生成指令文件及权重文件

1.生成带有调试信息的指令及权重。

2.生成不带调试信息的指令及权重。

5.3.3. 使用说明

5.3.3.1. 命令格式

caffe模型:

Knight --chip [chiptype] compile --net example.prototxt
--weight example.caffemodel --save-dir ./example/

onnx模型:

Knight --chip [chiptype] compile --onnx example.onnx --save-dir ./example/

5.3.3.2. 参数说明

-h或--help
  • 可选

  • 默认值:无

  • 说明:显示帮助信息

--run-config或-rc
  • 可选

  • 说明:命令行配置文件路径。命令行参数的优先级高于配置文件中的对应项。请参考 使用指南综述 的--run-config参数说明。

--net
  • 格式: --net net_file

  • 说明:编译caffe模型的必要参数。设定神经网络模型文件路径。

--weight或-w
  • 格式: --weight weight_file或-w weight_file

  • 说明:编译caffe模型的必要参数。设定神经网络权重文件路径。

--save-dir
  • 格式: --save-dir save_dir

  • 可选

  • 默认值:无

  • 说明:设置输出文件路径,默认为 /TS-KnightOutput/RneCompile 路径。

--log-level或 -l
  • 可选

  • 取值范围: {0,1,2,3}

  • 默认值:3

  • 说明:设定log输出等级,默认为3。0=DEBUG 1=INFO 2=WARNING 3=ERROR

--onceload-m
  • 可选

  • 默认值:-1,不使用onceload-m。

  • 说明:按照一次性载入权重的网络格式编译芯片配置文件时,量化参数的偏移值。 mspm_offs为MSPM空间的偏移。若多个模型使用onceload-m,则第一个模型指定mspm_offs为0,后面依次加上前一个模型end值(编译log里会有类似MSPM once load end:xxx的提示)。 不同芯片类型,参数的取值范围也不同,详见 compile部分参数详细说明

--onceload-w
  • 可选

  • 默认值:-1,不使用onceload-w。

  • 说明:按照一次性载入权重的网络格式编译芯片配置文件时,权重的偏移值。 wspm_offs为WSPM空间的偏移。若多个模型使用onceload-w,则第一个指定wspm_offs为0,后面依次加上前一个模型end值(编译log里会有类似WSPM once load end:xxx 的提示)。 不同芯片类型,参数的取值范围也不同,详见 compile部分参数详细说明

--output
  • 可选

  • 默认值:无

  • 说明:指明需要导出的blob_name。参数blob_name是在模拟器仿真d版本的cfg和weight配置时输出的blob_name。

备注

1)设置该参数确保某一个layer的输出blob在计算结束时是作为网络结果输出。

2)设置-l 0编译时,在npu_compile_xxx.log文件中可以看到所有可设置的blob_name列表。

3)多输出场景,需要多次使用--output参数,每次指定一个blob_name。如:--output blob_1 --output blob_2

设置--output参数出现blob_name错误原因和解决方法见 如何正确设置编译器--output参数值?

--general-process或-gp
  • 格式: --general-process或-gp

  • 可选

  • 默认值:关闭。

  • 说明:设置该参数时,打开自编译通用类型算子的开关。打开状态时,遇到不识别的算子自动编译成通用类型算子。关闭状态时,遇到不识别的算子报error。

备注

不识别的算子,是指除了规格表中定义的算子(包含高效类型算子和通用类型算子)之外的算子

--opt-ddr
  • 可选

  • 取值范围:{0,1,2}

  • 默认值:1

  • 说明:可选参数。指示是否对ddr做优化。

    0:算子使用的ddr缓存地址没有重叠,支持模拟器debug中间层输出功能,使用的ddr缓存较大。

    1:算子使用的ddr缓存地址会有重叠,使用ddr缓存相对较小。

    2:算子使用的ddr缓存地址会有重叠,不支持模拟器debug中间层输出功能,使用ddr缓存更小。

备注

如果使用Knight模拟器的--debug参数调试网络, 只能使用--opt-ddr 0。

--debug
  • 可选

  • 默认值:false

  • 说明:设置该参数时,打开编译输出xxx_d.tsmodel文件的开关。

    关闭状态时:编译不输出xxx_d. tsmodel文件。

    打开状态时:编译输出xxx_d. tsmodel文件。

--unfixloop
  • 可选

  • 默认值:false

  • 说明:设置该参数时,编译循环神经网络为不定循环次数的网络。

    1. 此参数控制是否编译循环神经网络为不定循环次数的网络。如果设置该参数,开启不定循环次数编译,编译器会做相应处理,对应保存的数据的中间数据缓存在执行时不会被清零。

    2. 配合Knight模拟器的-fs,-fc使用。

--sparse
  • 可选

  • 默认值:false

  • 说明:设置该参数时,打开权重稀疏化压缩的开关。部分芯片支持,详见 compile部分参数详细说明

--res-version
  • 可选

  • 默认值:1.0

  • 说明:配置资源版本号。配置的资源版本号编译到cfg文件中,用于模拟库和板端部署模型查询。最多支持配置16个字符。

--onnx
  • 可选

  • 说明:编译onnx模型的必选参数。设定onnx神经网络模型文件路径。

--res-version
  • 可选

  • 默认值:1.0

  • 说明:配置资源版本号。配置的资源版本号编译到cfg文件中,用于模拟库和板端部署模型查询。最多支持配置16个字符。

--opt-group
  • 可选

  • 取值范围: {0,1,2}

  • 默认值:0

  • 说明:此参数设置网络组优化策略。

    0: 不使用网络组优化。

    1: 使用内部融合处理算法进行优化。

    2: 使用遗传算法进行优化。

    不支持循环网络

--input-indep
  • 可选

  • 默认值:false

  • 说明:设置该参数时,打开input blobs mem是否独立于blobs mem的开关。后续推理流程支持SDK与模拟器。

    关闭状态时:input blobs mem 在blobs mem 里面,由SDK分配控制。

    打开状态时:input blobs mem 在blobs mem 外面,模型每个input blob所需内存由用户分配控制,SDK调用时将RNE_BLOB_S的vpAddr指针指向该内存(用户通过TS_MPI_TRP_RNE_GetInputBlobs获取vpAddr指针直接赋值实现;或通过TS_MPI_TRP_RNE_SetInputBlobsAddr接口实现)。RNE推理时不会覆盖此内存。用户可将前处理后的定点input data按HWCStride格式直接放入此内存,data数据为8bit或16bit的整型数(与输入层量化位宽对应),此时可以提高整个应用的性能。用户也可以通过TS_MPI_TRP_RNE_FillInputBlobs接口将input data放入此内存,此时无性能提升。详见 --input-indep参数说明流程图

备注

除TX510x外,其他芯片都支持该参数; Input后接通用算子时,不支持该参数。

--hardware-resource-mode或-hrm
  • 可选
    • 取值范围: {"little","middle", "big", "super"}

    • 默认值:super

    • 说明:此参数控制用户可使用的硬件资源大小,包括FSPM,MSPM,WSPM等。指定为little模式编译不过时,可使用big或super模式。

      little:只能使用最少的硬件资源。

      middle:与little模式相比,使用较多的硬件资源。

      big:与middle模式相比,使用较多的硬件资源。

      super:使用全部硬件资源

备注

目前只有TX5336x_TX5256x芯片支持该参数。

--start-layer-name或-sln
  • 可选

  • 默认值:模型的起始节点

  • 说明:支持编译ONNX模型的子网络,该参数指定子网络的起始layer。通常情况下,此参数与-eln同时使用。当原始的ONNX模型只有一个输入时,该参数可忽略,默认编译从原始模型的输入开始到-eln指定layer结束

备注

1)不支持input或cast作为参数值

2)卷积类算子会被量化为(GEMM/Conv/Deconv) + BN算子组合。在这种情况下,BN层名不能作为参数值。

3)GlobalAveragePooling或AveragePooling被量化为pooling + PyOp算子组合,PyOp层名不能作为参数值。

4)当算子有多个输入时,层名不能作为参数值。

详细说明见 编译器设置-sln/-eln注意事项

--end-layer-name或-eln
  • 可选

  • 默认值:编译从-sln指定layer开始到模型结束

  • 说明:支持编译ONNX模型的子网络,该参数指定子网络的结束layer。通常情况下,此参数与-sln同时使用。 当原始的ONNX模型只有一个输出时,该参数可忽略。

备注

1)卷积类算子会被量化为(GEMM/Conv/Deconv) + BN算子组合。在这种情况下,卷积(GEMM/Conv/Deconv) 层名不能作为参数值。

2)GlobalAveragePooling或AveragePooling被量化为pooling + PyOp算子组合,pooling层名不能作为参数值。

3)当算子有多个输出时,层名不能作为参数值。

详细说明见 编译器设置-sln/-eln注意事项

--input-order
  • 可选

  • 取值范围: {nchw,nhwc}

  • 默认值:nchw

  • 说明:指定模型输入节点数据排布顺序,仅在编译模型Blip, Clip, Swin Transformer 时,必需指定--input-order nhwc , 此时会带来性能优化;模拟器和板端部署时需要指定输入数据format 为nhwc 。

--output-indep
  • 可选

  • 默认值:false

  • 说明:设置该参数时,打开output blobs mem是否独立于blobs mem的开关。后续推理流程支持SDK与模拟器。

    关闭状态时:output blobs mem 在blobs mem 里面,由SDK分配控制。

    打开状态时:output blobs mem 在blobs mem 外面,模型每个output blob所需内存由用户分配控制,SDK调用时将RNE_BLOB_S的vpAddr指针指向该内存(用户通过TS_MPI_TRP_RNE_GetOutputBlobs获取vpAddr指针直接赋值实现;或通过TS_MPI_TRP_RNE_SetOutputBlobsAddr接口实现)。推理时不会覆盖此内存。用户也可以通过TS_MPI_TRP_RNE_DumpOutputBlobs接口将output data放入此内存,此时无性能提升。

    详见 --input-indep参数说明流程图

--transformer-opt
  • 可选

  • 默认值:false

  • 说明: 设置该参数时,将连续多个reshape、permute或连续多个reshape或连续多个permute算子合并为算子(gather或move)。

    关闭状态时:关闭该优化。

    打开状态时:打开算子合并。

    参数使用场景见 编译器--transformer-opt使用场景?

--rgb
  • 可选

  • 默认值:false

  • 说明:TX5336x_TX5256x芯片3通道输入推荐使用。设置该参数时,编译的模型接受RGB 3/6/9通道数据输入。该参数用于硬件直接载入定点输入数据,无需软件层预处理。

  • 注意:

TX5112x_TX5239x201系列芯片受硬件限制不支持9通道输入; 多batch或者无法一次全部装填到fspm的输入,h*w*c必须是4的倍数; 该参数只处理4维输入的模型。

-sr或-serial-run
  • 可选

  • 取值范围:{0,1}

  • 默认值:0

  • 说明:编译运行指令串行。

0: 不打开。 1: 打开。 仅TX5336x支持。

5.3.3.3. compile部分参数详细说明

部分参数只支持特定芯片,详情见下表(Y:支持 N:不支持)

参数

TX5326x

TX5368x_TX5339x_TX5335x

TX5215x_TX5239x200_TX5239x220_TX5239x300

TX5112x_TX5239x201

TX5336x_TX5256x

--unfixloop

Y

Y

Y

Y

Y

--sparse

N

Y

N

N

Y

--input-indep

Y

Y

Y

Y

Y

--hardware-resource-mode

Y

N

N

N

Y

--start-layer-name

Y

Y

Y

Y

Y

--end-layer-name

Y

Y

Y

Y

Y

---input-order

Y

Y

N

N

Y

--output-indep

Y

N

N

N

Y

--transformer-opt

Y

Y

N

N

Y

部分参数在不同芯片中的使用有差异,差异如下

TX510x芯片
--onceload-m

1.mspm end值计算:(mspm_offs + 127)/128*128 + mweight size。

2.如果输入的mspm_offs值不是128字节对齐,编译器会将mspm_offs对齐到128字节。

--onceload-w

1.wspm end值计算:(wspm_offs + 255)/256*256 + wweight大小。

2.如果输入的wspm_offs值不是256字节对齐,编译器会将wspm_offs对齐到256字节。

TX5368x_TX5339x_TX5335x芯片
--onceload-m

1.mspm end值计算:(mspm_offs + 255)/ 256*256 + mweight大小。

2.如果输入的mspm_offs值不是256字节对齐,编译器会将mspm_offs对齐到256字节。

3.编译输出的mweight文件为256字节对齐。

--onceload-w

1.wspm end值计算:(wspm_offs + 511)/ 512*512+ wweight大小。 2.如果输入的wspm_offs值不是512字节对齐,编译器会将wspm_offs对齐到512字节。

3.编译输出的wweight文件为256字节对齐。

--sparse
权重稀疏化压缩生效的条件:

1.Conv/innerproduct。

2.权重是8bit。

3.权重在稀疏化压缩时有正收益。

4.kernel_h <= 8 && kernel_w < =8。

5.特殊情况,Ci和kernel_w满足Ci>=1&&Ci<=4且kernel_w >= 3 &&kernel_w < =8时,不做稀疏化。

6.Ci方向满足连续32个为0,会被稀疏化,为一个稀疏化块(每32个Ci方向为一块)。如Ci为64,C0-C31为0或C32-C64为0。实际Ci小于32,连续Ci个为0即满足Ci方向稀疏化。

Co方向满足连续64个filter有相同的稀疏化块。Co小于64,实际Co满足即可。

TX5215x_TX5239x200_TX5239x220_TX5239x300芯片
--onceload-m

1.mspm end值计算: (mspm_offs+127)/ 128*128+ mweight大小。

2.如果输入的mspm_offs值不是128字节对齐,编译器会将mspm_offs对齐到128字节。

--onceload-w

1.wspm end值计算:(wspm_offs + 127)/128*128+ wweight大小。

2.如果输入的wspm_offs值不是128字节对齐,编译器会将wspm_offs对齐到128字节。

TX5112x_TX5239x201芯片
--onceload-m

1.mspm end值计算:(mspm_offs + 127)/ 128*128 + mweight大小。

2.如果输入的mspm_offs值不是128字节对齐,编译器会将mspm_offs对齐到128字节。

--onceload-w

1.wspm end值计算:(wspm_offs + 63)/64*64 + wweight大小。

2.如果输入的wspm_offs值不是64字节对齐,编译器会将wspm_offs对齐到64字节。

TX5336x_TX5256x芯片
--onceload-m

1.mspm end值计算:(mspm_offs + 255)/ 256*256+ mweight大小。

2.如果输入的mspm_offs值不是256字节对齐,编译器会将mspm_offs对齐到256字节。

--onceload-w

1.wspm end值计算:(wspm_offs + 511)/ 512*512+ wweight大小。

2.如果输入的wspm_offs值不是512字节对齐,编译器会将wspm_offs对齐到512字节。

--sparse

权重稀疏化压缩生效的条件:

1.Conv/innerproduct。

2.权重在稀疏化压缩时有正收益。

3.kernel_h <= 8 && kernel_w < =8。

4.stride_w >=1 && stride_w <=2。

5.特殊情况,Ci和kernel_w满足以下任一条件,不做稀疏化。

1)Ci>=1&&Ci<=4且kernel_w >= 3 &&kernel_w < =8。

2)Ci>4&&Ci<=8且kernel_w >= 2 &&kernel_w < =4。

6.Ci方向满足连续32个为0,会被稀疏化,为一个稀疏化块(每32个Ci方向为一块)。如Ci为64,C0-C31为0或C32-C64为0。实际Ci小于32,连续Ci个为0即满足Ci方向稀疏化。

7.支持8bit和16bit权重。

1)8bit:Co方向满足连续64个filter有相同的稀疏化块。Co小于64,实际Co满足即可。

2)16bit:Co方向满足连续32个filter有相同的稀疏化块。Co小于32,实际Co满足即可。

TX5326x芯片
--onceload-m

1.mspm end值计算:(mspm_offs + 255)/ 256*256+ mweight大小。 2.如果输入的mspm_offs值不是256字节对齐,编译器会将mspm_offs对齐到256字节。

--onceload-w

1.wspm end值计算:(wspm_offs + 255)/ 256*256+ wweight大小。 2.如果输入的wspm_offs值不是256字节对齐,编译器会将wspm_offs对齐到256字节。

5.3.3.4. --input-indep参数说明流程图

pipeline

5.3.3.5. 输出文件

文件

说明

*_r.tsmodel

模拟器指令和权重部署文件,用于模拟器仿真。

*_d.tsmodel

模拟器指令和权重部署文件,带有调试信息,用于模拟器仿真。

*_r.cfg

(即将废弃)芯片指令部署文件,不带有调试信息。用于芯片加载初始化。

*_r.weight

(即将废弃)芯片权重部署文件,包含模型权重和量化参数,用于芯片加载初始化。

log/npu_compile_yyyymmdd.log

log文件(yyyymmdd表示日志生成的日期,如20221011)。

备注

注意: *代表输入网络的basename(文件名中去除目录和扩展名的部分)。

5.3.3.6. ErrorCode

代 码

说明

0001

读文件错误。

0002

写文件错误。

0003

权重排列错误。

0004

网络配置错误。

0005

编译网络时出现逻辑错误。

0006

启动参数配置错误。

0007

该层需要占用的缓存太大,无法编译。

表示编 译器编译处理某一层算子时所需fspm缓存太大,超过硬件规格限制。

详细内存分配使用,可打开INFO级别的日志查看。

0008

芯片指令生成错误。

0009

数据索引超出应有范围。

5.4. Knight RNE模拟器

5.4.1. 概述

模拟器工具的主旨是通过Linux PC软件模拟硬件的运行情况,根据编译器生成的网络指令部署文件和网络权重部署文件,进行网络推理与功能验证。

模拟器的原理是模拟硬件算子的处理,根据指令数据决定算子的组合,每个算子根据输入数据、权重数据、量化数据进行数据处理,从而实现整个网络的推理。

模拟器目前支持多帧输入,支持输入nhwc/nchw/nhwcstride格式转换、支持查看最终推理结果输出和每层结果输出,支持查看网络推理前的输入数据等。

5.4.2. 使用说明

5.4.2.1. 命令格式

# config&&weight
Knight --chip [chiptype] run --input example.input
--config example.cfg --weight example.weight --save-dir ./example/

# tsmodel:
Knight --chip [chiptype] run --input example.input
--model example.tsmodel --save-dir ./example/

5.4.2.2. 参数说明

-h 或 --help
  • 可选

  • 说明:显示帮助信息。

-rc 或 --run-config
  • 可选

  • 说明:命令行配置文件路径。命令行参数的优先级高于配置文件中的对应项。

-i 或 --input
  • 可选

  • 说明:网络输入数据,数据格式是整型或浮点类型bit流格式。对于有多个输入的网络模型,把输入数据按照网络输入顺序合并放入一个总二进制文件中,或者按顺序放入多个二进制文件中,格式为"input_file1:input_file2:..."或"input_file1,input_file2,..."。

-fmt 或 --format
  • 可选

  • 取值范围:{nchw,nhwc,nhwcstride}

  • 默认值:nhwc

  • 说明: 取值范围:nchw|nhwc|nhwcstride 输入数据为(n,h,w,c)格式时可以不指定该参数。 输入数据为(n,c,h,w)格式时需要指定参数:--format nchw。 输入数据为(n,h,w,cstride)格式时需要指定参数:--format nhwcstride,cstride通过编译器指定-l = 1获取, info级别日志会打印”The cstride value of input{idx}: {cstride_value}”。

-m 或 --model
  • 可选

  • 说明:模拟器指令权重合一部署文件,编译工具Knight RNE编译器输出(*_r.tsmodel或*_d.tsmodel)

-w 或 --weight
  • 可选

  • 说明:模拟器权重部署文件,编译工具Knight RNE编译器输出(*_r.weight或*_d.weight)。

-cfg 或 --config
  • 可选

  • 说明:模拟器指令部署文件,编译工具Knight RNE编译器输出(*_r.cfg或*_d.cfg)。

-d 或 --debug
  • 可选

  • 默认值:无

  • 说明:layer_name: 网络层名字,可以在编译器指定log为0生成的npu_compile_xxx.log文件中查看所有layer_name。指定layer_name后运行模拟器,会输出该层的结果文件。

xxx.json: 量化生成的json文件,该文件中包含一个或多个由算子类型、算子名称和算子输出组成的信息,格式如下所示:

[
{
        "op_type": "Conv",
        "op_name": "conv1_scaleFix",
        "op_output_name": "sc1_decupled"
}
]

op_name同layer_name。

传参时不支持同时传入layer_name和xxx.json文件,且只能传入一个xxx.json文件。若遇到不存在的layer_name,会输出警告信息,继续debug下一层。

使用--debug参数时,需要使用*_d.cfg和*_d.weight。

设置为all时自动输出全部layer的数据。 调试层为没有量化的层时,该层的结果文件类型由下一层的输入类型决定。

-l 或 --log-level
  • 可选

  • 取值范围:{0,1,2,3}

  • 默认值:3

  • 说明:默认值设定log输出等级. 0=DEBUG 1=INFO 2=WARNING 3=ERROR

--save-dir
  • 可选

  • 默认值:/TS-KnightOutput/RneSim

  • 说明:设置输出文件路径。

-fs 或 --frame-step
  • 可选

  • 默认值:0

  • 说明:帧移。只有在fc>1的情况下,该值才有实际意义(即帧移在第二帧开始生效)。

    多帧模式(fc>1):模拟器会把输入数据按照帧移一帧一帧计算到输入数据,剩余数据不足一帧情况的舍弃计算。

    在有多个网络输入数据的网络中,允许多网络输入数据有不同帧移,以“帧移1:帧移2:...”或“帧移1,帧移2,...”格式输入,输入帧移个数可以为1个或者与网络需要输入个数相同,其他均为错误输入。

-fc或--frame-count
  • 可选

  • 默认值:1(单帧)

  • 说明:帧数。多帧模式有效(fc>1), 表示多帧模式下计算的帧数。设置该值时,程序会自动计算至输入数据的帧移数,剩余数据不足一帧的情况则舍弃计算。实际运行的帧数为最大可运行帧数和输入帧数的最小值。

-if 或--intofile
  • 可选

  • 默认值:0

  • 说明:类型为 int 将网络输入数据按照各路输入顺序存储到文本文件(intofile.txt)。

    -1:存储指定帧数组数据,每组数据包含完整一帧大小的各路输入数据;

    0:关闭,不保存数据到文本文件;

    >=1:存储指定帧数组数据,每组数据包含各路输入m个数据,m为 size 和一帧数据大小的最小值。

5.4.2.3. 输出文件

文件

内容

说明

result-layer_name-blob_name_p.txt

中间层的输出 (十进制)

数据顺序: CHW

设定的输出层的数据。 例如:调用Knight RNE模拟器时参数--debug是fc1, fc1的output blob name是fc1_output。 则生成十进制表示的输出文件:result-fc1-fc1_output_p.txt。

result-layer_name-blob_name_hwc_p.txt

中间层的输出

(十进制)

数据顺序:HWC

设定的输出层的数据。

例如:调用Knight RNE模拟器时参数 --debug是fc1,fc1的outputblob name是fc1_output。 则生成十进制表示的输出文件: result-fc1-fc1_output_hwc_p.txt。

result-blobname_hwc_p.txt

网络结果输出 (十进制)

数据顺序:HWC

调用Knight RNE模拟器时不设定参数--debug, 则生成整个网络的输出结果的十进制表示的文件 result-blobname_hwc_p.txt。

result-blobname_p.txt

网络结果输出 (十进制)

数据顺序:CHW

调用Knight RNE模拟器时不设定参数--debug, 则生成整个网络的输出结果的十进制表示的文件 result-blobname_p.txt。

npu_sim_yyyymmdd.log

log文件

log文件(yyyymmdd表示日志生成的日期,如20221011)。

intofile.txt

网络输入数据, 根据输入blobs 类型直接存储

保存网络输入数据的文本文件。

5.5. Knight RNE性能分析器

5.5.1. 概述

性能分析器工具的主旨是通过Linux PC软件模拟硬件的运行情况,根据编译器生成的网络指令部署文件和网络权重部署文件,进行网络耗时估计。

Knight RNE性能分析器的原理是模拟硬件算子的处理,根据指令数据决定算子的组合, 每个算子根据输入数据、权重数据、量化数据进行数据处理耗时分析,从而实现网络的耗时分析。

5.5.2. 使用说明

5.5.2.1. 命令格式

#config&weight
Knight --chip [chiptype] profiling --config example.cfg
--weight example.weight --save-dir ./example/

#tsmodel
Knight --chip [chiptype] profiling --model example.tsmodel
--save-dir ./example/

5.5.2.2. 参数说明

-h 或 --help
  • 可选

  • 说明:显示帮助信息。

-m 或 --model
  • 可选

  • 说明:模拟器指令权重合一部署文件,编译工具Knight RNE编译器输出(*_r.tsmodel或*_d.tsmodel). TX510X不使用此参数,weight和cfg是必选,其他芯片使用cfg/weight或者tsmodel。

-w 或 --weight
  • 可选

  • 说明:模拟器权重部署文件,编译工具Knight RNE编译器输出(*_r.weight或*_d.weight)。TX510X为必选参数,其他芯片不需要此参数。

-cfg 或 --config
  • 可选

  • 说明:模拟器指令部署文件,编译工具Knight RNE编译器输出(*_r.cfg或*_d.cfg)。

-l 或 --log-level
  • 可选

  • 取值范围:{0,1,2,3}

  • 默认值:3

  • 默认值设定log输出等级. 0=DEBUG 1=INFO 2=WARNING 3=ERROR

-mbw 或 --max-storage-bandwidth
  • 可选

  • 默认值:不同芯片类型,默认值及取值范围也不同,详见 profiling部分参数详细说明

  • 说明:设置最大存储带宽,单位GB/s。当设置为0时,按默认值处理。

-bu 或 --bandwidth-utilization
  • 可选

  • 默认值:1.00

  • 说明:设置带宽占用率,取值范围:0~1.00。

--save-dir
  • 可选

  • 默认值:/TS-KnightOutput/RneProfiling

  • 说明:设置输出文件路径。

5.5.2.3. profiling部分参数详细说明

max-storage-bandwidth 差异如下

芯片

取值有意 义范围(单位GB/s)

默认值(单位GB/s)

TX510x

0 ~ 5.960464

5.960464

T X5368x_TX5339x_TX5335x

0 ~ 11.920929

11.920929

TX5215x_TX5239x200 _TX5239x220_TX5239x300

0 ~ 2.980232

2.980232

TX5119x_TX5112x200

0 ~ 1.490116

1.490116

TX5112x_TX5239x201

0 ~ 2.980232

2.980232

TX5336x_TX5256x

0 ~ 11.920929

11.920929

5.5.2.4. 输出文件

文件

内容

说明

layer_cycles_NPU_0.txt

性能输出文件

打印性能信息。

npu_profiling_yyyymmdd.log

log文件

log文件(yyyymmdd表示日志生成的日期,如20221011)。

性能输出文件内容(此处以芯片TX5368x_TX5339x_TX5335x为例):

pipeline

Profiling显示字段说明
- Total RDMA byte:从DMA读数据总字节数。
- Total WDMA byte: 向DMA写数据总字节数。
- Cost (ms) : 预估的运行时间,单位:ms。
- Total calculation amout: 总计算数。
- RCCN utilization:mac利用率。
- Storage bandwidths (GB/s):片上缓存最大带宽,单位:GB/s。
- Storage bandwidths use rate:片上缓存带宽利用率。真实缓存带宽为Storage bandwidths*Storage bandwidths use rate。
- NPU freq (MHZ) NPU频率,单位:MHZ。

性能分析器运行_d资源时,会在layer_cycles_NPU_0.txt中打印出每一层的运行时间,如下图所示:

pipeline

备注

注意:Profiling不计算通用算子层的时间和网络中RoundClip层的时间。

5.6. 支持算子列表

请参考 算子支持列表

5.7. 自定义算子

Knight工具链中支持的算子有三类:
  • 高效算子:运行在硬件单元上,执行效率高;

  • 通用算子:运行在CPU等通用计算硬件单元上,执行效率相比于高效算子低,用户模型中经常使用且硬件单元不支持,Knight工具链出厂时已支持;

  • 用户自定义算子:运行在CPU等通用计算硬件单元上,执行效率相比于高效算子低,用户自定义开发,除上述两类算子外用户模型中不支持的算子;

各芯片支持的高效算子、通用算子请参见相应芯片的 算子支持列表

备注

注意:Knight模拟器不支持用户自定义算子,Knight性能分析器仅统计高效算子资源。自定义算子不支持多batch。

5.7.1. 自定义算子流程

  1. 在量化后的prototxt文件添加自定义算子层。自定义算子方式参考 定义自定义算子

  2. 编译网络。参考 knight编译器

  3. C语言实现。参考 SDK使用指南

  4. PC模拟或板端部署。参考 SDK使用指南

5.7.2. 定义自定义算子

自定义算子需要修改量化后的prototxt文件。

备注

注意。具体其他字段如下(注意:字段名字不能修改,不能扩展;自定义算子的prototxt用Knight RNE编译器编译时需要加选项-gp 1)。

layer {
    name: "userfunc1"
    type: "UserFunc1"
    bottom: "data"
    top: "userfunc1"
ts_rce_layer{
    layer_type: 1152
    top_channel: 4
    top_width: 1
    top_height: 1
    rce_param: 1024
    rce_param: 2048
    }
fix_param {
    input_bit: "s8"
    output_bit: "s8"
    }
}

字段

说明

是否必选

name

层名称。在当前网络中不可以重复。

type

层类型。 不可以与算子列表中定义的高效算子层的层类型相同。

bottom

Bottom层名称, 在网络中必须可以找到对应的top 层名称。

top

Top 层名称, 不可以与其他层的top 层名称相同。

ts_rce_layer.layer_type

层类型。

0~1023:为高效算子层类型使用。

1024~1151:保留内部使用。

1152及以上:用户自定义的算子层使用。

基于SDK开发算例时,需要根据该值调用 TS_MPI_TRP_RNE_RegisterGpLayer 注册该类型所需要调用的算法函数。

例如:

TS_MPI_TRP_RNE_RegisterGpLayer (1152,

TS_MPI_TRP_RNE_GpLayerCustormOperator)

ts_rce_layer.top_channel

输出channel。 在当前网络中。该层输出channel。

如果不设置该值,则自动使用该层输入channel。

可选

ts_rce_layer.top_height

输出height。 在当前网络中。该层输出height。

如果不设置该值,则自动使用该层输入height。

可选

ts_rce_layer.top_width

输出width。 在当前网络中,该层输出width。

如果不设置该值,则自动使用该层输入width。

可选

ts_rce_layer.rce_param

rce_param是float类型的数组, 存放用户传入到自定义计算中的参数,如scale。

可选

fix_param.input_bit

输入数据类型。

支持标记包括:

s8 ---8bit有符号数

us8 ---8bit无符号数

s16 ---16bit有符号数

s32 ---32bit有符号数

s64 ---64bit有符号数

注: 如果上一层已经设置了output_bit, 该值可以不设置,输入符号位与上一层输出一致。

可选

fix_param.output_bit

输出数据类型。

支持标记包括:

s8 ---8bit有符号数

us8 ---8bit无符号数

s16 ---16bit有符号数

s32 ---32bit有符号数

注:不设置该值时表示输出float32浮点数。

可选

5.7.3. 自定义算子函数

该接口使用方式可参考 SDK使用指南 章节TS_MPI_TRP_RNE_GpLayerHandler介绍.

TS_VOID TS_MPI_TRP_RNE_GpLayerHandler(RNE_BLOBS_S *input, RNE_BLOBS_S *output,
RNE_BIN_DATA_S *extraData, TS_VOID *userData);

5.7.4. 注册自定义算子函数

层类型必须通过枚举的方式传递给注册函数,且最后一层必须为RNE_LAYER_TYPE_MAX_LAYER_TYPE。注册前须通过TS_MPI_TRP_RNE_InitGpLayerNum初始化通用算子层。TS_MPI_TRP_RNE_OpenDevice第二个参数需要传入TS_MPI_TRP_RNE_RegisterGpLayers。

此示例参考 open_source/gp_layers。用户如果需要传权重,可通过userData参数传入。

参考 ts_rne_gp_layer.h

// 定义枚举
typedef enum tsRNE_LAYER_TYPE {
RNE_LAYER_TYPE_START_LAYER = 1024,
RNE_LAYER_TYPE_CUSTOM_OPERATOR_LAYER = 1152,
RNE_LAYER_TYPE_MAX_LAYER_TYPE
} RNE_LAYER_TYPE;

参考ts_rne_gp_layer.c

// 注册软件层
TS_S32 TS_MPI_TRP_RNE_RegisterGpLayers(TS_VOID) {
    TS_S32 ret = TS_MPI_TRP_RNE_InitGpLayerNum(RNE_LAYER_TYPE_MAX_LAYER_TYPE, RNE_LAYER_TYPE_START_LAYER);
    ret  |=TS_MPI_TRP_RNE_RegisterGpLayer(RNE_LAYER_TYPE_CUSTOM_OPERATOR_LAYER,
    TS_MPI_TRP_RNE_GpLayerCustormOperator);
    return ret;
    }
// TS_MPI_TRP_RNE_RegisterGpLayers在TS_MPI_TRP_RNE_OpenDevice时调用
 TS_MPI_TRP_RNE_OpenDevice(NULL, TS_MPI_TRP_RNE_RegisterGpLayers);

5.7.5. 读取传入参数

读取ts_rce_layer.rce_param定义的参数:

void TS_MPI_TRP_RNE_GpLayerCustormOperator(RNE_BLOBS_S *input, RNE_BLOBS_S *output,
    RNE_BIN_DATA_S *extraData, void *userData)
{
    // userData test
    if (NULL != userData) {
    TS_MPI_TRP_RNE_Info("UserData get <== %s\n", (TS_CHAR *)userData);
    }
    // prototxt 里面rce_param的值,float类型
    typedef struct {
        TS_S32 num;
        TS_FLOAT param1;
        TS_FLOAT param2;
    } ParamsData;
    ParamsData *pd = (ParamsData *)extraData->u8pData;
    if (pd != NULL) {
        TS_MPI_TRP_RNE_Info("params num=%d\n", pd->num);
        TS_MPI_TRP_RNE_Info("params%d=%f\n", 0, pd->param1);
        TS_MPI_TRP_RNE_Info("params%d=%f\n", 1, pd->param2);
    }
}

5.7.6. 内部支持的通用算子层

  • TX510x芯片

通用算子层

通用算子层

通用算子层

通用算子层

Normalize

Permute

Softmax

Flatten

Reshape

Embedding

PriorBoxS

DetectOutput

SoftmaxV2

GEMM_V6_I8032

EltwiseDiv

RowGEMM

  • TX5368x_TX5339x_TX5335x芯片

通用算子层

通用算子层

通用算子层

通用算子层

Embedding

5.8. 编译器IR图优化说明

编译处理量化后的模型,根据实际芯片支持的情况,会对网络模型中的一些场景进行优化处理。

算子

融合拆分场景

说明

Conv

Conv+scalefix

两层融为一层,模拟debug调试,使用scale层的layer name。

Deconv

Deconv+scalefix

两层融为一层,模拟debug调试,使用scale层的layer name。

Depwiseconv

Depwiseconv+scalefix

两层融为一层,模拟debug调试,使用scale层的layer name。

Innerproduct

Innerproduct+scalefix

两层融为一层,模拟debug调试,使用scale层的layer name。

Input

Input+roudclipfix

浮点输入,roudclipfix层会被优化掉,不可调试。

Permute

Permute未做任何变换, 且后面还有其它算子

无实际变化的permute层,编译优化掉,不可调试。

多个permute级联, Permute+permute+…

连续多个permute, 编译优化为一个permute。模拟debug调试, 使用最后一个permute层的layer name。

(pad除外,优化后的layer name与pad层相同)

Reshape

Reshape未做任何变换。

无实际变化的reshape层,编译优化掉,不可调试。

多个reshape级联, reshape+reshape+…

连续多个reshape, 编译优化为一个reshape。

模拟debug调试,使用最后一个reshape层的layer name。

Pad

Pad层未做任何变换

无实际变化的pad层,编译优化掉,不可调试。

Pad+conv/pad + depwisecov/pad+pooling,

H和W方向做pad, pad方式为zero(补0),

且pad补充的维度小于 kernel_H和kernel_W。

Pad会和conv/depwiseconv/pooling 融合, 模拟debug调试,

使用conv/depwiseconv/pooling的layer name。

Softmax

复合算子。

编译拆分多个算子,模拟debug调试, 使用该层原来的layer name。

Layernorm

复合算子。

编译拆分多个算子,模拟debug调试, 使用该层原来的layer name。

Rnn/lstm/gru 等循环算子

复合算子。

编译拆分多个算子,模拟debug调试, 使用该层原来的layer name。

IR图优化示例如下:

pipeline

备注

对于融合的算子,因为被融合层指令将会在融合层一起处理,所以被融合层不可被调试; 调试中间层时,编译器应设置--opt-ddr参数为0,防止编译优化导致的结果不一致; 循环算子拆分后的最后一层为reshape,当循环算子后面接reshape/squeeze/unsqueeze算子时,循环算子最后一层reshape会被融合,此时不能对循环算子进行调试; 多输出算子如split因为编译器拆分为多个指令,不支持--debug。

5.9. FAQ

5.9.1. 模拟器仿真的三种format分别在什么时候使用?

【问题描述】

模拟器仿真的format有nchw、nhwc和nhwcstride,三种format分别在什么时候使用?仿真输出的result_x_p.txt和result_x_hwc_p.txt应该怎么对应? 【解决方法】

  1. 输入数据为(n,h,w,c)格式时可以不指定该参数,默认是nhwc。输入数据为(n,c,h,w)格式时需要指定参数:--format nchw。 当用户自己申请inputblobs mem需自行将输入数据转为nhwcstride格式, 并指定—format nhwcstride, SDK使用指南

  2. 为方便用户根据自己的需要选择,所以输出结果有两种排布nhwc和nchw,result_x_hwc_p.txt对应的是nhwc,result_x_p.txt对应的是nchw。

  3. 量化平台是onnx,则仿真使用nchw,对比结果使用result_x_p.txt。

5.9.2. 什么原因会导致编译时间长?

【问题描述】

算子什么情况会导致编译时间较长?

【解决方法】

  1. 算子的shape比较大的时候,时间会变长;

  2. 某些算子编译时间长,是由于算子的参数配置较大导致的编译处理时间长;

如pooling的kernel或stride参数大于16时,编译器为了适配底层指令,会将pooling算子拆分为许多的global pooling算子来处理,导致编译时间变长,同时编译出来的指令也会多很多。

  1. deconv算子在shape较大和stride参数较大时,编译处理时间会比较长。

如下图,deconv的输入shape为(1,174,12,12),stride参数为16,输出shape为(1,4,179,179),编译处理时适配底层指令,会做很多拆分处理,编译时间会比较长。

pipeline

编译的时候使用默认日志级别(error级别 --log-level 3)会减少日志打印,减少编译时间

5.9.3. 模拟器仿真什么时候会处理时间长?

【问题描述】

某些算子仿真非常慢,原因是什么?

【解决方法】

  1. 网络较大,编译出来的指令会较多,相应的模拟处理时间也会相对较长。

  2. 算子shape较大,为适配底层支持,会对算子做拆分处理,指令也会变多,同时模拟处理较多数据,会导致模拟耗时较长。

示例说明:

如deconv的单算子case,输入shape为(1,1,100,200), kernel为(11,12), pad为(6,6),stride为(2,2),输出shape为(1,200,197,398),对应的权重为(1,200,11,12),单纯计算乘加操作的循环次数为:32(输入channel对齐到32)*11*12*200*398*197, 加上其它适配底层需要的其它指令操作,总耗时较长。

5.9.4. 模拟器仿真结果如何查看?

【问题描述】

仿真结果输出文件格式是什么,如何查看?

【解决方法】

  1. 网络模型如果有一个输出,按照输出blobname命名result-blobname_p.txt、result-blobname_hwc_p.txt。如果网络有多个输出,模拟器则会输出每个输出blob对应的一组result文件,每一组以对应的blobname命名。 result文件中会打印输出shape及结果数据。各result文件描述如下:

result-blobname_p.txt 是输出张量按照chw顺序排列数据,十进制表示的数据。 result-blobname_hwc_p.txt 是输出张量按照hwc顺序排列的数据,十进制表示的数据。

2. 使用_d和_r版本仿真输出的结果是一样的。区别在于,使用_d版本仿真输出result文件中会打印layer name,使用_r版本不会打印layer name。如果网络有多个输出,可使用_d版本仿真,比对结果时可根据layer name来一一对应。

5.9.5. 模拟器输入的.bin资源如何生成?

用户训练NN模型时,train data一般需先经过一系列前处理,比如图片数据会经过crop,resize,totensor等操作,之后才输入给NN模型进行训练。 同样,在量化NN模型时,quant data也要经过与训练时相同的前处理,才能正确进行量化。 在测试NN模型时, test data也要经过与训练时相同的前处理,才能进行正确推理。 在使用Knight-RNE模拟器推理时,test data也要经过相同的前处理,且将前处理后的data保存为二进制.bin格式。比如: 假设前处理后的数据为numpy格式的"data" tensor,dataType为"float32",则可以使用data.tofile("input.bin")直接保存为float32类型的.bin数据。上述流程示意如下图:

pipeline

5.9.6. 如何正确设置编译器--output参数值?

【问题描述】

执行编译命令,使用--output参数时,指定IR模型中的blob_name,有时会出现blob_name不存在的错误提示,为何会产生错误?如何正确设置--output参数值?

【问题原因】

编译器处理IR模型时,会对一些算子进行合并操作,被合并的算子以及算子相关的输出blob会被删除,如果--output指定参数是被删除的blob_name,会出现找不到blob_name的报错。

【解决方法】

  1. 执行编译器命令时用--log-level 0指定debug级别日志。

  2. 从IR中获取想要作为输出算子(假设名为operator)以及其输出blob(假设名为out_blob),然后在编译器的log文件中查找out_blob,如果能找到,将out_blob作为--output的参数。

  3. 如果找不到out_blob,则在log中查找算子名operator,若能找到,则将该算子的output blob name设置为--output的参数。

  4. 如果out_blob和operator在编译器log文件里面都找不到,建议将--output参数设置为其他算子的输出blob_name。

5.9.7. 编译器--transformer-opt使用场景?

【问题描述】

什么场景下使用编译器--transformer-opt参数?

【解决方法】

针对batch_size为1的swin_t网络,网络中有大量连续的reshape与permute(如下图所示),此时将transformer-opt选项打开,并设置input-order为nhwc时,会提升网络的执行效率。

pipeline

5.9.8. 编译器设置-sln/-eln注意事项

【问题描述】

使用编译器-sln/-eln参数需要注意什么?

【解决方法】

设置-sln/-eln时,需要满足以下条件

  1. 起始节点和结束节点中间无分支

pipeline

2. 起始节点和中间节点中间分支可闭环

pipeline

起始节点和中间节点中间分支不可闭环情况:

  1. -sln与-eln指定算子节点子网范围内,存在多输出算子,部分输出在子网内,部分输出在子网外

pipeline
  1. -sln与-eln指定算子节点子网范围内,存在多输入算子,部分输入在子网内,部分输入在子网外

pipeline

5.9.9. 编译器 --input-order使用限制?

【问题描述】

编译器的--input-order参数在什么场景下使用?

【解决方法】

--input-order 默认是 nchw 参数,仅在 clip 模型或 swin_t 模型时可以使用 --input-order nhwc 选项。