Part 1 OpenPPL ARM Server 简介
OpenPPL Arm Server 定义
• 针对高性能 ARM 架构服务器处理器优化的深度学习推理引擎
• 目前支持 FP32 及 FP16 两种浮点数精度格式
• 支持常见的分类网络以及部分超分、分割网络推理
• 支持多 batch 数据、多线程、多推理实例等不同并行方式
Part 2 Arm 架构及 A64 指令集、Neon 指令
2.1 Arm
• 精简指令集 (RISC) 处理器架构
• 通常使用定长指令集 (32-bit)
• 广泛应用在移动端、嵌入式设备
2.2 Arm 部分新特性
• Arm v8
• 首次支持A64指令集架构(64位)
• 更新 NEON 指令
• Arm v8.2
• 支持 FP16 运算
• 目前 OpenPPL Arm Server 所支持的最高 ISA
• Arm v8.4
• 支持有/无符号整数点积指令 (SDOT, UDOT)
• Arm v8.6
• 支持通用矩阵乘法 (GEMM,[2x4]×[4x2],混合精度)
• 支持 BF16 运算
• SIMD 矩阵乘法运算
• Arm v9
• 基于 Arm v8.5特性
• 支持 SVE 2指令集
2.3 NEON指令(Advanced SIMD)
• 128-bit 向量数据处理,支持 1、2、4、8字节不同长度的元素
• 支持全长 (128-bit) 或者半长 (64-bit) 向量计算,同时用于标量浮点数计算
• 提供了32个向量寄存器
• 部分 Neon 指令用例:
Part 3 Arm Server 微架构特点 (以鲲鹏920处理器为例)
3.1 鲲鹏920处理器的体系结构特点——核心架构
• TaiShan v110(Armv8.2-A ISA,非公版设计)
• 前端:
• 每周期最多取指4条
• 支持静态、动态(两级)分支预测
• 后端:
• 乱序执行
• 整数运算单元:3条ALU流水线,1条MDU流水线(整数乘除法运算)
• AdvSIMD 与浮点运算单元:两条FSU流水线(AdvSIMD)
• Load/Store 单元:两个L/S端口,含硬件自动预取器
• 缓存:
• L1 ICache: 4路,64KiB (private)
• L1 DCache: 4路,64KiB (private)
• L2 Cache: 8路,512KiB (private)
• L1 ITLB: 全关联,32表项(支持4KB~1GB页大小)
• L1 DTLB: 全关联,32表项(支持4KB~1GB页大小)
• L2 TLB: 4路组关联,1152表项
• LLC/L3 Cache: 32~64MiB (1 MiB per core, shared)
3.2 鲲鹏920处理器的体系结构特点——片上系统
• 处理器内核集群 CCL(Core CLuster):
• 包含4个处理器内核及其 L1 I/ DCache、L2 Cache
• 包含1个 L3 Cache Tag
• 超级内核集群 SCCL (Super CCL)
• 包含6个/8个内核集群(CCL)
• 包含2个 I/O 集群,4个 DDR 控制器
• 包含若干 L3 Cache Data,多核缓存一致性模块 (HHA)
• 环形总线互联
• 相应 I/O 部件:I/O 集群,超级 I/O 集群
3.3 鲲鹏920微架构性能测试
• 计算部分:
• Little’s law:需要 5 × 2 = 10 条独立(无数据依赖)的 FMLA 指令,才能充分利用Neon单元
• 访存部分:
• 使用一般的 pointer chasing 无法看到特征的 L2, L3 Cache 以及内存的load to use latency
• 进一步的测试显示,在 4K 页的配置下,L2 Cache latency 受到了L1 TLB miss 的影响
Part 4 OpenPPL Arm Server 卷积实现
4.1 卷积——常规算法和实现设计
• input: (N, Ci , Hi , Wi ), output: (N, Co , Ho , Wo), weights: (Co , Ci , Kh , Kw )
• 计算量:Co × Ci × Kh × Kw × Ho × Wo × 2 FLOP
• 并行维度:Co , Ho , Wo
• 累加维度:Ci , Kh , Kw
4.2 卷积——基础 Im2col-GEMM 实现
矩阵乘法:
4.3 算法优化
• tile Im2col:
• 分块做 im2col,减小用于 im2col 的额外内存开销
• Direct:
• 按卷积公式计算,无额外 im2col 开销
• 在 Co 维度上进行向量化
• Winograd:
• 降低卷积计算量,常用于 3×3、5×5 的卷积
• 减小卷积中的累加维度,增加额外的并行维度
• 需要额外的前后转换计算
• 在计算机浮点数运算中会产生误差
• 在 FP16 精度下更明显, 切分单元越大则误差越大
4.4 数据排布优化
• Ndarray 排布 —— 原始张量格式 (n, c, h, w)
• NBCX 排布 —— (n, c, h, w) → (n, c/cblk, h, w, cblk)
• 在 im2col 转换 / 直接卷积 / winograd 前后转换 中,易于利用 Neon 指令向量化
• 在 channel wise 算子(如 pooling2d, resize等)中,充分利用 Neon 指令
• NBCX 排布下,对卷积权重进行重排
• (Co , Ci , Kh , Kw ) → (Co / cblk, Ci / cblk, Kh , Kw , icblk, ocblk)
• 以外积的方式进行计算时,权重访存连续
• 重排在离线处理/预处理的阶段完成
4.5 GEMM 分块计算优化——寄存器分配
考虑 FMLA 与 LD 指令的比例,使用分块2能够最好地通过排布指令来用计算指令掩盖访存的时间。
4.6 GEMM 分块计算优化——缓存复用 (cache blocking)优化
• 保留三个矩阵各自的一个分块在 L1 DCache 中
• ( m1 × k1 + k1 × n1 + m1 × n1 ) × sizeof(type) ≈ 64KB
• 采用相对固定的分块大小
• 支持在预处理阶段,搜索性能最优的分块大小
• 权重数据在预处理阶段时,会按照分块大小进行重排优化访存
• Kunpeng920 上针对 L2 Cache 的blocking优化没有明显效果
4.7 多线程优化
• 任务分割
• 单 batch 内部,按 Co , Ho , Wo 并行维度分割
• 多 batch,按独立的 batch 分割
• 分组卷积,按独立的分组分割
• 任务并行调度 —— 基于 OpenMP 的多线程实现
• 多线程绑定到同一 NUMA 节点内的核心
4.8 多线程 Conv2d – Im2col
4.9 多线程 Conv2d – Winograd
Part 5 OpenPPL Arm Server 性能展示
5.1 推理性能——单线程单 batch
5.2 推理性能——单线程多 batch
5.3 OpenPPL Arm Server 开发计划与展望
• 支持更多的网络模型和算子
• 语义分割、目标检测等网络
• 支持 Int8 数据精度推理和 Arm v9 特性
Part 6 Q&A
Q:1. Arm 能否支持 transformer 或者 bert 的推理?
OpenPPL 框架方面研发和优化的支持计划已上线,整体上优先 GPU 和 x86 ,Arm 后续再行安排。有对 CPU transformer 感兴趣的同学,可以关注 x86 方面的开源情况和支持情况。
Q:2. OpenPPL 现在是否会针对 NUMA 架构提供推理方案?
OpenPPL ARM Server 支持在不同的 NUMA node 上面 launch 不同的推理引擎实例。有不同的推理数据流和流水线,不同的推理实例绑定在不同的 NUMA node 上,它们之间没有数据交互,通过这样的方式来使用服务器上的多节点、多 NUMA node 的核心。之后会尝试把一个推理实例分散到多个 NUMA node 上面进行推理计算。
Q:3. OpenPPL ARM Server 和 mobile 端有没有区别?
目前研发和优化主要针对 ARM Server 处理器,基于鲲鹏处理器开发。在不同的架构上面,已有比较好的性能并进行优化,比如公版的 ARM Server 的处理器。但对于 mobile 端,并没有进行特殊的优化。而且可能在某些算法实现、算法选择及实现参数上面,与 mobile 有比较大的不同。
Q:4. ARM 的 Micro Batch mark 的方法和设计思路是什么?
设计思路参考了别的架构的 micro-benchmark 的设计。之前在从事 x86 CPU(Sandy Bridge, Xeon Phi) 方面相关工作中,了解到相关的 micro-benchmark 针对指令的延时和 throughput, load/store 及 cache prefetcher 相关特性的实验。关于这方面,有不少论文和对应的公开的源码。这些 micro-benchmark 中,使用架构内部的一些 performance monitor unit 计算各个 event 所需的 cycle 数量,而不是非常宏观地使用一些系统级的 time stamp 函数测量它们的时间。这样,可以得到更加精细的实验结果。
Q:5. 针对其他的国产化架构有适配吗?比如说飞腾?
目前接触到的最新飞腾处理器支持 Armv8.0 的 ISA 架构,所以只支持 F32。我们的 OpenPPL 在上面能够运行且有着不错的性能。
|