文档
注册

格式转换优化

原理

  • 数据排布格式
    • 基础格式。
      在深度学习领域,多维数据通过多维数组存储,比如卷积神经网络的特征图(Feature Map)通常用四维数组保存,即4D,4D格式解释如下:
      • N:Batch数量,例如图像的数目。
      • H:Height,特征图高度,即垂直高度方向的像素个数。
      • W:Width,特征图宽度,即水平宽度方向的像素个数。
      • C:Channels,特征图通道,例如彩色RGB图像的Channels为3。

      由于数据只能线性存储,因此这四个维度有对应的顺序。不同深度学习框架会按照不同的顺序存储特征图数据,比如Caffe,排列顺序为[Batch, Channels, Height, Width],即NCHW。TensorFlow中,排列顺序为[Batch, Height, Width, Channels],即NHWC。

      图1所示,以一张格式为RGB的图片为例,NCHW中,C排列在外层,实际存储的是“RRRRRRGGGGGGBBBBBB”,即同一通道的所有像素值顺序存储在一起;而NHWC中C排列在最内层,实际存储的则是“RGBRGBRGBRGBRGBRGB”,即多个通道的同一位置的像素值顺序存储在一起。

      图1 NCHW和NHWC存储示例

      尽管存储的数据相同,但不同的存储顺序会导致数据的访问特性不一致,因此即便进行同样的运算,相应的计算性能也会不同。

    • NPU私有格式。

      NPU在NCHW基础格式上,定义了众多与硬件强相关的私有格式,用于加速硬件计算,NPU主要计算单元AI Core包括了三种基础计算资源:矩阵计算单元(Cube Unit)、向量计算单元(Vector Unit)和标量计算单元(Scalar Unit)。Cube的特殊计算方式导致了更加严格的对齐方式,因此通常在计算之前就按照Cube的对齐要求先把数据组织好;Vector相对没有那么严格,因此可以在计算逻辑中做一些对齐操作。Cube算子对于format的要求,典型有两种:卷积类算子要求的NC1HWC0Matmul类算子要求的FRACTAL_NZ,Vector算子对入参tensor无特殊对齐要求,一般使用ND格式

      NPU私有格式全量列举如下。

      typedef enum {
          ACL_FORMAT_UNDEFINED = -1,
          ACL_FORMAT_NCHW = 0,
          ACL_FORMAT_NHWC = 1,
          ACL_FORMAT_ND = 2,
          ACL_FORMAT_NC1HWC0 = 3,
          ACL_FORMAT_FRACTAL_Z = 4,
          ACL_FORMAT_NC1HWC0_C04 = 12,
          ACL_FORMAT_HWCN = 16,
          ACL_FORMAT_NDHWC = 27,
          ACL_FORMAT_FRACTAL_NZ = 29,
          ACL_FORMAT_NCDHW = 30,
          ACL_FORMAT_NDC1HWC0 = 32,
          ACL_FRACTAL_Z_3D = 33
      } aclFormat;
      • UNDEFINED:未知格式,默认值。
      • NCHW:NCHW格式。
      • NHWC:NHWC格式。
      • ND:表示支持任意格式,仅有Square、Tanh等这些单输入对自身处理的算子外,其它需要慎用。
      • NC1HWC0:5维数据格式。其中,C0与微架构强相关,该值等于cube单元的size,例如16;C1是将C维度按照C0切分:C1=C/C0, 若结果不整除,最后一份数据需要padding到C0。
      • FRACTAL_Z:卷积的权重的格式。
      • NC1HWC0_C04:5维数据格式。其中,C0固定为4,C1是将C维度按照C0切分:C1=C/C0, 若结果不整除,最后一份数据需要padding到C0。当前版本不支持。
      • HWCN:HWCN格式。
      • NDHWC:NDHWC格式。对于3维图像就需要使用带D(Depth)维度的格式。
      • FRACTAL_NZ:内部格式,用户目前无需使用。
      • NCDHW:NCDHW格式。对于3维图像就需要使用带D(Depth)维度的格式。
      • NDC1HWC0:6维数据格式。相比于NC1HWC0,仅多了D(Depth)维度。
      • FRACTAL_Z_3D:3D卷积权重格式,例如Conv3D/MaxPool3D/AvgPool3D这些算子都需要这种格式来表达。
  • 格式转换。

    NPU对于不同的计算单元(cube、vector)所使用的默认私有格式不一致,导致在数据在不同的计算单元下流通时需要进行格式转化,另外基础格式到NPU私有格式也需要进行格式转换,NPU侧执行格式转换的算子为TransData。举例如下(图中闪电图标所在位置即为添加转换算子的位置):

    图2 Conv2D
    图3 Matmul
  • 瓶颈产生原因。

    TransData算子通常耗时比Conv、MatMul等算子的耗时大。有一些TransData存在冗余的情况,举例如下:

    • 冗余:TransData(NCHW=>5HD) -- Conv2D -- TransData(5HD=>NCHW) -- TransData(NCHW =>5HD) -- Conv2D
    • 非冗余:TransData(NCHW=>5HD) -- Conv2D -- TransData(5HD=>NCHW/ND) -- ReduceMean

    典型场景如下:

    1. Cube-TransData-TransData-Cube。
      图4 典型场景1
    2. Cube-TransData-Vector*n-TransData-Cube。
      图5 典型场景2
    3. reshape场景,私有格式数据拷贝。
      图6 典型场景3

定位思路

查看Profiling数据文件op_summary.csv,查看算子输入数据格式,例如卷积类算子在cube计算单元上的数据格式要求为5HD,若不进行数据格式转换,则在算子计算过程中会通过插入transdata算子的形式,用户需根据profiling数据op_summary.csv文件查看TransData算子耗时是否过大进而判断是否需要提前进行格式转换。
  1. 参见Profiling数据采集及分析在训练脚本中使能profiling。
  2. 进入Profiling结果目录“path_to_profiling/result/PROF_timestamp/device_id/summary”。
  3. 打开op_summary_*_*.csv,按照“Input Formats”排序。
  4. 查看TransData算子耗时是否过长以分析是否进行格式转换。

优化策略

  • 算子的格式转换。

    使能npu_format_cast(format_type)。

    示例1:将ND格式转换为5HD格式数据。
    def forward(x):
        x = x.npu_format_cast(3)  # 3代表format_type的数字映射,完整映射关系请参见▪NPU私有格式
        ....# 前向计算过程

    示例2:

    hidden_states = self.embeddings(pixel_values) # 模型计算
    hidden_states = hidden_states.npu_format_cast(29) # 手动添加格式转换
    hidden_states = self.pre_layrnorm(hidden_states) # 模型计算
  • 对于需要进行格式转换的算子,需在训练脚本的main函数入口处添加如下代码,torch.npu.set_option更多使用方法请参见设置算子编译选项
    option = {}
    option['MM_BMM_ND_ENABLE'] = 'disable'
    torch.npu.set_option(option)
搜索结果
找到“0”个结果

当前产品无相关内容

未找到相关内容,请尝试其他搜索词