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/mkldnn
tensor-tang 6405438bcf
change some names and refine
8 years ago
..
image refine and add overview 8 years ago
README.MD change some names and refine 8 years ago

README.MD

Intel® MKL-DNN on PaddlePaddle: Design Doc

我们计划将Intel深度神经网络数学库(MKL-DNN[1])集成到PaddlePaddle充分展现英特尔平台的优势有效提升PaddlePaddle在英特尔架构上的性能。

我们短期内的基本目标是:

  • 完成常用layer的MKL-DNN实现。
  • 完成常见深度神经网络VGGGoogLeNet 和 ResNet的MKL-DNN实现。

Contents

Overview

我们会把MKL-DNN作为第三方库集成进PaddlePaddle整体框架图


Figure 1. PaddlePaddle on IA.

Actions

我们把集成方案大致分为了如下几个方面。

CMake

我们会在CMakeLists.txt中会添加WITH_MKLDNN的选项,当设置这个值为ON的时候会启用编译MKL-DNN功能。同时会自动开启OpenMP用于提高MKL-DNN的性能。

同时,我们会引入WITH_MKLML选项用于选择是否使用MKL-DNN自带的MKLML安装包。这个安装包可以独立于MKL-DNN使用但是建议在开启MKL-DNN的同时也打开MKLML的开关这样才能发挥最好的性能。

所以,我们会在cmake/external目录新建mkldnn.cmakemklml.cmake文件它们会在编译PaddlePaddle的时候下载对应的软件包并放到PaddlePaddle的third party目录中。

备注:当WITH_MKLML=ON的时候会优先使用这个包作为PaddlePaddle的CBLAS和LAPACK库所以会稍微改动cmake/cblas.cmake中的逻辑。

Layers

所有MKL-DNN相关的C++ layers都会按照PaddlePaddle的目录结构存放在 paddle/gserver/layers中,并且文件名都会一以Mkldnn开头。

所有MKL-DNN的layers都会继承于一个叫做MkldnnLayer的父类该父类继承于PaddlePaddle的基类Layer

Activations

由于在PaddlePaddle中激活函数是独立于layer概念的所以会在paddle/gserver/activations目录下添加一个MkldnnActivation.h文件定义一些用于MKL-DNN的接口实现方法还是会在ActivationFunction.cpp文件。

Unit Tests

会在paddle/gserver/test目录下添加test_Mkldnn.cppMkldnnTester.*用于MKL-DNN的测试。

Activation的测试计划在PaddlePaddle原有的测试文件上直接添加新的测试type。

Protobuf Messages

根据具体layer的需求可能会在proto/ModelConfig.proto里面添加必要的选项。

Python API

目前只考虑v1 API

计划在python/paddle/trainer/config_parser.py里面添加use_mkldnn这个选择方便用户选择使用MKL-DNN的layers。

具体实现方式比如:

use_mkldnn = bool(int(g_command_config_args.get("use_mkldnn", 0)))
if use_mkldnn
    self.layer_type = mkldnn_*

所有MKL-DNN的layer type会以*mkldnn_*开头,以示区分。

并且可能在python/paddle/trainer_config_helper目录下的activations.py layers.py里面添加必要的MKL-DNN的接口。

Demos

会在v1_api_demo目录下添加一个mkldnn的文件夹里面放入一些用于MKL-DNN测试的demo脚本。

Benchmarking

会考虑添加部分逻辑在benchmark/paddle/image/run.sh添加使用MKL-DNN的测试。

Others

  1. 如果在使用MKL-DNN的情况下会把CPU的Buffer对齐为64。
  2. 深入PaddlePaddle寻找有没有其他可以优化的可能进一步优化。比如可能会用OpenMP改进SGD的更新性能。

Design Concerns

为了更好的符合PaddlePaddle的代码风格[2]同时又尽可能少的牺牲MKL-DNN的性能[3]。

我们总结出一些特别需要注意的点:

  1. 使用deviceId_。为了尽可能少的在父类Layer中添加变量或者函数我们决定使用已有的deviceId_变量来区分layer的属性定义-2MkldnnLayer特有的设备ID。
  2. 重写父类Layer的init函数,修改deviceId_-2代表这个layer是用于跑在MKL-DNN的环境下。
  3. 创建MkldnnMatrix用于管理MKL-DNN会用到的相关memory函数、接口以及会用的到格式信息。
  4. 创建MkldnnBase定义一些除了layer和memory相关的类和函数。包括MKL-DNN会用到MkldnnStreamCpuEngine,和未来可能还会用到FPGAEngine等。
  5. Argument里添加两个MkldnnMatrixPtr,取名为mkldnnValuemkldnnGrad,用于存放MkldnnLayer会用到的memory buffer。 并且添加函数cvt(会修改为一个更加合适的函数名),用于处理"CPU device"和"MKL-DNN device"之间memory的相互转化。
  6. 在父类Layer中的getOutput函数中添加一段逻辑,用于判断deviceId并针对device在MKL-DNN和CPU之间不统一的情况做一个前期转换。 也就是调用Argument的cvt函数把output统一到需要的device上。
  7. 在原来的FLAGS中添加一个use_mkldnn的flag用于选择是否使用MKL-DNN的相关功能。

References

  1. Intel Math Kernel Library for Deep Neural Networks (Intel MKL-DNN)
  2. 原来的方案会引入nextLayer的信息。但是在PaddlePaddle中无论是重构前的layer还是重构后的op都不会想要知道next layer/op的信息。
  3. MKL-DNN的高性能格式与PaddlePaddle原有的NCHW不同(PaddlePaddle中的CUDNN部分使用的也是NCHW,所以不存在这个问题)所以需要引入一个转换方法并且只需要在必要的时候转换这种格式才能更好的发挥MKL-DNN的性能。