Adlik 1.0 版本,加入了与燧原科技合作的成果,增加了对燧原 i20 芯片的支持,该芯片是燧原科技发布的基于邃思 2.5 芯片打造的面向数据中心的第二代人工智能推理加速卡,具有高性能高能效、模型覆盖面广、易部署易运维等特点,可广泛应用于计算机视觉、语音识别与合成、自然语言处理、搜索与推荐等推理场景。该芯片使用推理引擎TopsInference为深度学习应用提供低延迟、高吞吐率的推理部署。
项目开发前,对燧原 i20 芯片进行了相关调研,调研结果如下:
芯片采用 16GB 高带宽 HBM2E 存储,存储带宽高达 819GB/s。
芯片采用 12nm 工艺、采用自研架构 GCU(General Compute Unit)。
芯片主要应用范围是 AI 推算,支持图像分类、目标检测、自然语言处理等领域。
芯片支持 fp32 、 fp16 ,以及混合精度,暂不支持 int8。
芯片支持 ONNX 模型,但不是所有 ONNX 模型都支持。
芯片对静态模型支持度高,暂不支持动态模型。
在 Adlik 中增加 i20 芯片的支持,需要增加以下内容:编译器部分增加原始模型格式到 i20 芯片支持的模型格式的转换,即加入一条从 ONNX 模型格式到燧原支持的 EXEC 模型格式的路径,运行时部分增加燧原运行时,提供使用 i20 芯片进行推理的支持。
由于 model_compiler 模型转换路径较多,可以分类为源模型格式直接到目的模型格式的方式,以及源模型格式到目的模型格式有中间状态的方式。编译器加入燧原模型,增加了一条ONNX 模型直接到燧原模型的路径。
增加后,源模式直接到目的模式的路径状态图如下:
adlik_serving 的功能是根据不同模型部署相应的服务,支持部署在 CPU、GPU 上。推理时,通过调度器,调度相应的推理引擎,由 http grpc 进行数据传输,将客户端数据传输到 Adlik 服务端进行推理。
Adlik 运行时支持情况:
推理引擎 | TensorFlow | OpenVino | TensorRT | TFLite | ML | PaddlePaddle | TFtrt | TVM | Libtorch | TopsInference |
---|---|---|---|---|---|---|---|---|---|---|
硬件 | CPU/GPU | CPU/GPU | GPU | CPU | CPU | CPU | GPU | CPU | CPU/GPU | GCU |
Adlik runtime 增加燧原运行时后,可以将不同的深度学习模型通过 Adlik 服务平台部署到燧原 i20 芯片上,实现了在硬件 GCU 上使用 TopsInference 进行推理。可支持单 batch 、多 batch 、多模型、多实例的推理。
编译器部分首先使用TopsInference接口创建ONNX解析器,使用解析器读取ONNX模型,得到模型结构,接着使用TopsInference接口创建优化器,使用优化器构建燧原模型。代码如下:
with TopsInference.device(0, 0):
onnx_parser = TopsInference.create_parser(TopsInference.ONNX_MODEL)
network = onnx_parser.read(source.model_path)
optimizer = TopsInference.create_optimizer()
engine = optimizer.build(network)
#这是onnx模型到燧原模型转换过程
代码详见:Adlik/model_compiler/src/model_compiler/compilers/onnx_model_file_to_enflame_model.py
单元测试:
pytest tests/model_compiler/compilers/test_onnx_model_file_to_enflame_model.py
pytest tests/model_compiler/models/targets/test_enflame_model.py
转换测试:
python3.8 compile_model.py
生成的文件夹,目录结构如下:
model_repos
├── resnet50
│ ├── 1
│ │ └── model.exec
│ └── config.pbtxt
└── resnet50_1.zip
Adlik 提供了全面的 SDK(Software Development Kit),以 SDK 方式提供给开发者可扩展实现自定义推理运行时的能力,以便更快的开发新运行时。例如在 adlik_serving 中提供运行时的管理和调度功能,开发者只需要关注计算引擎的具体实现即可。在燧原运行时中,计算引擎的实现类为 BatchProcessor 类。这个类可以直接调用 TopsInference 计算引擎的执行 API 实现推理。在这个过程中,提炼了 Buffer 类概念,对此类进行实例化产生输入输出缓冲区对象,用于存储输入输出的数据。
执行推理的具体实现:
std::vector inputs_buffer_bound;
for (auto& input : inputs) {
inputs_buffer_bound.push_back(input.buffer_on_device);
}
std::vector outputs_buffer_bound;
for (auto& output : outputs) {
outputs_buffer_bound.push_back(output.buffer_on_device);
}
bool rtn = engine->run_with_batch(config.max_batch_size(),
inputs_buffer_bound.data(),
outputs_buffer_bound.data(),
TopsInference::BufferType::TIF_ENGINE_RSC_IN_DEVICE_OUT_DEVICE,
stream);
if (!rtn) {
return tensorflow::errors::Internal("Faild run in enflame reference.");
}
status = splitOutputs(payloads);
TopsInference::synchronize_stream(stream);
//异步推理
代码详见:Adlik/adlik_serving/runtime/topsinference/model/topsinference_model.cc
测试过程:
(1)服务器首先部署燧原模型
adlik_serving --model_base_path=/workspace/Adlik/examples/topsinference_model/model_repos --grpc_port=8500 --http_port=8501
(2)若成功则进入loop状态
I adlik_serving/server/http/internal/server_interface.cc:167] Entering the event loop ...
(3)等待客户端提出请求,服务器接受处理请求并返回响应。
python3.8 resnet50_client_acc.py -t data/val_map.txt data/figures/tench.JPEG data/imagenet_class.txt
(4)结果如下:
Image: 'data/figures/tench.JPEG', result: [{'idx': 0, 'score': 14.775530815124512, 'label': '0 tench'}]
测试选取图像分类领域 resnet50 模型,目标检测领域 yolov5s 模型,以及自然语言处理领域的 bert 模型。模型及大小,来源如下,数据类型是均为 fp32。
ONNX模型 | 大小 | 数据集 | 模型来源 |
---|---|---|---|
resnet50 | 97.4M | imagenet | 链接1 |
剪枝resnet50 | 39.8M | imagenet | 链接2 |
yolov5s | 27.6M | coco2017 | 链接3 |
bert | 415.2M | dev-v1.1.json | 燧原提供 |
其中模型均可在Adlik仓库中获取,链接如下。
链接1:https://github.com/Adlik/Adlik/blob/master/benchmark/tests/test_model/resnet50_pytorch/resnet50_pytorch.py
链接2:https://github.com/Adlik/model_zoo/tree/main/model_optimizer
链接3:https://github.com/Adlik/model_zoo
经测试,Adlik 模型编译器可以完成模型转换,Adlik 燧原运行时可以完成模型部署、模型推理,并返回相应的推理结果。
在测试时延的场景下,取 batch_size=1。resnet50、剪枝resnet50、yolov5s、bert 等迭代次数为 1200 次,warmup 10 次,推理时延取所有 batch 推理时延的平均数。
ONNX模型 | Adlik推理时延(ms) |
---|---|
resnet50 | 4.86533 |
剪枝resnet50 | 3.3735 |
yolov5s | 10.3394 |
bert | 1154.33 |
在测量吞吐量的场景下,resnet50、剪枝 resnet50 和 bert batch_size 取 120,yolov5s 取 30 。
ONNX模型 | Adlik推理时延(ms) | 单实例-fps |
---|---|---|
resnet50 | 101.704 | 1179.894596 |
剪枝resnet50 | 68.6933 | 1746.895258 |
yolov5s | 134.559 | 222.950527 |
bert | 1233.91 | 97.251825 |
在同等条件下,燧原测试工具 topsexec 的吞吐量结果如下:
ONNX模型 | batch_size | 吞吐量 |
---|---|---|
resnet50 | 120 | 1162.58 |
剪枝resnet50 | 120 | 1659.88 |
yolov5s | 30 | 514.543 |
bert | 120 | 86 |
Adlik 对接燧原芯片的工作还在继续。目前有一个遗留问题,能否将内存中的 onnx.onnx_ml_pb2.ModelProto 数据转换为燧原模型的格式,如果可以,编译器就可以提供TensorFlow、Keras 等到燧原格式的转换。此方法由于燧原构建模型的 API 暂不支持动态 shape 因此无法提供使用。后续将会继续跟踪燧原相关新特性消息,提高编译器对这种转换形式的支持程度。