|
| 1 | +# Faster GPT 使用 |
| 2 | + |
| 3 | +在这里我们集成了 NVIDIA [Faster Transformer](https://github.com/NVIDIA/FasterTransformer/tree/v3.1) 用于预测加速。同时集成了 FasterGPT float32 以及 float16 预测。以下是使用 FasterGPT 的使用说明。 |
| 4 | + |
| 5 | +## 使用环境说明 |
| 6 | + |
| 7 | +* 本项目依赖于 PaddlePaddle 2.1.0 及以上版本或适当的 develop 版本 |
| 8 | +* CMake >= 3.10 |
| 9 | +* CUDA 10.1(需要 PaddlePaddle 框架一致) |
| 10 | +* gcc 版本需要与编译 PaddlePaddle 版本一致,比如使用 gcc8.2 |
| 11 | +* 推荐使用 Python3 |
| 12 | +* [Faster Transformer](https://github.com/NVIDIA/FasterTransformer/tree/v3.1#setup) 使用必要的环境 |
| 13 | + |
| 14 | +## 快速开始 |
| 15 | + |
| 16 | +我们实现了基于 GPU 的 FasterGPT 的自定义 op 的接入。接下来,我们将分别介绍基于 Python 动态图和预测库使用 FasterGPT 自定义 op 的方式,包括 op 的编译与使用。 |
| 17 | + |
| 18 | +## Python 动态图使用自定义 op |
| 19 | + |
| 20 | +### 编译自定义OP |
| 21 | + |
| 22 | +在 Python 动态图下使用自定义 OP 需要将实现的 C++、CUDA 代码编译成动态库,我们已经提供对应的 CMakeLists.txt ,可以参考使用如下的方式完成编译。同样的自定义 op 编译的说明也可以在自定义 op 对应的路径 `PaddleNLP/paddlenlp/ops/` 下面找到。 |
| 23 | + |
| 24 | +#### 克隆 PaddleNLP |
| 25 | + |
| 26 | +首先,因为需要基于当前环境重新编译,当前的 paddlenlp 的 python 包里面并不包含 FasterGPT 相关 lib,需要从源码自行编译,可以直接使用 Python 的 package 下的 paddlenlp,或是可从 github 克隆一个 PaddleNLP,并重新编译。 |
| 27 | + |
| 28 | +``` sh |
| 29 | +git clone https://github.com/PaddlePaddle/PaddleNLP.git |
| 30 | +``` |
| 31 | + |
| 32 | +其次,配置环境变量,让我们可以使用当前 clone 的 paddlenlp,并进入到自定义 OP 的路径,准备后续的编译操作: |
| 33 | + |
| 34 | +``` sh |
| 35 | +export PYTHONPATH=$PWD/PaddleNLP/:$PYTHONPATH |
| 36 | +cd PaddleNLP/paddlenlp/ops/ |
| 37 | +``` |
| 38 | + |
| 39 | +#### 编译 |
| 40 | + |
| 41 | +编译之前,请确保安装的 PaddlePaddle 的版本是大于 2.1.0 或是最新的 develop 分支的代码编译,并且正常可用。 |
| 42 | + |
| 43 | +编译自定义 OP 可以参照一下步骤: |
| 44 | + |
| 45 | +``` sh |
| 46 | +mkdir build |
| 47 | +cd build/ |
| 48 | +cmake .. -DSM=xx -DCMAKE_BUILD_TYPE=Release -DPY_CMD=python3.x -DWITH_GPT=ON |
| 49 | +make -j |
| 50 | +cd ../ |
| 51 | +``` |
| 52 | + |
| 53 | +其中, |
| 54 | +* `-DSM`: 是指的所用 GPU 的 compute capability。举例来说,可以将之指定为 70(V100) 或是 75(T4)。 |
| 55 | +* `-DPY_CMD`: 是指编译所使用的 python,若未指定 `-DPY_CMD` 将会默认使用系统命令 `python` 对应的 Python 版本。 |
| 56 | +* `-DWITH_GPT`: 是指是否编译带有 FasterGPT 自定义 op 的动态库。 |
| 57 | + |
| 58 | + |
| 59 | +最终,编译会在 `./build/lib/` 路径下,产出 `libdecoding_op.so`,即需要的 FasterGPT decoding 执行的库。 |
| 60 | + |
| 61 | +### 使用 GPT-2 decoding 高性能推理 |
| 62 | + |
| 63 | +编写 python 脚本的时候,调用 `FasterGPT` API 并传入 `libdecoding_op.so` 的位置即可实现将 FasterGPT 用于当前的预测。 |
| 64 | + |
| 65 | +``` python |
| 66 | +from paddlenlp.ops import FasterGPT |
| 67 | +from paddlenlp.transformers import GPTModel, GPTForPretraining |
| 68 | + |
| 69 | +MODEL_CLASSES = { |
| 70 | + "gpt2-medium-en": (GPTLMHeadModel, GPTTokenizer), |
| 71 | +} |
| 72 | + |
| 73 | +model_class, tokenizer_class = MODEL_CLASSES[args.model_name] |
| 74 | +tokenizer = tokenizer_class.from_pretrained(args.model_name) |
| 75 | +model = model_class.from_pretrained(args.model_name) |
| 76 | + |
| 77 | +# Define model |
| 78 | +gpt = FasterGPT( |
| 79 | + model=model, |
| 80 | + candidate_num=args.candidate_num, |
| 81 | + probability_threshold=args.probability_threshold, |
| 82 | + max_seq_len=args.max_seq_len, |
| 83 | + start_id=start_id, |
| 84 | + end_id=end_id, |
| 85 | + temperature=args.temperature, |
| 86 | + decoding_lib=args.decoding_lib, |
| 87 | + use_fp16_decoding=args.use_fp16_decoding) |
| 88 | +``` |
| 89 | + |
| 90 | +目前,GPT-2 的例子仅支持 `batch size` 为 `1` 或是 batch 内输入的样本的长度都是相同的情况。并且,仅支持 topk-sampling 和 topp-sampling,不支持 beam-search。 |
| 91 | + |
| 92 | +更详细的例子可以参考 `./infer.py`,我们提供了更详细用例。 |
| 93 | + |
| 94 | +#### 执行 GPT-2 decoding on PaddlePaddle |
| 95 | + |
| 96 | +使用 PaddlePaddle 仅执行 decoding 测试(float32): |
| 97 | + |
| 98 | +``` sh |
| 99 | +export CUDA_VISIBLE_DEVICES=0 |
| 100 | +python infer.py --model_name_or_path gpt2-medium-en --decoding_lib ./build/lib/libdecoding_op.so --batch_size 1 --topk 4 --topp 0.0 --max_out_len 32 --start_token "<|endoftext|>" --end_token "<|endoftext|>" --temperature 1.0 |
| 101 | +``` |
| 102 | + |
| 103 | +其中,各个选项的意义如下: |
| 104 | +* `--model_name_or_path`: 预训练模型的名称或是路径。 |
| 105 | +* `--decoding_lib`: 指向 `libdecoding_op.so` 的路径。需要包含 `libdecoding_op.so`。若不存在则将自动进行 jit 编译产出该 lib。 |
| 106 | +* `--batch_size`: 一个 batch 内,样本数目的大小。 |
| 107 | +* `--candidate_num`: 执行 topk-sampling 的时候的 `k` 的大小,默认是 4。 |
| 108 | +* `--probability_threshold`: 执行 topp-sampling 的时候的阈值的大小,默认是 0.0 表示不执行 topp-sampling。 |
| 109 | +* `--max_seq_len`: 最长的生成长度。 |
| 110 | +* `--start_token`: 字符串,表示任意生成的时候的开始 token。 |
| 111 | +* `--end_token`: 字符串,生成的结束 token。 |
| 112 | +* `--temperature`: temperature 的设定。 |
| 113 | +* `--use_fp16_decoding`: 是否使用 fp16 进行推理。 |
| 114 | + |
| 115 | + |
| 116 | +## C++ 预测库使用自定义 op |
| 117 | + |
| 118 | +### 编译自定义OP |
| 119 | + |
| 120 | +在 C++ 预测库使用自定义 OP 需要将实现的 C++、CUDA 代码**以及 C++ 预测的 demo**编译成一个可执行文件。因预测库支持方式与 Python 不同,这个过程将不会产生自定义 op 的动态库,将直接得到可执行文件。我们已经提供对应的 CMakeLists.txt ,可以参考使用如下的方式完成编译。并获取执行 demo。 |
| 121 | + |
| 122 | +#### 克隆 PaddleNLP |
| 123 | + |
| 124 | +首先,仍然是需要克隆一个 PaddleNLP: |
| 125 | + |
| 126 | +``` sh |
| 127 | +git clone https://github.com/PaddlePaddle/PaddleNLP.git |
| 128 | +``` |
| 129 | + |
| 130 | +其次,让我们可以使用当前 clone 的 paddlenlp,并进入到自定义 OP 的路径,准备后续的编译操作: |
| 131 | + |
| 132 | +``` sh |
| 133 | +cd PaddleNLP/paddlenlp/ops/ |
| 134 | +``` |
| 135 | + |
| 136 | +#### 编译 |
| 137 | + |
| 138 | +编译之前,请确保安装的 PaddlePaddle 预测库的版本是基于最新的 develop 分支的代码编译,并且正常可用。 |
| 139 | + |
| 140 | +编译自定义 OP 可以参照一下步骤: |
| 141 | + |
| 142 | +``` sh |
| 143 | +mkdir build |
| 144 | +cd build/ |
| 145 | +cmake .. -DSM=xx -DWITH_GPT=ON -DCMAKE_BUILD_TYPE=Release -DPADDLE_LIB=/path/to/paddle_inference_lib/ -DDEMO=./demo/gpt.cc -DWITH_STATIC_LIB=OFF -DON_INFER=ON -DWITH_MKL=ON |
| 146 | +make -j |
| 147 | +cd ../ |
| 148 | +``` |
| 149 | + |
| 150 | +注意: |
| 151 | +* `xx` 是指的所用 GPU 的 compute capability。举例来说,可以将之指定为 70(V100) 或是 75(T4)。 |
| 152 | +* `-DPADDLE_LIB` 需要指明使用的 PaddlePaddle 预测库的路径 `/path/to/paddle_inference_install_dir/`,并且在该路径下,预测库的组织结构满足: |
| 153 | + ```text |
| 154 | + . |
| 155 | + ├── CMakeCache.txt |
| 156 | + ├── paddle/ |
| 157 | + ├── include/ |
| 158 | + └── lib/ |
| 159 | + ├── third_party/ |
| 160 | + ├── cudaerror/ |
| 161 | + ├── install/ |
| 162 | + └── threadpool/ |
| 163 | + └── version.txt |
| 164 | + ``` |
| 165 | +* `-DDEMO` 说明预测库使用 demo 的位置。比如指定 -DDEMO=./demo/gpt.cc。最好使用绝对路径,若使用相对路径,需要是相对于 `PaddleNLP/paddlenlp/ops/faster_transformer/src/` 的相对路径。 |
| 166 | +* `-DWITH_GPT`,如果是编译 GPT 的预测库可执行文件,需要加上 `-DWITH_GPT=ON`。 |
| 167 | +* **当使用预测库的自定义 op 的时候,请务必开启 `-DON_INFER=ON` 选项,否则,不会得到预测库的可执行文件。** |
| 168 | + |
| 169 | +#### 执行 GPT decoding on PaddlePaddle |
| 170 | + |
| 171 | +如果需要使用 Paddle Inference 预测库针对 GPT 进行预测,首先,需要导出预测模型,可以通过 `./export_model.py` 脚本获取预测库用模型,执行方式如下所示: |
| 172 | + |
| 173 | +``` sh |
| 174 | +python ./export_model.py --model_name_or_path gpt2-medium-en --decoding_lib ./build/lib/libdecoding_op.so --topk 4 --topp 0.0 --max_out_len 32 --start_token "<|endoftext|>" --end_token "<|endoftext|>" --temperature 1.0 --inference_model_dir ./infer_model/ |
| 175 | +``` |
| 176 | + |
| 177 | +各个选项的意义与上文的 `infer.py` 的选项相同。额外新增一个 `--inference_model_dir` 选项用于指定保存的模型文件、词表等文件。若是使用的模型是 gpt2-medium-en,保存之后,`./infer_model/` 目录下组织的结构如下: |
| 178 | + |
| 179 | +``` text |
| 180 | +. |
| 181 | +├── gpt.pdiparams # 保存的参数文件 |
| 182 | +├── gpt.pdiparams.info # 保存的一些变量描述信息,预测不会用到 |
| 183 | +├── gpt.pdmodel # 保存的模型文件 |
| 184 | +├── merges.txt # bpe |
| 185 | +└── vocab.txt # 词表 |
| 186 | +``` |
| 187 | + |
| 188 | +同理,完成编译后,可以在 `PaddleNLP/paddlenlp/ops/build/bin/` 路径下将会看到 `gpt` 的一个可执行文件。通过设置对应的设置参数完成执行的过程。 |
| 189 | + |
| 190 | +``` sh |
| 191 | +cd bin/ |
| 192 | +./gpt -batch_size 1 -gpu_id 0 -model_dir path/to/model -vocab_dir path/to/vocab -start_token "<|endoftext|>" -end_token "<|endoftext|>" |
| 193 | +``` |
0 commit comments