AMD 矩阵核心

news2024/9/28 22:21:00

AMD matrix cores — ROCm Blogs

注意: 本文博客之前是  AMD lab notes 博客系列的一部分。

矩阵乘法是线性代数的一个基本方面,它在高性能计算(HPC)应用中是一个普遍的计算。自从 AMD 推出 CDNA 架构以来,广义矩阵乘法(GEMM)计算现在通过矩阵核心处理单元实现了硬件加速。矩阵核心加速的 GEMM 内核位于像 rocBLAS 这样的 BLAS 库的核心,但开发人员也可以直接编程。通过利用矩阵核心,可以使在 GEMM 计算受限的吞吐量的应用程序获得额外的加速。

AMD 的矩阵核心技术支持全范围的混合精度操作,使我们能够处理大型模型并增强任何 AI 和机器学习工作负载的内存受限操作性能。各种数值格式在不同的应用中有其用途。例如,8 位整数(INT8)用于机器学习推理,32 位浮点数(FP32)用于机器学习训练和高性能计算应用,16 位浮点数(FP16)用于图形工作负载,以及 16 位脑浮点(BF16)用于在训练中减少收敛问题的机器学习。

要了解使用矩阵核心相比于 SIMD 向量单元所能实现的理论加速,请参考下表。表格列出了上一代(MI100)和当前一代(MI250X)CDNA 加速器的向量单元(即融合乘加(FMA))和矩阵核心单元的性能。

MI100 和 MI250X 的矩阵核心性能:

Data format

MI100 Flops/Clock/CU

MI250X Flops/Clock/CU

FP64

N/A

256

FP32

256

256

FP16

1024

1024

BF16

512

1024

INT8

1024

1024

矢量(FMA)单元在 MI100 和 MI250X 上的性能:

Data format

MI100 Flops/Clock/CU

MI250X Flops/Clock/CU

FP64

64

128

FP32

128

128

与矢量单元性能相比,MI100 和 MI250X 上的矩阵核心速度提升。_注意,MI250X 还支持打包 FP32 指令,这也会使 FP32 吞吐量加倍_:

Data format

MI100 Matrix/Vector Speedup

MI250X Matrix/Vector Speedup

FP64

N/A

2x

FP32

2x

2x

使用 AMD 矩阵核心

AMD CDNA GPU 中的矩阵融合乘加(MFMA)指令在每个波前(wavefront)上操作,而不是在每个车道(线程)上操作:输入和输出矩阵的条目分布在波前的矢量寄存器的车道上。

可以通过多种方式利用 AMD 矩阵核心。在高层次上,可以使用诸如 rocBLAS 或 rocWMMA 等库在 GPU 上进行矩阵操作。例如,rocBLAS 可以在有利于当前计算时选择使用 MFMA 指令。对于更接近底层的方法,可以选择:
- 完全用汇编语言编写 GPU 内核(这可能有些具有挑战性且不太实用)
- 在 HIP 内核中夹杂内联汇编(不推荐,因为编译器不会查看内联指令的语义,可能不会解决数据危害,例如在使用 MFMA 指令结果之前所需的强制性周期数)

- 使用编译器内置函数:这些函数表示汇编指令,以便编译器了解其语义和要求。

本文中的编码示例使用了一些可用的 MFMA 指令的编译器内置函数,并展示了如何将输入和输出矩阵的条目映射到波前的矢量寄存器车道上。所有示例都使用单个波前来计算一个小的矩阵乘法。这些示例并非旨在展示如何从 MFMA 操作中获得高性能。

MFMA编译器内部函数语法

考虑以下矩阵乘法 MFMA 操作,其中所有操作数AB、 C、 D 均为矩阵:

D = AB + C

要在 AMD GPU 上执行 MFMA 操作,LLVM 内置了函数。回想一下,这些内置函数是在整个波阵面宽度(wavefront-wide)上执行的,输入和输出矩阵的部分内容会加载到波阵面中每条通道的寄存器中。MFMA 编译器内部函数的语法如下所示:
d = \_\_builtin\_amdgcn\_mfma\_CDFmt\_MxNxKABFmt (a, b, c, cbsz, abid, blgp)

其中,
CDFmt 是 C 和 D 矩阵的数据格式
ABFmt 是 A 和 B 矩阵的数据格式
M、`N` 和 K 是矩阵的维度:
  - mA[M][K] 源矩阵 A
  - mB[K][N] 源矩阵 B
  - mC[M][N] 累加输入矩阵 C
  - mD[M][N] 累加结果矩阵 D
a 是存储源矩阵 A 的值的向量寄存器集合
b 是存储源矩阵 B 的值的向量寄存器集合
c 是存储累加输入矩阵 C 的值的向量寄存器集合
d 是存储累加结果矩阵 D 的值的向量寄存器集合
cbsz,控制广播大小修饰符,用于更改输入值馈送到矩阵核心的方式,仅受到具有多个输入块的 A 矩阵指令的支持。设置 cbsz 会通知指令将一个选定的输入块的值广播到 A 矩阵中的 2^cbsz 个其他邻近块。使用 abid 参数来确定选择哪个输入块进行广播。默认值 0 表示不广播值。例如,对于 16 块的 A 矩阵,设置 cbsz=1 将导致块 0 和 1 接收相同的输入值,块 2 和 3 接收相同的输入值,块 4 和 5 接收相同的输入值,等等。

abid,A 矩阵广播标识符,支持具有多个输入块的 A 矩阵指令。它与 cbsz 一起使用,并指示选择哪个输入块广播到 A 矩阵中的其他邻近块。例如,对于 16 块的 A 矩阵,设置 cbsz=2 且 abid=1 将导致块 1 的值被广播到块 0-3,块 5 的值被广播到块 4-7,块 9 的值被广播到块 8-11,依此类推。
blgp,B 矩阵通道组模式修饰符,允许对通道之间的 B 矩阵数据进行一组限制的变换操作。对于支持此修饰符的指令,可以使用以下值:
  - blgp=0 正常的 B 矩阵布局
  - blgp=1 从通道 0-31 的 B 矩阵数据也会被广播到通道 32-63
  - blgp=2 从通道 32-63 的 B 矩阵数据会被广播到通道 0-31
  - blgp=3 所有通道的 B 矩阵数据向下旋转 16 位(例如,通道 0 的数据会被放入通道 48,通道 16 的数据会被放入通道 0)
  - blgp=4 从通道 0-15 的 B 矩阵数据会被广播到通道 16-31、32-47 和 48-63
  - blgp=5 从通道 16-31 的 B 矩阵数据会被广播到通道 0-15、32-47 和 48-63
  - blgp=6 从通道 32-47 的 B 矩阵数据会被广播到通道 0-15、16-31 和 48-63
  - blgp=7 从通道 48-63 的 B 矩阵数据会被广播到通道 0-15、16-31 和 32-47

在 CDNA2 GPU 上支持的矩阵维度和块数量列在下表中。

A/B Data Format

C/D Data Format

M

N

K

Blocks

Cycles

Flops/cycle/CU

FP32

FP32

32

32

2

1

64

256

32

32

1

2

64

256

16

16

4

1

32

256

16

16

1

4

32

256

4

4

1

16

8

256

FP16

FP32

32

32

8

1

64

1024

32

32

4

2

64

1024

16

16

16

1

32

1024

16

16

4

4

32

1024

4

4

4

16

8

1024

INT8

INT32

32

32

8

1

64

1024

32

32

4

2

64

1024

16

16

16

1

32

1024

16

16

4

4

32

1024

4

4

4

16

8

1024

BF16

FP32

32

32

8

1

64

1024

32

32

4

2

64

1024

16

16

16

1

32

1024

16

16

4

4

32

1024

4

4

4

16

8

1024

32

32

4

1

64

512

32

32

2

2

64

512

16

16

8

1

32

512

16

16

2

4

32

512

4

4

2

16

8

512

FP64

FP64

16

16

4

1

32

256

4

4

4

4

16

128

完成的 CDNA2 架构支持的所有指令列表可以在 AMD Instinct MI200 Instruction Set Architecture Reference Guide 中找到。AMD 的 Matrix Instruction Calculator 工具允许生成关于 AMD Radeon™ 和 AMD Instinct™ 加速器上 MFMA 指令的计算吞吐量和寄存器使用等更多信息。

示例 1 - V_MFMA_F32_16x16x4F32

考虑矩阵乘法运算 D = AB,其中 M = N = 16K = 4,且元素类型为 FP32。为简化计算,我们假设输入矩阵 \(C\) 含有零元素。我们将演示使用内建函数 __builtin_amdgcn_mfma_f32_16x16x4f32 计算一次调用中四个外积的和。此函数操作单个块的矩阵。

输入矩阵AB 的尺寸分别为 16 \times 44 \times 16,矩阵CD的尺寸为16 \times 16。将一个16 \times 4 线程块映射到两个输入矩阵的元素是方便的。在此,每个线程块有一个波阵面,x 维上有 16 个线程,y 维上有 4 个线程。我们采用行主序格式来表示矩阵: A[i][j] = j + i * N,其中i是行索引,j是列索引。使用此表示方法,位置 x, y的线程会加载条目 A[x][y] 和 B[y][x]。输出矩阵有 16 \times 16个元素,因此每个线程都有 4 个元素要存储,如下图和代码片段所示。

以下两张图显示了 1) A 和 B 输入的形状和大小;2) A 和 B 的元素如何在波阵面所属的寄存器中映射到不同的通道中。

通过这样的描述和图示,您能更直观地理解 MFMA 指令在高性能计算任务中的应用及其实现方式。

下面的两幅图显示了:1) 输出矩阵 D 的形状和大小;2) D 矩阵的元素如何映射到波前拥有的寄存器中的通道中。

下面给出了一个执行此 MFMA 操作的示例内核。

#define M 16
#define N 16
#define K 4

using float4 = __attribute__( (__vector_size__(K * sizeof(float)) )) float;

__global__ void sgemm_16x16x4(const float *A, const float *B, float *D)
{
  float4 dmn = {0};

  int mk = threadIdx.y + K * threadIdx.x;
  int kn = threadIdx.x + N * threadIdx.y;

  float amk = A[mk];
  float bkn = B[kn];
  dmn = __builtin_amdgcn_mfma_f32_16x16x4f32(amk, bkn, dmn, 0, 0, 0);

  for (int i = 0; i < 4; ++i) {
    const int idx = threadIdx.x + i * N + threadIdx.y * 4 * N;
    D[idx] = dmn[i];
  }
}

该内核的启动方式如下。

dim3 grid (1, 1, 1);
dim3 block(16, 4, 1);
 
sgemm_16x16x4 <<< grid, block >>> (d_A, d_B, d_D);

如前所述,输入 C 矩阵假定包含零。

例子 2 - V_MFMA_F32_16x16x1F32

考虑使用编译器内建函数 __builtin_amdgcn_mfma_f32_16x16x1f32 进行矩阵乘法,矩阵的尺寸为 M=N=16 和 K=1。在这种情况下,输入值可以仅由波阵面(wavefront)的16个通道(lanes)持有。实际上,这条指令可以同时乘以4个这样的矩阵,因此每个通道持有其中一个矩阵的值。
我们可以重新使用上一个例子的图来说明该操作的数据布局。在这种情况下,输入矩阵 A 不是16×4的矩阵,而是四个16×1的矩阵。但它们的布局方式,以及每个通道在波阵面(wavefront)中拥有的元素是相同的。A矩阵的“列”是不同的16×1矩阵。输入矩阵 B 也是类似的。

给定矩阵乘法的输出数据布局与前一个例子完全相同。不同之处在于,现在有四个独立的输出,每个乘法对应一个输出。
下面的代码示例展示了对4个尺寸为M=N=16和K=1的矩阵进行批量打包乘法运算的内核。

#define M 16
#define N 16
#define K 1

using float16 = __attribute__( (__vector_size__(16 * sizeof(float)) )) float;

__global__ void sgemm_16x16x1(const float *A, const float *B, float *D)
{
  float16 dmnl = {0};

  int mkl = K * threadIdx.x + M * K * threadIdx.y;
  int knl = threadIdx.x + N * K * threadIdx.y;

  float amkl = A[mkl];
  float bknl = B[knl];

  dmnl = __builtin_amdgcn_mfma_f32_16x16x1f32(amkl, bknl, dnml, 0, 0, 0);

  for (int l = 0; l < 4; ++l) {
    for (int i = 0; i < 4; ++i) {
      const int idx = threadIdx.x + i * N  + threadIdx.y * 4 * N + l * M * N;
      D[idx] = dmnl[i];
    }
  }
}

此内核使用以下方式启动:

dim3 grid (1, 1, 1);
dim3 block(16, 4, 1);

sgemm_16x16x1 <<< grid, block >>> (d_A, d_B, d_D);

示例 3 - V_MFMA_F64_4x4x4F64

考虑 V_MFMA_F64_4x4x4F64 指令,它计算四个独立的大小为 4×4 的矩阵块的 MFMA。执行的操作是 Z_{N}=W_{N}X_{N}+Y_{N},其中,W_{N}X_{N}Y_{N }Z_{N} 都是大小为 4×4 元素的矩阵,且 N=0,1,2,3。
下图显示了 1) 输入参数 A 和 B 的四个组成部分的大小和形状,以及 2) 这些组成部分如何映射到波前持有的寄存器中的通道。该指令的参数包括 A、B、C 并返回 D,因此我们理解为每个参数和输出都包含 4 个矩阵。

输出D和输入C的布局与输入B的布局相同。

关于rocWMMA的一点说明

我们仅介绍了三个使用编译器内建函数来利用AMD矩阵核心的示例。更多示例可以在rocm-blogs/blogs/software-tools-optimization/matrix-cores at release · ROCm/rocm-blogs · GitHub找到。请注意,内建函数可能会在未来发生变化,因此最好使用AMD的rocWMMA C++库来加速混合精度MFMA操作。rocWMMA API有助于将矩阵乘累加问题分解为片段,并在波阵列内并行分布进行块状操作。该API是GPU设备代码的头文件库,可以将矩阵核心加速直接编译到你的内核设备代码中。这可以在生成内核汇编时受益于编译器优化。更多详情请参考rocWMMA仓库。

关于AMD矩阵指令计算器工具的一点说明

对于那些对AMD Radeon和AMD Instinct加速器上各种MFMA指令性能感兴趣,并希望了解矩阵元素与硬件寄存器之间映射关系的用户,我们推荐AMD矩阵指令计算器工具。这个强大的工具可以用来描述WMMA指令以及给定架构的MFMA ISA级指令。我们欢迎社区问题和反馈。

其他资源

• AMD Instinct MI200指令集架构参考指南
• AMD CDNA架构白皮书
• AMD CDNA™ 2架构白皮书
• AMD矩阵指令计算器工具
我们要感谢Joseph Greathouse的帮助性审查和建议。如果你有任何问题或意见,请在GitHub 讨论区联系我们。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2174941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot+Vue+MySQL的甜品店管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 在数字化浪潮的推动下&#xff0c;甜品店行业也面临着转型与升级的需求。传统的线下经营模式已难以满足现代消费者对于便捷、高效购物体验的追求。为了提升运营效率、优化顾客体验&#xff0c;我们设计了一款基于SpringBoot后端…

Django基础-创建新项目,各文件作用

学习Django的前置知识&#xff1a; python基本语法&#xff1a;需要掌握Python中的变量、循环、条件判断、函数等基本概念。面向对象编程&#xff08;OOP&#xff09;&#xff1a;Django的核心架构基于面向对象编程&#xff0c;许多功能&#xff08;如模型和视图&#xff09;依…

黑神话悟空小西天

游戏里我们一开始就出现一个很可爱的小和尚&#xff0c;当脚步声传来&#xff0c;小和尚化身为一尊弥勒佛&#xff0c;而这尊弥勒佛的大小和位置都在说&#xff0c;这里没有弥勒佛的位置。 随后天命人进入一片雪地&#xff0c;遇到了赤尻马猴&#xff0c;打跑赤尻马猴&#xff…

C++_unordered系列关联式容器(哈希)

unordered系列关联式容器&#xff0c;我们曾在C_map_set详解一文中浅浅的提了几句。今天我们来详细谈谈 本身在C11之前是没有unordered系列关联式容器的&#xff0c;unordered系列与普通的map、set的核心功能重叠度达到了90%&#xff0c;他们最大的不同就是底层结构的不同&…

AVL树(平衡二叉树)的介绍以及相关构建

欢迎光临 &#xff1a; 羑悻的小杀马特-CSDN博客 目录 一AVL树的介绍&#xff1a; 二AVL树的实现&#xff1a; 1结构框架&#xff1a; 2节点的插入&#xff1a; 旋转&#xff1a; 21左单旋&#xff1a; 2.1.1左单旋介绍及步骤&#xff1a; 2.1.2左单旋代码实…

【JavaSE系列】IO流

目录 前言 一、IO流概述 二、IO流体系结构 三、File相关的流 1. FileInputStream 2. FileOutputStream 3. FileReader 4. FileWriter 四、缓冲流 五、转换流 1. InputStreamReader 2. OutputStreamWriter 六、数据流 七、对象流 八、打印流 九、标准输入输出流…

C++学习9.28

1> 创建一个新项目&#xff0c;将默认提供的程序都注释上意义 por QT core gui #QT表示引入的类库 core:核心库例如IO操作在该库中 gui:图形化显示库 #如果要使用其他类库中的相关函数&#xff0c;就需要调用相关类库后&#xff0c;才能加以使用greaterThan(Q…

c++926

1.什么是虚函数&#xff1f;什么是纯虚函数&#xff1f; 虚函数&#xff1a;被virtual关键字修饰的成员函数&#xff0c;用于实现多态性&#xff0c;通过基类访问派生类的函数。纯虚函数&#xff1a;在虚函数后面添加0&#xff0c;只有声明而没有实现&#xff0c;需要派生类提…

天龙八部怀旧单机微改人面桃花+安装教程+GM工具+虚拟机一键端

今天给大家带来一款单机游戏的架设&#xff1a;天龙八部怀旧单机微改人面桃花。 另外&#xff1a;本人承接各种游戏架设&#xff08;单机联网&#xff09; 本人为了学习和研究软件内含的设计思想和原理&#xff0c;带了架设教程仅供娱乐。 教程是本人亲自搭建成功的&#xf…

图说数集相等定义表明“R各元x的对应x+0.0001的全体=R“是几百年重大错误

黄小宁 设集A&#xff5b;x&#xff5d;表A各元均由x代表&#xff0c;&#xff5b;x&#xff5d;中变量x的变域是A。其余类推。因各数x可是数轴上点的坐标故x∈R变为实数yx1的几何意义可是&#xff1a;一维空间“管道”g内R轴上的质点x∈R(x是点的坐标)沿“管道”g平移变为点y…

红队信息搜集扫描使用

红队信息搜集扫描使用 红队行动中需要工具化一些常用攻击&#xff0c;所以学习一下 nmap 等的常规使用&#xff0c;提供灵感 nmap 帮助 nmap --help主机扫描 Scan and no port scan&#xff08;扫描但不端口扫描&#xff09;。-sn 在老版本中是 -sP&#xff0c;P的含义是 P…

视频美颜SDK与直播美颜工具API是什么?计算机视觉技术详解

今天&#xff0c;小编将深入探讨视频美颜SDK与直播美颜工具API的概念及其背后的计算机视觉技术。 一、视频美颜SDK的概念 视频美颜SDK是一套用于开发实时美颜效果的工具集&#xff0c;开发者可以利用它在视频流中实现面部特征的优化。这些SDK通常提供了一系列功能&#xff0c…

.NET 红队武器库和资源集合 (第38期)

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

计算机网络自顶向下(1)---网络基础

目录 1.网络的分类 2.网络协议 3.网络分层结构 1.OSI七层模型 2.TCP/IP四层模型 3.网络与OS的关系 4.网络传输基本流程 1.协议报头 5.网络中的地址管理 1.IP地址 2.端口号 6.传输层协议 1.TCP协议 2.UDP协议 3.网络字节序 7.socket 1.网络的分类 局域网&…

excel-VBA知识点记录

1、计算机硬件的组成部分 内存&#xff0c;一旦断电&#xff0c;存储在里面的数据就消失了&#xff0c;而硬盘是永久存储数据的&#xff0c;所以刚开始我们在文件里面编辑没有按保存的时候&#xff0c;数据是在内存里面的&#xff0c;一旦断电数据就没了&#xff0c;但我们点了…

大语言模型知识点分享

1 目前主流的开源模型体系有哪些&#xff1f; Prefix Decoder 系列模型 核心点&#xff1a; 输入采用双向注意力机制&#xff0c;输出为单向注意力。双向注意力意味着输入的每个部分都可以关注到输入的所有其他部分&#xff0c;这在理解上下文时具有很强的优势。 代表模型&a…

六级翻译 高分笔记

第一节 句子的拆分与重组 核心原则&#xff1a;拆主干&#xff0c;补修饰 一、句子的拆分与重组 1.青藏铁路是世界最高最长的高原铁路。&#xff08;“的”字前面所有去掉&#xff0c;就是句子主干&#xff09; The Qinghai-Tibet Railway is the highest and longest plate…

css 数字比汉字要靠上

这个问题通常是由于数字字体的下排的问题造成的&#xff0c;也就是数字的底部边缘位置比汉字的顶部边缘位置更靠下。为了解决这个问题&#xff0c;可以尝试以下几种方法&#xff1a; 使用CSS的vertical-align属性来调整对齐方式。例如&#xff0c;可以将数字的对齐方式设置为to…

数组的练习

1.使用函数的递归方法&#xff0c;输出给定字符串的逆序&#xff0c;如"abcdefg"&#xff0c;输出为“gfedcba”. 方法一&#xff1a;首先不采用递归的方法&#xff0c;如何完成上述要求 #include<stdio.h> #include<string.h> int main() {char arr[]…

3.数据结构与算法-基本概念和术语

数据、数据元素、数据项和数据对象 数据 数据元素 学生表-记录 数-节点 图&#xff1a;顶点 数据项 数据对象 数据对象与数据元素的关系 数据结构 数据结构的三个部分 逻辑结构的种类 存储结构分类 顺序存储结构 链式存储结构 索引存储结构 散列存储结构 数据类型和抽象数据类…