GPU Microarch 学习笔记【3】Tensor Core_tensorcore 寄存器布局-程序员宅基地

技术标签: Microarchiture  GPU  

目录

1. 指令与架构

2. Load

3. 计算MMA

4. Set, Step 与thread group

5. OCTET

6. Tensor Core微架构

7. Final


Nvidia自从Volta/Turing(2018)架构开始,在stream multi processor中加入了tensor core,用于加速矩阵计算。如下图所示,其中每个SM有两个tensor core。相信大家也看了这个图很多次,那么一个tensor core里面的64个绿色小格子代表的是什么级别的计算呢?

图片

  图自[3]

指令与架构


Tensor core支持mixed precision和FP16矩阵计算:D = A x B + C. mixed precision指的是 A和B为FP16,但是C和D为FP32或FP16. 

图片

CUDA9.0支持的最小矩阵乘法为16x16x16(不是一个周期就能计算完毕的),下图所示为Tensor Core load A, B, C,进行mma(matrix multiply-accumulate),而后store结果D的PTX指令,其中每个指令都有sync,用于进行warp-wide的同步。

图片

Tensor Core PTX指令

Volta的每个SM core内部有两个tensor core,每个Tensor Core每个周期可以完成一个 4x4x4的MACC操作,如下图所示:

图片

这里的4x4x4指的是A*B矩阵中A的维度为4x4, B的维度为4x4,A*B的计算量即为4x4x4。

这里写的two 4x4x4是因为有两个tensor core。

下图右侧即为Turing架构新引入的tensor core,在A和B矩阵的精度为FP16时,每次A的4x4,B的矩阵4x4,每次进行乘法累加,得到下方绿色的4x4。INT8和INT4复用乘法单元,计算能力分别x2,x4。

图片

图片

传统的CUDA教学里面,每个线程的寄存器是private,仅自己可见。

但是对于Tensor Core来说,一个warp内的线程,互相之间的寄存器都是可见的。因此一个warp的32个线程,可以各自load输入矩阵A,B,C的一部分,加载到register file,读取时也可以复用其他寄存器加载的寄存器。

与传统CUDA相同,tensor core的一个warp仍然是32个thread,但是不同的是,32个thread被切成了8个thread group,每个thread group 4个线程。

Load


首先将是将矩阵加载到寄存器中: 

图片

如左图所示,一共16行,每4行为一个segment,每个segment由两个thread group一同加载。一行16个元素,每个元素16bit,共计256bit,需要两条load.E.128指令完成。

这里个人理解,因为一共四行,每行可以两个thread加载,所以可以每个thread执行一个load.E.128,一共32个thread

32(thread 个数)*128(load.E.128) = 16(矩阵行数)*16(矩阵列数)*16(每个元素大小)

文章未具体介绍。

计 算MMA


加载之后就是计算了,一条mma 16*16*16的指令如下图所示,

图片

在Nvidia的SASS汇编级别会被展开成16条指令:

图片

这里只展示了mixed precision的汇编。FP16的汇编指令与此相同,但是概念相通,这里就不赘述。

上图右侧显示了计算完毕一条16x16x16需要的时间,54个cycle,除了开始需要10个cycle,后面每条指令基本上只需要2个cycle。

需要注意的是,这里的16条指令会在一个warp的32个thread上同时执行。

上图左侧,一共有4个set,每个set内部又有4个step。

Set, Step与Thread Group


Set,step都是汇编级别的指令,都是逐一计算的,但是thread,thread group这些thread的概念,是同时进行的。具体step,set和thread group的切分如下图所示。

从set的角度看矩阵的计算: 

图片

如上图所示的是thread group 0的计算每个set可以计算完毕一个4*4*8的计算,4次set计算完毕之后,就可以得到最终的C矩阵中的一个4*8小矩阵。与此同时,其他的thread group 1-7也在进行计算,最终我们就可以得到完整的C矩阵。 

图片

更细致的计算解释如下图所示:

图片

如上图(b)所示,每个step完成了2*4*4的计算,得到了2*4的矩阵输出(上图b的ADBC标错了,应该是ABCD)。

那么是如何完成2*4*4的计算的呢?

OCTET 


这里又要引入一个新的概念OCTET,具体的OCTET负责的计算一个8*8的小矩阵具体如下图所示:

图片

之所以引入这个概念,是因为OCTET内部的threadgroup存在加载数据的依赖关系,比如上图b)中,每个小方块为4x4的矩阵。

  • d,c,b,a,D,C,B,A由thread group 0加载

  • h,g,f,e,H,G,F,E由thread group4加载

因此当thread group0计算a*A和a*E时,需要等待thread group4加载完毕,也就是Octet内部的计算需要另一个thread group load完毕数据,但是Octet之间不存在数据依赖关系。

而这个依赖关系,个人理解后面会体现在thread group 0和4公用的matrix buffer上。

如下图所示,step0/1,threadgroup0和4公用thread0加载的A,step2/3,threadgroup0和4公用thread0加载的E.

图片

这里的a[0:1]代表a的0行和1行

而再回忆一下刚才介绍的输出C的矩阵:

图片

可以看出OCTET 0的这个部分是由Thread group 0和 Thread group 4共同计算完成的。

Tensor Core 微架构


图片

如上图所示,右上角的为一个FEDP unit (four-element dop-product),这个灰色的单元,每个可以完成一个行矩阵和一个列矩阵的点乘计算,即一个1*4的行矩阵和一个4*1的列矩阵的点乘计算。这个4次的乘法累加,每周期可以计算完毕一次。

每个thread group内部有4个,那么就是4*4,可以理解成一个1*4的A矩阵和一个4*4的B矩阵,每个周期可以计算完毕一次A和B的成累加,那么两个周期,就可以计算完毕一个两行四列的A矩阵和一个4行4列的B矩阵的计算,得到一个两行四列的C矩阵。对应了上面的单个step的计算图。

图片

我们再回忆一下,tensor core支持每周期4*4*4的矩阵计算,这里一个thread group每个周期可以计算完毕1*4*4的计算,每个Octet内部有两个thread group,即2*4*4,而每个tensor core内部又有两个Octet,这样每个周期就可以有4*4*4的计算量了。

图片

Octet0内部的Thread group0和Thread group共用了一个matrix B buffer,利用了计算时复用矩阵的B的特点,减轻了加载操作数到计算单元的负担。

Final


到这里我们已经从架构,指令,指令分解到微架构已经明白了Volta的tensor core是如何计算的。

那么具体的每个tensor core内部有2个Octet,每个Octet有2个thread group,每个thread group有4个thread,每个thread执行在一个FEDP上,每个FEDP内部有四个乘法单元,2*2*4*4 = 64.

也就是说最开始的那个问题,tensor core里面的绿色小格子就是一个乘法单元: 

图片

也就是微架构图里的这个:

图片

本文是基于文章[1]和[2]的理解。

[1] Modeling Deep Learning Accelerator Enabled GPUs

[2] Dissecting the NVIDIA Volta GPU  Architecture  via Microbenchmarking

[3] https://learnopencv.com/demystifying-gpu-architectures-for-deep-learning-part-2/

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hit_shaoqi/article/details/134498937

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签