CPU 不适合模型推理和训练?那已经是老刻板印象了,英特尔® 至强® 可扩展处理器搭配 AVX-512 指令集,单核一次能同时进行 128 次 BF16 浮点运算,这对于一般的深度学习模型不论在训练还是推理已经是足够的了。
说到模型训练,很多算法工程师首先想到的就是各种深度学习框架,以及 CUDA、cuDNN、NCCL 等 GPU 训练环境,似乎我们很少优先考虑在 CPU 上直接训练模型。这可能是在潜意识里,我们将 CPU 视为不适合并行计算的设备,思考着,也许 CPU 训练模型不仅速度慢,同时内存等资源占用也不少。
但实际上,经过这么多年的发展,像英特尔® 至强® 可扩展处理器这种 AI build-in 的 CPU 在支持模型训练上已经有了极大的提升,基本上每一代 CPU 都比上一代提升个 1.5 倍左右,运用或不运用 CPU 模型训练加速库的差别,能达到 8 倍。因此整体上 CPU 的训练速度已经非常可观了,再加上相比显存更易扩展的 CPU 内存,很多推荐算法、排序模型、图片 / 影像识别等应用,已经在大规模使用 CPU 作为基础计算设备。
本文将主要介绍近几年 英特尔® 至强® 可扩展处理器 在模型训练上的努力与进展,包括 AVX-512 指令集、DL Boost 低精度训练模型等等;用这一套配置实操训练模型也很简单,这里我们将简单看看 英特尔® 至强® 可扩展处理器 上的模型该怎么训练最为高效;最后,相比高昂的 GPU,CPU 其实是一种性价比很高的训练硬件,也非常适合对结果准确度要求高兼顾成本考量的制造业、图像处理与分析等行业客户的深度学习模型。
CPU 上的深度模型训练
在 CPU 上训练模型,看起来很简单,但实际上要做到高效训练还是很复杂的。作为一种通用计算设备,英特尔® 至强® 可扩展处理器要为各种设备或者软件提供计算支持。如果想要更好地支持深度学习模型,那么从底层指令集的设计,到矩阵运算加速库,再到神经网络加速库,都需要额外的设计与优化。
底层优化:AVX-512 指令集
了解过计算机组成原理的同学们都知道,CPU 指令集或者说指令系统,是实现计算机能力的核心部分。在 CPU 的眼里,它只会一条条执行指令,例如加法指令,从内存读取某个值的指令等等。如果放到神经网络计算流,那么优化或者增加一些基础指令,例如支持 FP16 的矩阵运算、支持单指令多条运算数据等等,就能大大提高 CPU 运行神经网络计算流的能力。
英特尔 AVX-512 指令集的目的就旨在提升单条指令的计算数量,从而提升 CPU 的矩阵运算效率。简单而言,一条指令一般分为操作码部分与地址码(内存地址)部分,早期通用处理器一般是基于 SISD(单指令单数据流)指令,即每个核心中,一个指令单次操作一条数据。因此当我们计算一个向量内积,一个值需要和好几个值进行乘加运算,因此就需要好几条类似的指令,它们具有相同的操作码,只是不同的地址码。
SIMD(单指令多数据流)就为了解决这个问题,它能让一个指令可以单次操作多条数据。此外,英特尔还为特意为矩阵运算场景加入了 FMA (Fused multiply-add)指令集,让处理器一次能同时完成乘法和加法两种基本操作。
同样一个向量内积,单指令单数据流需要拆分成多条指令,单指令多数据流只需要一条指令。
现在,英特尔至强处理器所采用的 AVX-512 指令集(Advanced Vector Extensions,AVX),在 SIMD 的基本想法上,已经经过 20 多年的优化与发展,其寄存器已由最初的 64 位升级到了 512 位,且具备两个 512 位的 FMA (融合乘加运算指令)单元,这意味着应用程序可同时执行 32 次双精度、64 次单精度浮点运算,或操作八个 64 位和十六个 32 位整数。
加速训练:DL Boost
前面我们介绍了非常基础的 AVX-512 指令集,假设数值精度是模型训练常用的 FP32,单个 512 位寄存器能存储 16 个浮点数,如果配合两个 FMA 单元可以同时执行 16*2*2=64 次浮点运算。那么我们会想到,要是训练和推理模型,用不上 FP32 精度,只需要 BF16 或者 INT8,岂不是并行计算的数量要翻一到两倍?再加上内存可以移动更多的数据量,总体低精度计算要快上好几倍?
英特尔 DL Boost 就是这样思考的,其技术的精髓就是把对低精度数据格式的操作指令融入到了 AVX-512 指令集中,即 AVX-512_VNNI (矢量神经网络指令) 和 AVX-512_BF16(bfloat16),分别提供了对 INT8(主要用于量化推理)和 BF16(兼顾推理和训练)的支持。
不同指令集中,单条 SIMD 指令能包含的数据类型及数据量。
2020 年问世的第三代英特尔® 至强® 可扩展处理器家族已集成了英特尔深度学习加速技术这两种 AI 加速指令集,并被广泛运用于商业深度学习的训练和推理过程。其中,AVX-512_VNNI 理论上可使推理效率提升至 4 倍,而 AVX-512_BF16 则能帮助训练性能提升达 1.93 倍。
让我们来看看更接地气的实践场景。以图像分析为例,如图三所示,如果在影像分析场景中引入集成有英特尔深度学习加速技术的英特尔® 至强® 可扩展处理器,配合 OpenVINO 工具套件,在对检测模型进行了 INT8 转换和优化后,推理速度较原始方案提升高达 8.24 倍,且精确度损失不到 0.17%。
对模型进行转换、优化前后在英特尔 ® 至强 ® 可扩展处理器上的效果对比 。
AI 实训:极高性价比
在了解 英特尔® 至强® 可扩展处理器加速模型训练的基本原理之后,我们再来考虑一件事,在模型计算量不那么大的情况下,使用 CPU 来训练模型有什么优势?显然,与昂贵的 GPU 不同,英特尔® 至强® 可扩展处理器 推理和训练的性价比极高。在只使用英特尔® 至强® 可扩展处理器的情况下,内存可以便捷地根据需要扩充,同时也可以根据任务和场景分配计算核心,这样的灵活性是其它硬件很难具备的。
例如拿一个入门级的小模型 LeNet-5 作为示例,我们可以讨论一下如何用几块性价比极高的英特尔® 至强® 可扩展处理器,打造一个计算核心可分配的深度学习系统。当然,在本例子中,分配计算资源主要为了多个「用户」,也许是学生,都能高效地训练 LeNet-5。实际上这种计算资源分配在企业中也非常常见,分割不同深度学习应用、不同用户的计算资源都是比较大的需求。
现在如果我们在英特尔® 至强® 可扩展处理器上使用 TensorFlow 训练 LeNet-5,那么重要的是确定最优并发线程数,以及最优算力分配方案,这样才能充分利用 CPU 的能力。
首先对于确定最优并发线程数,TensorFlow 在 CPU 上有三个重要参数:
OMP 并发线程数:单个进程中线程的并发数
intra_op 线程并发数:执行单个 OP 算子 时的并行线程数
inter_op 线程并发数:执行多个 OP 算子之间的线程并发数
如上图所示为经典的经验参数,一般 inter_op 在绝大多数情况下设置为 1 效果最好,但确定前两个参数需要实际运行一段时间。具体而言,我们可以给模型足够多的算力,并选择不同的并发线程数 thread_num,以查看模型的迭代速度。
首先我们可以选择默认配置,这样 LeNet-5 在 Fashion-MNIST 训练一个 epoch 需要 160 秒左右。当然这里因为数据集、模型特别小,所以可以用 epoch 的遍历时间作为指标,在真实数据集中我们还可以以迭代多少次的时间作为指标。
CPU 在默认参数下训练一个 epoch 的时间。
如下训练代码所示,现在我们可以将 OMP 与 intra_op 的并行数设置为 2,这样就能尝试新配置的训练迭代时间。实验表明这样的配置能大幅度降低训练耗时,最终只需要 4.55 秒。
LeNet-5 参数配置及训练代码,这一套配置迭代一个 epoch 的时间只需要 4.55 秒。
最后,依次将 thread_num 设置为不同的数值,我们就能得到一份并行数的分布表,从而选出最优 thread_num。当然,不同模型会有不同的最优并行数,只是因为 LeNet-5 模型比较小,所以两个并行数就能获得非常好的效果。
LeNet-5 在 Fashion-MNIST 数据集上的最优线程数的分布。
在确定最优线程数之后,我们还能确定为每个用户分配的最优核心数,即查看不同核数下的训练时间与 CPU 利用率。这里使用 numactl 命令就可以测试不同 Socket 与核心数运行模型。例如「numactl -C 0,48 -m 0 python train-lenet5.py」,则表明采用 0 与 48 两个核心,第 0 个 Socket。
如上图所示,这样的配置看起来训练速度也不是太低,只需要 6 秒就能迭代一个 epoch。这是由于 LeNet-5 模型较小,核多的时候,每个核分配到的计算量过小,导致整体计算效率不高,还不如分配少一点计算核心。
当我们跑完整个不同核心数的测试,就能得到下图关于训练时间、分配核心数、 CPU 利用率三者的关系。当然我们会选择更加经济高效的 2 核心配置。
总的而言,经过上面两种实验,我们能确定为单个 LeNet-5 模型配置的线程数、CPU 核心数这两大参数。这样的配置可以称得上具有极高性价比了,假设单张至强 CPU 具有 32 核,那么能为 16 个用户分配可观的训练资源,还不需要怎么降低训练速度。
所以说如果没有超高时延要求,主要对训练精度有要求的场景,CPU 的确是个高性价比的选择,比如在制造业等领域。
AI 产业应用:CPU 也可以是主角
在企业中部署 AI 模型,CPU 服务器其实也特别常用,只要模型对推断速度没有那么高的要求,只要模型不算特别大,使用搭载英特尔® 至强® 可扩展处理器的服务器部署可是能省太多预算了。在现实应用场景中,大多数 AI 实际要求的是并发量,要求计算的 指标是 Query Per Seconds, 这对于英特尔® 至强® 可扩展处理器来说特别合适。我们可以为每个模型进程配置适当的 CPU 核心数,从而获得极高的并发量。
在制造业与图像 / 影像业,模型都不会太大,它们就特别适合用 CPU 充当计算设备。
在制造业,基于机器视觉的工业辅助检测,或者基于云边协同新架构的 AI 瑕疵检测系统,都能引入了英特尔® 至强® 可扩展处理器作为边缘服务器的核心计算引擎,并借助英特尔 AVX-512 技术,为深度学习推理任务中的密集计算提供硬件加速,还引入 OpenVINO 工具套件来为检测提供软件调优,可大幅提升检测准确率并降低人力成本。
在制造业中,至强可扩展处理器可作为边缘计算设备,也可为多功能平台提供基本计算能力,以支持各种 AI 场景与模型。
此外对于常规的图像、影像识别,若引入英特尔® 至强® 可扩展处理器,并利用 OpenVINO 工具套件的优化能力,就可以解决以往采购专用硬件服务器带来的成本问题、推理速度与准确度平衡问题。使用 OpenVINO 工具套件来开展 AI 推理加速,深度学习模型能从 FP32 转换成为使用 VNNI 进行优化的 INT8,成功地加快了影像信息系统中深度学习的推理速度。
使用 INT8 量化推理能充分利用 CPU 的计算能力提升推断速度。
总的来说,从指令集到加速库,CPU 在支持深度模型上已经做了很多优化,常规的模型只使用 CPU 进行训练与推断已经是非常不错的选择。这种选择不仅具有极高的性价比,同时灵活性与稳定性还要远远超过其它计算设备,毕竟 CPU 内存、持久化储存都能比较简单地扩展。
所以,用 CPU 加速,AI 学习也能快又准。现在,你对英特尔® 至强® 可扩展处理器做 AI,是不是有了更多理解呢?