X86 CPU 上部署BF16预测

1 概述

bfloat16 (Brain float Point)浮点格式是一种计算机内存中占用16位的计算机数字格式。该格式是32位IEEE 754单精度浮点格式(float32)的截断(16位)版本。它保留了32位浮点数的近似动态范围,保留了指数的8位,但只支持8位精度,在float32中,8位精度是24位。Bfloat16用于降低存储需求,提高机器学习算法的计算速度。关于bfloat16数据类型的更多细节可以在这里找到。目前,bfloat16预测支持被添加到PaddlePaddle中。bfloat16训练正在开发中。

2 图像分类模型和自然bfloat16在Intel(R)机型上的精度和性能

图像分类模型在 Intel(R) Xeon(R) Platinum 8371HC CPU @ 3.30GHz 上精度和性能

Full dataset BF16 fps improvement compared to MKLDNN FP32 TOP1 acc MKLDNN FP32 TOP1 acc MKLDNN BF16 TOP1 acc drop
resnet50 1.85x 0.7663 0.7656 0.00091
googlenet 1.61x 0.705 0.7049 0.00014
mobilenetV1 1.71x 0.7078 0.7071 0.00099
mobilenetV2 1.52x 0.719 0.7171 0.00264

Note: Clas models batch_size=1 nr_threads=1

自然语言处理模型在 Intel(R) Xeon(R) Platinum 8371HC CPU @ 3.30GHz 上精度和性能

GRU Accuracy FP32 BF16 diff
Precision 0.89211 0.89225 -0.00014
Recall 0.89442 0.89457 -0.00015
F1 score 0.89326 0.89341 -0.00015
GRU Performance (QPS) Naive FP32 FP32 BF16 (BF16/FP32)
thread = 1 2794.97 2700.45 4210.27 1.56x
thread = 4 3076.66 4756.45 6186.94 1.30x

Note: Gru model batch size = 50 iterations = 160

3 Paddle Bfloat16 Inference 复现

3.1 安装Paddle

参考Paddle官网,安装Paddle最新CPU或者GPU版本。

3.2 检查机器

  • 可以通过在命令行输入lscpu查看本机支持指令。

  • 在Intel支持avx512_bf16指令的机型上,(目前Cooper Lake机型支持avx512_bf16,如Intel(R) Xeon(R) Platinum 8371HC CPU, Intel(R) d on(R) Gold 6348H CPU),bfloat16性能会获得如上表的性能提升。Cooper Lake机型列表

  • 在Intel支持avx512bwavx512vlavx512dq指令但是不支持avx512_bf16的机型上,如:SkyLake, CasCade Lake等,可以顺利运行不报错,但是性能无法达到上表的性能。

  • 为了防止在非配套机器上测试bfloat16功能,应进行适当检查:

Python
import paddle
paddle.fluid.core.supports_bfloat16() // 如果为true, bf16可以顺利运行不报错,性能未知。
paddle.fluid.core.supports_bfloat16_fast_performance() // 如果为true, bf16可以顺利运行,且可获得上表所示的性能。

c++
#include "paddle/fluid/platform/cpu_info.h"
platform::MayIUse(platform::cpu_isa_t::avx512_core) // 如果为true, bf16可以顺利运行不报错,性能未知。
platform::MayIUse(platform::cpu_isa_t::avx512_bf16) // 如果为true, bf16可以顺利运行,且可获得上表所示的性能。

3.3 预测部署

C++ API举例如下:

paddle_infer::Config config;
if (FLAGS_model_dir == "") {
config.SetModel(FLAGS_model_file, FLAGS_params_file); // Load combined model
} else {
config.SetModel(FLAGS_model_dir); // Load no-combined model
}
config.EnableMKLDNN();
config.SwitchIrOptim(false);
config.SetCpuMathLibraryNumThreads(FLAGS_threads);
config.EnableMemoryOptim();/
// 将所可转为BF16的op转为BF16
config.EnableMkldnnBfloat16();
// 如果您想自己决定要替换哪些操作符,可以使用SetBfloat16Op选项
//config.SetBfloat16Op({“conv2d”、“pool2d”})

auto predictor = paddle_infer::CreatePredictor(config);

Python API举例如下:

if args.model_dir == "":
    config = Config(args.model_file, args.params_file)
else:
    config = Config(args.model_dir)
config.enable_mkldnn()
config.set_cpu_math_library_num_threads(args.threads)
config.switch_ir_optim(False)
config.enable_memory_optim()
config.enable_mkldnn_bfloat16 ()
# 如果您想自己决定要替换哪些操作符,可以使用set_bfloat16_op选项
# config.set_bfloat16_op({"conv2d", "pool2d"})
predictor = create_predictor(config)