fasttransformer.rst 12.4 KB
Newer Older
yuguo-Jack's avatar
yuguo-Jack committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
============
Transformer高性能加速
============


使用环境说明
------------

* 本项目依赖于 PaddlePaddle 2.1.0 及以上版本或适当的 develop 版本
* CMake >= 3.10
* CUDA 10.1 或 10.2(需要 PaddlePaddle 框架一致)
* gcc 版本需要与编译 PaddlePaddle 版本一致,比如使用 gcc8.2
* 推荐使用 Python3
* `FasterTransformer <https://github.com/NVIDIA/FasterTransformer/tree/v3.1#setup>`_ 使用必要的环境
* 环境依赖

  - attrdict
  - pyyaml

  .. code-block::

      pip install attrdict pyyaml


快速开始
------------

我们实现了基于 FasterTransformer 的自定义 op 的接入,打造了 FastGeneration 的能力用于加速文本生成模型在 GPU 上的预测性能。接下来,我们将分别介绍基于 Python 动态图和预测库使用 FastGeneration 自定义 op 的方式,包括 op 的编译与使用。

Python 动态图使用自定义 op
------------

JIT 自动编译
^^^^^^^^^^^^

目前当基于动态图使用 FastGeneration 预测加速自定义 op 时,PaddleNLP 提供了 Just In Time 的自动编译,在一些 API 上,用户无需关注编译流程,可以直接执行对应的 API,程序会自动编译需要的第三方库。

以 Transformer 为例,可以直接调用 `TransformerGenerator()` 这个 API,程序会自动编译。使用示例可以参考 `Transformer 预测加速使用示例-sample <https://github.com/PaddlePaddle/PaddleNLP/blob/develop/paddlenlp/ops/fast_transformer/sample/decoding_sample.py>`_,`Transformer 预测加速使用示例-机器翻译 <https://github.com/PaddlePaddle/PaddleNLP/tree/develop/examples/machine_translation/transformer/fast_transformer>`_。

编译自定义OP
^^^^^^^^^^^^

除了自动编译外,如果需要自行编译,我们已经提供对应的 CMakeLists.txt,可以参考使用如下的方式完成编译。

PaddleNLP 准备
""""""""""""

首先,如果需要从源码自行编译,可以直接使用 Python 的 package 下的 paddlenlp,或是可从 github 克隆一个 PaddleNLP,并重新编译:

以下以从 github 上 clone 一个新版 PaddleNLP 为例:

.. code-block::

    git clone https://github.com/PaddlePaddle/PaddleNLP.git

其次,配置环境变量,让我们可以使用当前 clone 的 paddlenlp,并进入到自定义 OP 的路径,准备后续的编译操作:

.. code-block::

    export PYTHONPATH=$PWD/PaddleNLP/:$PYTHONPATH
    cd PaddleNLP/paddlenlp/ops/

编译
""""""""""""

编译之前,请确保安装的 PaddlePaddle 的版本高于 2.1.0 或是基于最新的 develop 分支的代码编译,并且正常可用。

编译自定义 OP 可以参照一下步骤:

.. code-block::

    mkdir build
    cd build/
    cmake .. -DCMAKE_BUILD_TYPE=Release -DPY_CMD=python3.x
    make -j
    cd ../

可以使用的编译选项包括:

* `-DPY_CMD`: 指定当前装有 PaddlePaddle 版本的 python 环境,比如 `-DPY_CMD=python3.7`。若未指定 `-DPY_CMD` 将会默认使用系统命令 `python` 对应的 Python。
* `-DSM`: 是指的所用 GPU 的 compute capability,建议不使用该选项设置,未设置时将自动检测。如要设置,需根据 [compute capability](https://developer.nvidia.com/zh-cn/cuda-gpus#compute) 进行设置,如 V100 时设置 `-DSM=70` 或 T4 时设置 `-DSM=75`。
* `-DWITH_GPT`: 是否编译带有 GPT 相关的 lib。若使用 GPT-2 高性能推理,需要加上 `-DWITH_GPT=ON`。默认为 OFF。
* `-DWITH_UNIFIED`: 是否编译带有 Unified Transformer 或是 UNIMOText 相关的 lib。若使用,需要加上 `-DWITH_UNIFIED=ON`。默认为 ON。
* `-DWITH_BART`: 是否编译带有 BART 支持的相关 lib。若使用,需要加上 `-DWITH_BART=ON`。默认为 ON。
* `-DWITH_DECODER`: 是否编译带有 decoder 优化的 lib。默认为 ON。

最终,编译会在 `./build/lib/` 路径下,产出 `libdecoding_op.so`,即需要的 FastGeneration decoding 执行的库。

使用 Transformer decoding 高性能推理
^^^^^^^^^^^^

编写 python 脚本的时候,调用 `FasterTransformer API <https://paddlenlp.readthedocs.io/zh/latest/source/paddlenlp.ops.fast_transformer.transformer.fast_transformer.html#paddlenlp.ops.fast_transformer.transformer.fast_transformer.FasterTransformer>`_ 即可实现 Transformer 模型的高性能预测。

举例如下:

.. code-block::

    from paddlenlp.ops import FasterTransformer

    transformer = FasterTransformer(
        src_vocab_size=args.src_vocab_size,
        trg_vocab_size=args.trg_vocab_size,
        max_length=args.max_length + 1,
        n_layer=args.n_layer,
        n_head=args.n_head,
        d_model=args.d_model,
        d_inner_hid=args.d_inner_hid,
        dropout=args.dropout,
        weight_sharing=args.weight_sharing,
        bos_id=args.bos_idx,
        eos_id=args.eos_idx,
        decoding_strategy=args.decoding_strategy,
        beam_size=args.beam_size,
        topk=args.topk,
        topp=args.topp,
        max_out_len=args.max_out_len,
        decoding_lib=args.decoding_lib,
        use_fp16_decoding=args.use_fp16_decoding)

若当前环境下没有需要的自定义 op 的动态库,将会使用 JIT 自动编译需要的动态库。如果需要自行编译自定义 op 所需的动态库,可以如前文所述进行编译。编译好后,使用 `FasterTransformer(decoding_lib="/path/to/lib", ...)` 可以完成导入。

更详细的例子可以参考 `Transformer 预测加速使用示例-sample <https://github.com/PaddlePaddle/PaddleNLP/blob/develop/paddlenlp/ops/fast_transformer/sample/decoding_sample.py>`_,`Transformer 预测加速使用示例-机器翻译 <https://github.com/PaddlePaddle/PaddleNLP/tree/develop/examples/machine_translation/transformer/fast_transformer>`_,我们提供了更详细用例。

Transformer decoding 示例代码
""""""""""""

使用 PaddlePaddle 仅执行 decoding 测试(float32):

.. code-block::

    export CUDA_VISIBLE_DEVICES=0
    export FLAGS_fraction_of_gpu_memory_to_use=0.1
    # 执行 decoding_gemm 目的是基于当前环境、配置,提前确定一个性能最佳的矩阵乘算法,不是必要的步骤
    ./build/third-party/build/fastertransformer/bin/decoding_gemm 32 4 8 64 30000 32 512 0
    python ./fast_transformer/sample/decoding_sample.py --config ./fast_transformer/sample/config/decoding.sample.yaml --decoding_lib ./build/lib/libdecoding_op.so

使用 PaddlePaddle 仅执行 decoding 测试(float16):
执行 float16 的 decoding,需要在执行的时候,加上 `--use_fp16_decoding` 选项。

.. code-block::

    export CUDA_VISIBLE_DEVICES=0
    export FLAGS_fraction_of_gpu_memory_to_use=0.1
    # 执行 decoding_gemm 目的是基于当前环境、配置,提前确定一个性能最佳的矩阵乘算法,不是必要的步骤
    ./build/third-party/build/fastertransformer/bin/decoding_gemm 32 4 8 64 30000 32 512 1
    python ./fast_transformer/sample/decoding_sample.py --config ./fast_transformer/sample/config/decoding.sample.yaml --decoding_lib ./build/lib/libdecoding_op.so --use_fp16_decoding

其中,`decoding_gemm` 不同参数的意义可以参考 `FasterTransformer 文档 <https://github.com/NVIDIA/FasterTransformer/tree/v3.1#execute-the-decoderdecoding-demos>`_。这里提前执行 `decoding_gemm`,可以在当前路径下生成一个 config 文件,里面会包含针对当前 decoding 部分提供的配置下,性能最佳的矩阵乘的算法,并在执行的时候读入这个数据。

C++ 预测库使用自定义 op
------------

编译自定义OP
^^^^^^^^^^^^

在 C++ 预测库使用自定义 OP 需要将实现的 C++、CUDA 代码**以及 C++ 预测的 demo**编译成一个可执行文件。因预测库支持方式与 Python 不同,这个过程将不会产生自定义 op 的动态库,将直接得到可执行文件。我们已经提供对应的 CMakeLists.txt ,可以参考使用如下的方式完成编译。并获取执行 demo。

PaddleNLP 准备
""""""""""""

首先,因为需要基于当前环境重新编译,当前的 paddlenlp 的 python 包里面并不包含 FastGeneration 相关 lib,需要从源码自行编译,可以直接使用 Python 的 package 下的 paddlenlp,或是可从 github 克隆一个 PaddleNLP,并重新编译:

以下以从 github 上 clone 一个新版 PaddleNLP 为例:

.. code-block::

    git clone https://github.com/PaddlePaddle/PaddleNLP.git

其次,让我们可以使用当前 clone 的 paddlenlp,并进入到自定义 OP 的路径,准备后续的编译操作:

.. code-block::

    cd PaddleNLP/paddlenlp/ops/

编译
""""""""""""

编译之前,请确保安装的 PaddlePaddle 的版本高于 2.1.0 或是基于最新的 develop 分支的代码编译,并且正常可用。

编译自定义 OP 可以参照一下步骤:

.. code-block::

    mkdir build
    cd build/
    cmake .. -DCMAKE_BUILD_TYPE=Release -DPADDLE_LIB=/path/to/paddle_inference_lib/ -DDEMO=./demo/transformer_e2e.cc -DON_INFER=ON -DWITH_MKL=ON
    make -j
    cd ../

可以使用的编译选项包括:

* `-DPADDLE_LIB`: 需要指明使用的 PaddlePaddle 预测库的路径 `/path/to/paddle_inference_install_dir/`,需要使用的 PaddlePaddle 的 lib 可以选择自行编译或者直接从官网下载 `paddle_inference_linux_lib <https://paddleinference.paddlepaddle.org.cn/user_guides/download_lib.html#linux>`_。需要注意的是,在该路径下,预测库的组织结构满足:
  .. code-block::

      .
      ├── CMakeCache.txt
      ├── paddle/
        ├── include/
        └── lib/
      ├── third_party/
        ├── cudaerror/
        ├── install/
        └── threadpool/
      └── version.txt

* `-DDEMO`: 说明预测库使用 demo 的位置。比如指定 -DDEMO=./demo/transformer_e2e.cc 或是 -DDEMO=./demo/gpt.cc。最好使用绝对路径,若使用相对路径,需要是相对于 `PaddleNLP/paddlenlp/ops/fast_transformer/src/` 的相对路径。
* `-DSM`: 是指的所用 GPU 的 compute capability,建议不使用该选项设置,未设置时将自动检测。如要设置,需根据 [compute capability](https://developer.nvidia.com/zh-cn/cuda-gpus#compute) 进行设置,如 V100 时设置 `-DSM=70` 或 T4 时设置 `-DSM=75`。
* `-DWITH_GPT`: 是否编译带有 GPT 相关的 lib。若使用 GPT-2 高性能推理,需要加上 `-DWITH_GPT=ON`。默认为 OFF。
* `-DWITH_UNIFIED`: 是否编译带有 Unified Transformer 或是 UNIMOText 相关的 lib。若使用,需要加上 `-DWITH_UNIFIED=ON`。默认为 ON。
* `-DWITH_BART`: 是否编译带有 BART 支持的相关 lib。若使用,需要加上 `-DWITH_BART=ON`。默认为 ON。
* `-DWITH_DECODER`: 是否编译带有 decoder 优化的 lib。默认为 ON。
* `-DWITH_MKL`: 若当前是使用的 mkl 的 Paddle lib,那么需要打开 MKL 以引入 MKL 相关的依赖。
* `-DON_INFER`: 是否编译 paddle inference 预测库。
* **当使用预测库的自定义 op 的时候,请务必开启 `-DON_INFER=ON` 选项,否则,不会得到预测库的可执行文件。**

执行 Transformer decoding on PaddlePaddle
""""""""""""

编译完成后,在 `build/bin/` 路径下将会看到 `transformer_e2e` 的一个可执行文件。通过设置对应的设置参数完成执行的过程。

.. code-block::

    cd bin/
    ./transformer_e2e -batch_size <batch_size> -gpu_id <gpu_id> -model_dir <model_directory> -vocab_file <dict_file> -data_file <input_data>

举例说明:

.. code-block::

    cd bin/
    # 执行 decoding_gemm 目的是基于当前环境、配置,提前确定一个性能最佳的矩阵乘算法,不是必要的步骤
    ../third-party/build/fastertransformer/bin/decoding_gemm 8 5 8 64 38512 256 512 0
    ./transformer_e2e -batch_size 8 -gpu_id 0 -model_dir ./infer_model/ -vocab_file DATA_HOME/WMT14ende/WMT14.en-de/wmt14_ende_data_bpe/vocab_all.bpe.33708 -data_file DATA_HOME/WMT14ende/WMT14.en-de/wmt14_ende_data_bpe/newstest2014.tok.bpe.33708.en

其中:

* `decoding_gemm` 不同参数的意义可以参考 `FasterTransformer 文档 <https://github.com/NVIDIA/FasterTransformer/tree/v3.1#execute-the-decoderdecoding-demos>`_。这里提前执行 `decoding_gemm`,可以在当前路径下生成一个 config 文件,里面会包含针对当前 decoding 部分提供的配置下,性能最佳的矩阵乘的算法,并在执行的时候读入这个数据。
* `DATA_HOME` 则是 `paddlenlp.utils.env.DATA_HOME` 返回的路径。

预测所需要的模型文件,可以通过 `fast_transformer/README.md <https://github.com/PaddlePaddle/PaddleNLP/blob/develop/examples/machine_translation/transformer/fast_transformer/README.md>`_ 文档中所记述的方式导出。