65.9K
CodeProject 正在变化。 阅读更多。
Home

减少矩阵-矩阵乘法中的打包开销

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2017 年 2 月 7 日

CPOL

7分钟阅读

viewsIcon

19006

提升多核和众核 Intel® 架构上的性能,特别是对于深度神经网络

点击此处免费试用软件下载

Kazushige Goto、Murat Efe Guney 和 Sarah Knepper,软件开发工程师,英特尔公司

通用矩阵乘法 (GEMM) 是许多科学、工程和机器学习应用中的基本操作,也是 BLAS(基本线性代数子程序)领域中的关键例程之一。GEMM 存在四种精度(实数单精度、实数双精度、复数单精度和复数双精度)。在本文中,我们关注 SGEMM(实数单精度)。

SGEMM 的 Fortran API 是

SGEMM(transa, transb, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc)

它执行以下计算

C := alpha * op(A) * op(B) + beta * op(C),其中 op(X) = XX<sup>T</sup>(取决于 transx 参数的值)。

数组 AB 是输入,而 C 既是输入又是输出。数组 A 包含一个 mk 列的矩阵,数组 B 包含一个 kn 列的矩阵,数组 C 包含一个 mn 列的矩阵。领先维度 (ldaldbldc) 决定了从一列到下一列的步幅,允许 GEMM 处理更大矩阵的一部分。领先维度还可以通过使后续列与缓存行对齐或映射到 8 路一级缓存上的同一组来影响性能。

Intel® 数学核心函数库 (Intel® MKL) 提供了高性能的 GEMM 实现。优化矩阵乘法的典型方法是将原始输入矩阵的块转换为内部数据格式(例如打包格式),通过手写汇编内核乘以转换后的块,然后更新输出矩阵。1 选择块大小以最大限度地利用缓存和寄存器。打包的原因有很多

  • 能够将 A 和 B 的更多数据放入缓存中,从而允许更大的分块和更多的数据重用
  • 连续、对齐和可预测的访问,最大限度地减少缓存和数据转换旁路缓冲区 (DTLB) 缺失
  • 减少循环开销

对于高性能计算中的常规大小,这种基于打包的方法效果很好。通常,这里 m 和 n 相对较大,而 k 可能适中(外积)或也相对较大(平方),因此打包输入矩阵所花费的时间相对于计算内核所花费的时间来说很小。然而,对于其中 m 或 n 之一相对较小的尺寸,如某些机器学习应用中常见的,打包开销可能会变得显著。因此,不依赖显式打包的 GEMM 实现可以胜过传统的、基于打包的 GEMM 实现。Intel MKL 11.3 Update 3 包含针对这些偏斜尺寸优化的 {S,D}GEMM 内核,适用于 Intel® 高级矢量扩展 2 (Intel® AVX2) 和 Intel® 高级矢量扩展 512 (Intel® AVX-512) 以及第二代 Intel® Xeon Phi™ 处理器。后续版本的 Intel MKL 继续改进这些内核。

为了展示这些新内核带来的好处,图 1 比较了 Intel MKL 2017 Update 1 中 SGEMM 与 Intel MKL 11.3 Update 2 在机器学习中可能出现的尺寸下的性能。这里,m 和 k 分别固定为 1000 和 256,而 n 变化。性能以吉flops(每秒数十亿次浮点运算)给出,因此越高越好。

图 1. 改进的 Intel® MKL SGEMM 在偏斜尺寸下的性能

根据 SGEMM 调用的具体情况(包括处理器类型和线程数、问题大小和领先维度以及转置参数),Intel MKL 选择使用传统内核或新的无打包内核。依赖 Intel MKL 进行 SGEMM 性能的深度学习框架无需修改框架即可受益于这些优化。

当一个或多个输入矩阵(A 或 B)在多次矩阵乘法中重复使用时,可以进一步最小化打包开销;例如,这可能发生在循环神经网络中。在这种情况下,我们可以一次性支付打包重复使用矩阵的成本,然后在多次 SGEMM 计算中使用打包版本。Intel MKL 2017 引入了用于 {S,D}GEMM 的打包 API,允许将打包开销分摊到多次矩阵乘法中。对于单精度,四个新的打包 API 是

dest = sgemm_alloc (identifier, m, n, k)
sgemm_pack (identifier, trans, m, n, k, alpha, src, ld, dest)
sgemm_compute (transa, transb, m, n, k, A, lda, B, ldb, beta, C, ldc)
sgemm_free (dest)

参数与 SGEMM 相似,增加了标识符字符,用于标识要打包的矩阵(A 或 B)。sgemm_computetransatransb 参数可以像往常一样设置为“T”(转置)或“N”(不转置);此外,值 P 表示相应的矩阵处于内部打包格式。如果输入矩阵被多次使用,打包 API 将提供好处;因此,sgemm_allocsgemm_pack 将分别被调用一次以分配内存并将所需矩阵打包成内部打包格式,然后多次调用 sgemm_compute,其中打包矩阵作为输入矩阵之一传递。最后,调用 sgemm_free 以释放内存。(有关更多详细信息,请参阅Intel® 数学核心函数库开发人员参考。)

图 2 显示了 sgemmsgemm_compute 的性能比较(其中 A 矩阵已打包,并忽略打包时间),以吉flops 为单位。

配置信息 - 版本:Intel® 数学核心函数库 (Intel® MKL) 2017.1;硬件:Intel® Xeon® 处理器 E5-2699v4,2 个 22 核 CPU (55MB LLC, 2.2GHz),64GB RAM;操作系统:RHEL 7.2 GA x86_64。

性能测试中使用的软件和工作负载可能已针对 Intel 微处理器上的性能进行优化。SYSmark 和 MobileMark 等性能测试是使用特定的计算机系统、组件、软件、操作和功能进行测量的。任何这些因素的任何更改都可能导致结果有所不同。您应该查阅其他信息和性能测试,以帮助您全面评估您考虑的购买,包括该产品与其他产品结合时的性能。*其他名称和品牌可能被声称是他人的财产。基准测试来源:英特尔公司

优化声明:Intel 的编译器对于非 Intel 微处理器可能不会以相同的程度进行优化,对于那些非 Intel 微处理器独有的优化。这些优化包括 SSE2、SSE3 和 SSSE3 指令集以及其他优化。Intel 不保证在非 Intel 制造的微处理器上任何优化的可用性、功能或有效性。本产品中依赖微处理器的优化旨在与 Intel 微处理器一起使用。某些不特定于 Intel 微架构的优化保留给 Intel 微处理器。请参阅适用的产品用户和参考指南,了解有关本声明所涵盖的特定指令集的更多信息。声明修订号 #20110804。

图 2. 使用 Intel® MKL 打包 API 实现更快的矩阵乘法

在 GEMM 调用之间重复使用较大输入矩阵 A 和 B 的应用程序,从打包 API 中受益的潜力最大。如果 m 和 n 参数都很大,或者重复使用两个输入矩阵中较小的一个,则切换到打包 API 的性能改进可能不足以证明编程工作的合理性。因此,我们建议在修改应用程序代码以使用打包 API 之前测量特定用例的性能。

正如我们所见,传统 GEMM 实现中发现的内部打包操作可能会带来显著的开销,特别是对于一个或多个维度较小的尺寸。这种开销可以通过使用避免显式打包输入矩阵的内核,或者通过将打包成本分摊到多次 GEMM 计算中来减少。从 Intel MKL 11.3 Update 3 开始,{S,D}GEMM 可以选择使用直接在输入矩阵上操作而无需首先打包到内部缓冲区的内核;使用哪些内核是根据问题特征和处理器信息在运行时确定的。另外,Intel MKL 2017 引入了打包 API,允许显式打包一个或两个输入矩阵,然后将其重复用于多次矩阵乘法计算。这两种方法有助于在多核和众核 Intel® 架构上实现高 GEMM 性能,特别是对于深度神经网络产生的尺寸。

1. Kazushige Goto 和 Robert A. van de Geijn。2008 年。《高性能矩阵乘法的剖析》。 ACM Transactions on Mathematical Software, 34, 3, 文章 12, 2008 年 5 月。

立即试用 Intel® 数学核心函数库 (Intel® MKL)

© . All rights reserved.