作者:旷视 MegEngine 架构师 张孝斌

疾速理解 mperf

在挪动/嵌入式平台,为了最大水平施展硬件算力,对算子极致性能的谋求变成必然,不同于桌面/服务器平台,挪动/嵌入式平台在算子性能调优方面可抉择的工具很少。

MegEngine 团队始终在摸索什么样的工具可能在算子调优流程中带来助益,来帮忙达成如下的算子性能调优反馈回路,这也是 mperf 诞生的背景。

<p align=center><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/db65dd714a724afd943a3860cc041974~tplv-k3u1fbpfcp-zoom-1.image" alt="图1 算子性能调优反馈回路" /></p>
<p align=center>图1 算子性能调优反馈回路</p>

mperf 是一个微架构档次的算子性能调优工具箱,次要面向挪动/嵌入式平台的 CPU/GPU 外围,指标是“为构建一个更靠近闭环的算子调优反馈回路”提供系列根底工具。

外围性能:

  • [根底能力] 测试微架构档次的各类罕用性能剖析参数(GFLOPS/Multi-level Bandwidth/Latency...)
  • [根底能力] 提供 PMU(Performance Monitoring Unit) 数据获取能力
  • [性能剖析] 绘制 Hierarchical Roofline
  • [问题定位] 加工 PMU 数据失去各种指标(如 IPC, Instructions per cycle)、TMA(Top-Down Microarchitecture Analysis Method)剖析能力,能够作为局部 vendor 提供的 GUI 剖析工具的平替
  • [优化指引] 提供 OpenCL Linter 计划(后续版本提供)
  • ...

作为一个 C++ API 级别的工程,mperf 内部依赖少,能够简略不便(侵入式)集成到指标工程中,目前曾经开源到 GitHub,欢送大家试用交换。

应用办法参考 README 文档;疾速上手指南见 Tutorial 文档

对 mperf 的实现原理感兴趣的同学,能够持续往下看~~

开展说说 mperf 的工程实现

缘起

算子调优目前还是一个难以闭环的工作,须要开发者对指标硬件架构个性、算子优化程度评估、性能瓶颈定位、丰盛的优化技巧等都有很深的理解之后能力变得熟能生巧。同时随着 CPU/GPU 架构越来越多,越来越简单,一般的开发者很少有精力去深刻了解各个架构的个性,问题变得更加辣手。

现实中的调优过程是可能造成如上图所示的闭环,甚至能够走向编译器全自动化调优计划,过程中往往须要依赖工具实现,在桌面/服务器平台的工具较为齐备,如 linux perf, lmbench/stream,NVIDIA NSight Compute,Intel vtune/Advisor/pmu-tools 等开闭源工具等都提供了一部分能力,通过人为组合还是能失去比拟全的能力;与此同时,在挪动/嵌入式平台,也有 simpleperf、Arm mali streamline、snapdragon profiler、MegPeak、ArchProbe、HWCPipe 等优良的开闭源工具,然而齐备性和易用性方面都存在很多问题:

  • GUI 工具不反对函数级/代码片段剖析(如基于 PMU 的指标剖析等,详见下方“PMU 数据收集、加工和剖析”),还不容易扩大新的剖析指标
  • 不反对 ARM CPU 的 TMA 剖析(详见下方“PMU 数据收集、加工和剖析”)
  • 绘制 Roofline 等所依赖的根底数据的获取能力散落在多个工具中,一般同学很难动手
  • 很少的优化领导能力

因而咱们启动了 mperf 我的项目,心愿提供系列工具来残缺取得这些根底能力:

  • 常见 CPU/GPU 微架构参数,目前曾经反对 ARM CPU/Mali GPU/ Adreno GPU 的局部型号
  • 通过 Hierarchical Roofline 模型评估算子优化程度
  • 通过丰盛的指标和 TMA 分析模型来定位性能瓶颈/提示性能问题
  • 通过 OpenCL Linter 等工具能固化专家优化教训,扫描用户代码后给出性能优化倡议
  • ...

常见 CPU/GPU 微架构参数

为 Roofline 绘制/Metrics (指标)计算等模块提供架构相干的根底参数,如多级存储 bandwidth/latency,指令 throughput/latency,各种根底 micro-kernel的bandwidth,GPU 特有的参数(warp size 等)等,这部分是惯例性能,测试原理很多都参考了 MegPeak/lmbench/ArchProbe 等工程的实现,此处不再开展,仅举一个小例子不便大家看到它的价值。

例1. 在挪动端 GPU 上在做向量计算的时候,咱们会关怀 int8:int16:int32 算力是否肯定存在 4:2:1 的关系?mperf 实测数据显示在 Adreno A640 出现难以解释的 int16>int8>int32,在 Mali G78 上则满足比例关系,实测的详实数据会告知开发者 float->int16 定点化是否能带来性能收益。

Hierarchical Roofline 绘制

原生 Roofline Model 建模了“算子计算模式、指标硬件架构、性能”三者之间的关系,能够为算子调优提供大方向的指引,比方:

  • 确认瓶颈:位于 Machine Balance Point 左侧是访存 bound,右侧是计算 bound
  • 领导优化方向: 如果是访存 bound,能够思考联合各种已知的专家教训如 tiling/prefetch/aligned allocator 等进行优化尝试,也就是晓得了致力的方向
  • 提醒进行优化的机会:如果是计算 bound 且曾经靠近屋顶(峰值性能下限),能够思考进行优化
  • 预测性能:如果已知架构峰值性能数据、算子自身的计算访存比、计算规模这三个数据就能算估算出执行工夫

但因为原生 Roofline Model 存在一些问题:

  • 未辨别多级存储的状况,个别只思考 DRAM Bandwidth,如果输出 Tensor 小到能够塞入 L1 Cache,采纳 L1 Cache Bandwidth 更加精确
  • 未辨别执行环境的复杂性,比方是否启动多线程,处于 Turbo Mode 等,这些都影响理论实践峰值
  • 未辨别指令类型(instruction mixes),个别默认采纳繁多指令如 FMA 进行测试,理论实践峰值能够是不同指令性能的加权求和
  • 未辨别 read/write/access,比方 sum(Tensor),采纳 read Bandwidth 更加精确

之后倒退出了 Hierarchical Roofline,理论中为了不便绘制,mperf 提供了不同的伎俩来获取上述根底数据。

绘制Roofline须要两组数据:

  • 架构实践峰值性能(GFLOPS)和带宽(Bandwidth)

    • 实践峰值性能:单指令测试原理参考此文;剖析不同指令占比的计划还在验证中;
    • 实践带宽: 提供的计划能够测试多级存储带宽,并提供各种根底 micro-kernel (如纯 read 函数)来测试贴近理论访存模式的带宽下限
  • 算子实测性能/带宽: 通过 PMU 的形式获取

PMU 数据收集、加工和剖析

PMU 数据收集

CPU/GPU 架构大多都蕴含 PMU 硬件,用于计数一些底层硬件事件,如 CPU Core 所属的执行指令数和时钟周期,Cache 所属的 L1 Cache Miss 等;mperf 提供了 CPU/GPU 的 PMU 数据获取能力,特地是 Adreno GPU 这种不足官网开源反对的平台。

加工指标(又名 Metrics)

以 ARM A55 Core 为例,有超过 100 种硬件事件,Adreno A6xx 系列 GPU 则有约 125 种硬件事件,这些事件的数值能够用来加工计算各种指标,如 IPC=INST_RETIRED 计数(指令数)/ CPU_CYCLES 计数(Cycle 数),也能够用来计算 DRAM Bandwidth、算子 GFLOPS、L1 MISS Ratio 等等,具体的指标反对列表及其计算形式可浏览文档及源码。

图2 Arm A76 Core 微架构图(起源)

TMA 剖析

TMA 是一套自顶向下的 Intel CPU 算子性能瓶颈分析方法,这套思维能够扩大到其它架构。上图形容了 A76 Core 指令的生命周期,过程中波及到的硬件资源(如可执行 FMA 的端口数量)都可能成为指令执行过程中的瓶颈,TMA 用于剖析瓶颈所在,从而指引优化方向,具体思维大家能够浏览官网文档。

mperf 计算失去的所有指标中一部分能够归类进 TMA 范式,另一部分作为独自的指标存在用于辅助性能剖析。不论是 TMA 还是独立指标都能够提供细粒度的优化方向指引。

在 mperf 外面咱们将 TMA 扩大到了 ARM CPU 上,过程中咱们失去了一些教训:

  • 因为 ARM CPU 提供的硬件事件的类别/定义与 Intel CPU 有很多差别,完满复刻 TMA 各类别的定义很艰难也不事实,然而 ARM CPU 自身提供的硬件事件的类别也很丰盛,能够摸索和总结出适宜本身的 TMA 计划和独立指标,实际中咱们证实了这条路行的通。
  • ARM 不同系列 CPU 微架构之间有显著差别,比方 A55(in-order)与 A76(out-of-order)在 TMA 各类别/定义上有很多不同,每个架构都须要独自解决。
  • 因为 vendor 相干材料凋谢水平不同,局部指标的定义可能会在长期实践验证中被修改。

本模块 GPU 局部的长期指标是成长为挪动端 GPU 相似 NVIDIA Nsight Compute 的等价物。目前曾经总结了很多有优化指导意义的 GPU 指标,但 TMA 在 GPU 上可行性和必要性咱们还在摸索中。在通用计算相干指标方面(不波及渲染相干),目前曾经具备代替 ARM 官网 GUI 工具 streamline 和高通官网 GUI 工具 snapdragon profiler 的能力,应用这两个 GUI 工具的同学能够尝试替换为 mperf,一方面 API 级别更加灵便,另一方面能够享受到一直增补指标(Metrics)带来的益处。

这里同样举一个理论例子来展现 mperf 的工作逻辑:

例2:GPU 反对不同向量宽度的浮点数据加载,如 vload4/8/16 等等,不同的架构有不同的限度,并不是向量宽度越宽越好,咱们察看到 Mali G78 GPU 上 vload4 比 vload16 快很多,在 mperf 中的剖析逻辑如下:

首先收集一系列 event 的数值(下图 3 展现了其中一部分),如 ExternalMemoryReadBytes 含意是 DDR→Unified L2 Cache 的 read 数据量,能够看出 vload16 绝对 vload4 减少了 4 倍还多, LoadStoreReadFull(LS_MEM_READ_FULL) 含意是 full-width read 的次数,LoadStorePartial(LS_MEM_READ_SHORT)代表了 partial-width read 的次数,发现在 vload16 的时候 partial-width read 的次数增大了很多,额定发射了更多的 read 指令,解释了速度变慢的起因。为了不便疾速发现此类问题,mperf 也专门整顿了一个 PartialReadRatio 的指标,其计算公式见下方。


图3 Mali G78 vload4/vload8

// PartialReadRatio 计算公式GpuCounter::PartialReadRatio, [this] {    return get_counter_value(MALI_NAME_BLOCK_SHADER, "LS_MEM_READ_SHORT") /           (float)(get_counter_value(MALI_NAME_BLOCK_SHADER,"LS_MEM_READ_FULL") + get_counter_value(MALI_NAME_BLOCK_SHADER, "LS_MEM_READ_SHORT"));}

更多对于 PMU 数据收集、加工和剖析的细节,欢送大家浏览源码。

OpenCL Linter

MegEngine 团队在做 OpenCL 算子开发的过程中积攒了一系列优化教训,心愿能通过工具化的形式将这部分教训固化下来。

目前初步打算参考 Linter 思路,大体有两个局部:

  • 动态代码剖析扫描 OpenCL Kernel,查看规定是预置的 OpenCL 专家优化教训,如应用 select 指令而非三目运算符,对齐查看等,给出优化倡议。
  • 在动静执行过程中监测各种预置的指标,联合专家教训对一些异样数据给出提醒,如寄存器使用量剖析等,疏导用户调优。

这部分工作目前正在做 POC 验证,敬请期待。

总结

mperf 为挪动/嵌入式平台性能调优提供了系列工具,其中在 PMU 获取/ARM TMA/分层 Roofline 绘制/OpenCL Linter 等方面都有不同水平的翻新,心愿这个工具箱能为开发人员提供更多的剖析伎俩和调优倡议。

以后阶段 mperf 开发方向会以优先丰盛根底工具为主,局部工具临时还须要一些体系结构的常识能力用好,更久远来看,咱们会做更多的工作来升高应用门槛,朝着更易用更自动化的方向致力。与此同时,大家都心愿有一套闭环的方法论来通知咱们算子调优的时候每一步先剖析什么指标,而后倡议尝试 N 种优化办法,一直迭代到最优,然而目前业内间隔这个愿景还有点远,mperf 也是如此,它的次要能力此刻还停留在为开发者提供更多决策信息的阶段。

为了能更近一步,下一阶段咱们会先从积攒丰盛的实操案例动手,和 mperf 的使用者一起摸索在不同的案例下什么样的指标能发现问题,什么样的优化办法能够尝试;之后在发现特定指标异样的时候能够将积攒的优化办法展现给用户。因而,mperf 是一个具备成长性的工程,欢送大家一起参加共建,聚沙成塔,打造好用的调优工具!

mperf 开发过程中受到了下面提到的各种优良开源工程的启发和指引,方法论上参考了大量包含 Intel/ARM 官网文档在内的诸多材料,在此一并致谢!

附:

更多 MegEngine 信息获取,您能够:查看文档和 GitHub 我的项目,或退出 MegEngine 用户交换 QQ 群:1029741705。欢送参加 MegEngine 社区奉献,成为 Awesome MegEngineer,荣誉证书、定制礼品享不停。