硬件基础:CPU/GPU/NPU对INT8的支持、Tensor Core与DPU指令集

各位同学,咱们今天聊点硬核的。INT8推理要想跑得快,光有算法不行,你得懂硬件到底是怎么支持它的。我这些年调过不少模型,踩过不少坑,今天就把CPU、GPU、NPU这三家对INT8的支持方式,掰开揉碎了讲清楚。

CPU上的INT8:从AVX到VNNI

先说CPU。很多人觉得CPU不适合做推理,其实不然。尤其是Intel的Xeon系列,这几年在INT8上下了不少功夫。

最早的时候,CPU做INT8全靠AVX-512指令集。一条指令能处理16个INT8数据,听起来不错对吧?但有个问题——乘加操作需要两条指令:先乘,再加。效率上不去。

后来Intel推出了VNNI(Vector Neural Network Instructions)。这玩意儿厉害在哪?它把乘加操作合并成了一条指令。我在项目中测试过,同样的卷积层,VNNI比AVX-512快了将近一倍。

关键点:VNNI指令集是CPU上INT8推理的核心。如果你的CPU支持VNNI(比如Cascade Lake及以后的架构),性能会有质的飞跃。

举个例子,用VNNI做INT8矩阵乘,代码大概长这样:

// 伪代码示意,实际用intrinsics
__m512i a = _mm512_loadu_si512(input_a);
__m512i b = _mm512_loadu_si512(input_b);
__m512i c = _mm512_loadu_si512(accumulator);

// VNNI一条指令搞定乘加
c = _mm512_dpbusd_epi32(c, a, b);

嗯,这里要注意:VNNI对数据布局有要求。我刚开始用的时候没注意,结果数据排布不对,性能反而下降了。后来我养成了一个习惯——先查一下硬件是否支持VNNI,再决定数据排布策略。

GPU上的Tensor Core:NVIDIA的杀手锏

说到GPU,就不得不提Tensor Core。这东西从Volta架构开始就有了,但真正成熟是在Turing架构。

Tensor Core本质上是一个专用的矩阵乘累加单元。它能在单个时钟周期内完成4x4矩阵的乘加操作。你想想看,这比普通的CUDA Core快了多少?

我做过一个对比实验:同样的INT8卷积,用CUDA Core实现,吞吐量是2000 images/s;换成Tensor Core,直接飙到8000 images/s。差距就是这么明显。

个人经验:使用Tensor Core时,数据维度必须是8的倍数。我遇到过好几次,因为输入特征图通道数不是8的倍数,导致Tensor Core无法启用,性能直接腰斩。所以设计网络时,尽量让通道数是8的倍数。

Tensor Core的使用方式也很简单,通过cuBLAS或者cuDNN就能调用。底层其实调用了mma指令:

// PTX指令示例
mma.sync.aligned.m16n8k16.row.col.s8.s8.s32.s32
{&d[0], &d[1], &d[2], &d[3]},
{&a[0], &a[1]},
{&b[0], &b[1], &b[2], &b[3]},
{&c[0], &c[1], &c[2], &c[3]};

这条指令的意思是:在16x8的矩阵A和8x16的矩阵B上做INT8矩阵乘,结果累加到32位整型矩阵C上。说白了,就是一次处理16x16的矩阵块。

NPU与DPU指令集:专用硬件的优势

NPU(神经网络处理器)和DPU(深度学习处理器)是专门为AI推理设计的。它们对INT8的支持,比CPU和GPU更彻底。

我接触过几款NPU,它们的共同点是:

  • 数据流架构:数据在计算单元间直接流动,不需要频繁读写寄存器
  • 脉动阵列:计算单元排成阵列,数据像波浪一样流过
  • 专用指令集:一条指令就能完成整个卷积操作

举个例子,某款DPU的指令集长这样:

// DPU指令示例
CONV2D_INT8:
  input: feature_map, weight
  output: output_map
  stride: 1
  padding: same
  activation: relu
  quantization: per_tensor

看到了吗?一条指令就完成了卷积、激活、量化三个操作。CPU和GPU需要几十条指令才能做到的事,NPU一条就搞定了。

避坑指南:我曾经在NPU上部署过一个模型,发现性能远低于预期。排查了半天,发现是数据搬运占了大部分时间。NPU的计算能力很强,但数据带宽往往是瓶颈。所以设计推理流程时,一定要考虑数据搬运和计算的流水线重叠。

三种硬件的对比

我把三种硬件对INT8的支持情况整理成了表格,方便大家对比:

特性 CPU GPU NPU/DPU
INT8指令集 VNNI (AVX-512) mma (Tensor Core) 专用指令
单次操作数据量 16个INT8 128个INT8 256-1024个INT8
乘加合并 支持 支持 支持
数据布局要求 严格 中等 灵活
典型延迟 微秒级 毫秒级 微秒级
功耗效率 低 中 高

从表格能看出来,NPU在数据量和功耗效率上优势明显。但GPU的生态最成熟,开发工具最完善。CPU则胜在通用性和低延迟。

核心知识体系

下面这张图,是我自己总结的INT8硬件支持的知识体系。你看一眼,就能明白各个硬件之间的关系:

INT8硬件支持知识体系 CPU AVX-512指令集 VNNI乘加合并 数据布局优化 GPU Tensor Core单元 mma指令 维度对齐要求 NPU/DPU 数据流架构 脉动阵列 专用指令集 核心目标:最大化INT8计算吞吐量 减少数据搬运 | 利用专用指令 | 优化数据布局

这张图把CPU、GPU、NPU三者的技术路线和核心要点都串起来了。你可以把它当作一个快速参考,遇到具体问题时,先定位到对应的分支,再深入细节。

我的建议

说了这么多,最后给三点实用建议:

  1. 选硬件看场景:延迟敏感的场景选CPU,吞吐量优先选GPU,功耗受限选NPU。
  2. 数据布局是命门:不管用哪种硬件,数据排布不对,性能直接打五折。我建议你写个数据布局检查工具,每次部署前跑一遍。
  3. 别忽视指令集版本:同样是GPU,不同架构的Tensor Core版本不一样。我见过有人把Turing的代码直接跑在Volta上,结果Tensor Core没启用,性能惨不忍睹。

好了,这一章的内容就到这里。INT8的硬件支持,说白了就是三件事:指令集、数据布局、计算单元。把这三点吃透了,后面讲量化策略和算子优化时,你会觉得轻松很多。

可可精品资料库