You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Paddle/doc/design/mkl/mkl_packed.md

5.3 KiB

Intel® MKL Packed on PaddlePaddle: Design Doc

Contents

Overview

我们计划将 Intel® MKL 中引入的 GEMM Packed APIs[1] 集成到 PaddlePaddle 中充分发挥英特尔平台的优势有效提升PaddlePaddle在英特尔架构上的性能。 现阶段的优化主要针对 Recurrent Neural Network以下简称RNN相关层包括RecurrentLayer, GatedRecurrentLayerLstmLayer 以及 PaddlePaddle V1 API。

Key Points

Background

目前PaddlePaddle采用了 Intel® MKL库的cblas_?gemm函数,这个函数本身会在计算前将原数据转换为更适合英特尔平台的内部格式。

  1. 转换耗时
    这一数据格式的转换操作Packing在问题本身的计算量比较小的时候显得相对来说较为耗时。例如在DeepSpeech2 [2] 的Vanilla RNN部分中矩阵大小是batch_size * 2048
  2. 转换冗余
    由于在现有的某些情况下例如RNN多次调用 cblas_?gemm 会使用相同的原数据因此每次调用时对原数据的重复Packing便成为了冗余。

为了最大程度减少多次调用 cblas_?gemm 在Packing上的耗时Intel® MKL 引入了以下四个API:

通过使用这些API我们可以先完成对原数据的Packing操作再把已转换为Packed格式的数据传递给那些复用同一数据的gemm_compute函数从而避免了Packing冗余。

Solution

在RNN的情况下同一次前向、后向forward/backward过程中所有时间步time step共享同一个权重weight。当只做推断inference各次前向之间也都使用了相同的权重没有必要在每次前向中每个时间步的计算时对权重进行重复的Packing操作。

我们通过使用新引入的GEMM Packed APIs在层初始化的时候先完成对权重的Packing操作然后在前向后向时复用已经转换过的权重并在每次权重更新后对新的权重进行转换用于下次迭代。

  • 优化前对于序列长度sequence lengthT的网络模型model, N次迭代执行的转换次数为:
    • inference N * T
    • training 2 * N * T
  • 优化后,对于同样设置的网络模型,其转换次数减少至:
    • inference 1
    • training 2 * N

Actions

添加的相关文件和目录结构如下:

PaddlePaddle/Paddle
├── ...
└── paddle/
    ├── ...
    └── gserver/
        ├── ...
        ├── layers/
        │   ├── ...
        │   ├── MKLPackedRecurrentLayer.*
        |   ├── MKLPackedGatedRecurrentLayer.*
        |   ├── MKLPackedLstmLayer.*
        |   └── MKLPackedGemm.h
        └── tests/
            ├── ...
            └── test_MKLPacked.cpp

CMake

在对应的CMakeLists.txt中根据WITH_MKL是否打开来决定是否开启MKL Packed相关功能。

Layers

所有的MKLPacked*Layer都继承于PaddlePaddle的基类Layer, 并添加头文件 MKLPackedGemm.h该文件对相关GEMM Packed APIs做了封装。

Unit Tests

我们会添加test_MKLPacked.cpp用于MKL Packed优化后layer的测试。 对于每一个新加的RNN layer我们会对比如下2个方面

  1. 对比优化后layer自身sequence modernn_use_batch=false与batch mode(rnn_use_batch=true)的结果。
  2. 对比优化后layer与相对应的PaddlePaddle原有layer, 在batch mode下的结果。

Python API

计划在paddle/utils.Flags中添加use_mkl_packed的flag用于选择是否使用相关功能并且当编译时WITH_MKL=ON的情况下,默认设置为true

同时,在python/paddle/trainer/config_parser.py中对应的layer处添加use_mkl_packed这个选择方便用户在Python端选择是否启用这个功能。

具体实现方式比如:

use_mkl_packed = bool(int(g_command_config_args.get("use_mkl_packed", 0)))
if use_mkl_packed:
    self.layer_type = mkl_packed_*

所有相关的layer_type会以*mkl_packed_*开头,这些会在MKLPacked*Layer注册layer的时候保证以示区分。

Benchmarking

会添加相应的脚本用于测试和对比在使用MKL Packed recurrent layers 前后的网络性能。

References

  1. Introducing the new Packed APIs for GEMM
  2. DeepSpeech2 on PaddlePaddle