\u200E
即刻体验!在飞桨 x Graphcore IPU上运行训练与推理任务 | 洞见AI硬件
发布日期:2021-12-18T11:58:00.000+0000 浏览量:195次

飞桨框架(PaddlePaddle)现在可以支持Graphcore的IPU处理器了!在过去的几个月里, 通过飞桨研发团队与Graphcore China CE团队的不懈努力,已经初步完成了IPU与飞桨框架的适配工作。目前,用户可以在飞桨框架选择IPU硬件作为后端做深度学习的训练或推理任务。

本篇文章中, 我们会详细演示基于Graphcore IPU的安装、训练和推理流程 ;本期的第二篇文章『 飞桨 x Graphcore IPU适配方案深度解读与硬件介绍 』中,我们还会进一步介绍飞桨与Graphcore的适配初衷、适配的方案设计,以及关于Graphcore IPU的详细解读。

Graphcore在2016年成立于英国,其智能处理器(IPU)硬件和Poplar软件帮助创新者在机器智能方面实现了新突破。IPU是第一个专为机器智能设计的处理器,与通常用于人工智能的其他计算硬件相比,具有显著的性能优势。


飞桨框架通过与Graphcore的适配合作,可以让广大开发者以极低的学习成本即可使用Graphcore出众的软硬件产品,真正做到以灵活的硬件后端和完善的功能助力开发者快速实现AI想法,上线AI业务,帮助越来越多的行业完成AI赋能,实现产业智能化升级。

在本期的第二篇文章中,会有更多关于本次适配架构的说明,以及关于Graphcore IPU的详细解读。



如何开始 

(How to get started)





环境准备

Graphcore的Poplar SDK对硬件、操作系统以及软件环境均有一定的要求,具体参见: https://docs.graphcore.ai/projects/sdk-overview/en/latest/overview.html#requirements


通过源码编译安装

(1)下载源码

git clone -b paddle_bert_release https://github.com/graphcore/Paddle.git

(2)构建 Docker 镜像
docker build -t paddlepaddle/paddle:dev-ipu-2.3.0 \
-f tools/dockerfile/Dockerfile.ipu .

(3)创建并运行 Docker container
IPU依赖于ipu.conf配置文件进行分区,需要有可用的ipu.conf才能获取IPU设备。如果没有ipu.conf,可参考如下命令生成。
# 例:生成POD16(16个IPU)配置文件:
vipu create partition ipu --size 16
ipu.conf将会生成在以下路径:
ls ~/.ipuof.conf.d/

(4)启动Docker并编译环境
请将以下命令的${HOST_IPUOF_PATH}替换成host中ipu.conf的绝对路径。
docker run --ulimit memlock=-1:-1 --net=host --cap-add=IPC_LOCK \
--device=/dev/infiniband/ --ipc=host --name paddle-ipu-dev \
-v ${HOST_IPUOF_PATH}:/ipuof \
-e IPUOF_CONFIG_PATH=/ipuof/ipu.conf \
-it paddlepaddle/paddle:dev-ipu-2.3.0 bash
【注意:之后的操作均在container内执行。】

(5)(可选)验证IPU设备
通过以下命令可以查看当前全部IPU设备,以及正在使用的IPU设备ID
gc-monitor

出现以下图片说明正常获取IPU设备。如果没办法获取IPU设备,请检查是否提供正确的ipu.conf。

(6)编译飞桨框架
git clone -b paddle_bert_release https://github.com/graphcore/Paddle.git

cd Paddle 

cmake -DPYTHON_EXECUTABLE=/usr/bin/python \
-DWITH_PYTHON=ON -DWITH_IPU=ON -DPOPLAR_DIR=/opt/poplar \
-DPOPART_DIR=/opt/popart -G "Unix Makefiles" -H`pwd` -B`pwd`/build   

cmake --build \`pwd`/build --config Release --target paddle_python -j$(nproc) 

(7)安装wheel包
pip install -U build/python/dist/paddlepaddle-0.0.0-cp37-cp37m-linux_x86_64.whl 

(8)验证安装
python -c "import paddleprint(paddle.fluid.is_compiled_with_ipu())"

预期得到以下结果:
> True

目前Graphcore的IPU支持通过飞桨框架做大规模的模型训练任务,也支持通过Paddle Inference库执行高性能的推理任务。


BERT-Base 训练体验



Demo示例获取:
https://github.com/graphcore/portfolio-examples/tree/master/paddlepaddle/bert-base

Bert-Base Training 包含以下任务:
- phase1: sequence_length=128预训练
- phase2: sequence_length=384预训练
- SQuAD fine-tune
- SQuAD validation



数据准备

(1)预训练数据生成
git clone https://github.com/NVIDIA/DeepLearningExamples.git
cd DeepLearningExamples/TensorFlow/LanguageModeling/BERT
bash scripts/docker/build.sh

打开脚本并修改生成数据的配置
cd data/ 
vim create_datasets_from_start.sh

修改line 40 --max_seq_length 512 成--max_seq_length 384修改line 41 -- max_predictions_per_seq 80 成--max_predictions_per_se 56
cd ../ 
bash scripts/data_download.sh wiki_only

运行后将生成sequence_length=128 和 384的输入数据。

(2)准备SQuAD数据集
Stanford Question Answering Dataset (SQuAD) 是一个包含了特定范围内的维基百科内容,规模大且质量高的阅读理解数据集。SQuAD的答案是text span,即以文章原文中的某小一段文字来作为问题的答案,这种形式是首次在同类数据集中提出。

  • Fine-tune dataset:
curl --create-dirs -L https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v1.1.json -o data/squad/train-v1.1.json 

  • Validation dataset:
curl --create-dirs -L https://rajpurkar.github.io/SQuAD-explorer/dataset/dev-v1.1.json -o data/squad/dev-v1.1.json



PaddleNLP环境准备

本例除了依赖飞桨框架(已在上文中安装),还依赖PaddleNLP做模型构建和数据处理。请按照如下操作安装PaddleNLP:
(1)安装依赖:
pip3.7 install jieba h5py colorlog colorama seqeval multiprocess numpy==1.19.2 paddlefsl==1.0.0 six==1.13.0 wandb

pip3.7 install torch==1.7.0+cpu -f https://download.pytorch.org/whl/cpu/torch_stable.html

pip3.7 install torch-xla@https://storage.googleapis.com/tpu-pytorch/wheels/torch_xla-1.7-cp37-cp37m-linux_x86_64.whl

(2)安装PaddleNLP
pip3.7 install git+https://github.com/graphcore/PaddleNLP.git@paddle_bert_release



开始训练

修改run_stage.sh中的--input_dir为对应的输入数据路径:
  • Phase1: tfrecord(sequence_length=128)文件的存放路径;
  • Phase2: tfrecord(sequence_length=384)文件的存放路径;
  • Fine-tune: train-v1.1.json的存放路径;
  • Validation: dev-v1.1.json的存放路径。
run_stage.sh有4个参数:
  • device: ipu 或 cpu;
  • stage: phase1, phase2, SQuAD或validation;
  • input_pdparams: 导入的pdparams的路径+前缀;
  • output_pdparams: 导出的pdparams的路径+前缀。

【注意:程序中有使用wandb记录运行数据,运行时会弹出如下提示,需要选择对应的模式运行。如果没有wandb账号请输入3。】

Run Phase1:
Phase1不需要导入params,随机初始化权重
./run_stage.sh ipu phase1 _ pretrained_128_model

Run Phase2:
Phase2需要导入phase1训练好的params
./run_stage.sh ipu phase2 pretrained_128_model pretrained_384_model

Run SQuAD fine-tune:
fine-tune需要导入phase2训练好的params
./run_stage.sh ipu SQuAD pretrained_384_model finetune_model

Run validation:
./run_stage.sh ipu validation finetune_model _




BERT-Base

精度与性能 



目前Graphcore的IPU支持通过飞桨框架做大规模的模型训练任务,也支持通过Paddle Inference库执行高性能的推理任务。



BERT训练 (BERT trainning)

Pretrain Phase1 (sequence_length=128):


Pretrain Phase2 (sequence_length=384):

SQuAD:




Paddle Inference 推理 (FP16)




word2vec推理演示





生成Paddle Inference原生推理库

基于之前的飞桨编译命令增加-DON_INFER=ON,编译完成后将在build目录下生成 paddle_inference_install_dir目录。该目录为Paddle Inference库目录。
cmake -DPYTHON_EXECUTABLE=/usr/bin/python \
-DWITH_PYTHON=ON –DON_INFER=ON -DWITH_IPU=ON -DPOPLAR_DIR=/opt/poplar \
-DPOPART_DIR=/opt/popart -G "Unix Makefiles" -H`pwd` -B`pwd`/build   

cmake --build \`pwd`/build --config Release --target paddle_python -j$(nproc)

#目录如下:

可参考以下ipu_word2vec_sample.cc使用Paddle Inference库进行推理:
下载模型:
wget -q http://paddle-inference-dist.bj.bcebos.com/word2vec.Inference.model.tar.gz



编写Paddle Inference推理代码

#include <iostream>
#include <vector>
#include <numeric>
#include <string>

#include "paddle/fluid/inference/api/paddle_inference_api.h"
#include "gflags/gflags.h"
#include "glog/logging.h"

DEFINE_string(infer_model, """Directory of the inference model.");

using paddle_infer::Config;
using paddle_infer::Predictor;
using paddle_infer::CreatePredictor;

void inference(std::string model_path, bool use_ipu, std::vector<float> *out_data) {
//# 1. Create Predictor with a config.
Config config;
config.SetModel(FLAGS_infer_model);
if (use_ipu) {
// ipu_device_num, ipu_micro_batch_size
config.EnableIpu(14);
}
auto predictor = CreatePredictor(config);

//# 2. Prepare input/output tensor.
auto input_names = predictor->GetInputNames();
std::vector<int64_t> data{1234};
// For simplicity, we set all the slots with the same data.
for (auto input_name : input_names) {
auto input_tensor = predictor->GetInputHandle(input_name);
input_tensor->Reshape({41});
input_tensor->CopyFromCpu(data.data());
}

//# 3. Run
predictor->Run();

//# 4. Get output.
auto output_names = predictor->GetOutputNames();
auto output_tensor = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_tensor->shape();
int out_num = std::accumulate(output_shape.begin(), output_shape.end(), 1,
std::multiplies<int>());
out_data->resize(out_num);
output_tensor->CopyToCpu(out_data->data());
}

int main(int argc, char *argv[]) {
::GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
std::vector<float> ipu_result;
std::vector<float> cpu_result;
inference(FLAGS_infer_model, true, &ipu_result);
inference(FLAGS_infer_model, false, &cpu_result);
for (size_t i = 0; i < ipu_result.size(); i++) {
CHECK_NEAR(ipu_result[i], cpu_result[i], 1e-6);
}
LOG(INFO) << "Finished";
}




编译生成推理Demo程序

编译方法:

CMakeList.txt:
cmake_minimum_required(VERSION 3.0)
project(cpp_inference_demo CXX C)

include_directories("${PADDLE_LIB}/")
set(PADDLE_LIB_THIRD_PARTY_PATH "${PADDLE_LIB}/third_party/install/")
include_directories("${PADDLE_LIB_THIRD_PARTY_PATH}protobuf/include")
include_directories("${PADDLE_LIB_THIRD_PARTY_PATH}glog/include")
include_directories("${PADDLE_LIB_THIRD_PARTY_PATH}gflags/include")
include_directories("${PADDLE_LIB_THIRD_PARTY_PATH}xxhash/include")
include_directories("${PADDLE_LIB_THIRD_PARTY_PATH}cryptopp/include")
include_directories("${PADDLE_LIB_THIRD_PARTY_PATH}mkldnn/include")
include_directories("${PADDLE_LIB_THIRD_PARTY_PATH}mklml/include")

link_directories("${PADDLE_LIB_THIRD_PARTY_PATH}protobuf/lib")
link_directories("${PADDLE_LIB_THIRD_PARTY_PATH}glog/lib")
link_directories("${PADDLE_LIB_THIRD_PARTY_PATH}gflags/lib")
link_directories("${PADDLE_LIB_THIRD_PARTY_PATH}xxhash/lib")
link_directories("${PADDLE_LIB_THIRD_PARTY_PATH}cryptopp/lib")
link_directories("${PADDLE_LIB_THIRD_PARTY_PATH}ipu")
link_directories("/opt/poplar/lib")
link_directories("/opt/popart/lib")
link_directories("${PADDLE_LIB}/paddle/lib")

set(EXTERNAL_LIB "-lrt -ldl -lpthread")
set(DEPS ${DEPS}
${PADDLE_LIB_THIRD_PARTY_PATH}mkldnn/lib/libdnnl.so.2 
${PADDLE_LIB_THIRD_PARTY_PATH}mklml/lib/libiomp5.so 
paddle_inference paddle_ipu flags
glog gflags protobuf xxhash cryptopp
${EXTERNAL_LIB})
set(CMAKE_CXX_FLAGS "-std=c++11")

add_executable(${DEMO_NAME} ${DEMO_NAME}.cc)
target_link_libraries(${DEMO_NAME} ${DEPS})

编译脚本compile.sh:
【注意:请将${PADDLE_INFERENCE_INSTALL_DIR}替换为对应的Paddle Inference库路径】
#!/bin/bash
mkdir -p build
cd build
rm -rf *

DEMO_NAME=ipu_word2vec_sample
LIB_DIR=${PADDLE_INFERENCE_INSTALL_DIR}
cmake .. -DPADDLE_LIB=${LIB_DIR} -DDEMO_NAME=${DEMO_NAME}
make –j

编译:
./compile.sh

本测例将会分别完成IPU和CPU的推理,并对比两者结果
./ipu_word2vec_sample –-infer_model=word2vec.inference.model


其他Demo体验



MNIST demo

https://github.com/graphcore/Paddle_internal/issues/312

相关资料 (links)

https://www.paddlepaddle.org.cn/
https://github.com/PaddlePaddle/Paddle

关注公众号,获取更多技术内容~