文章目录

  • 关于
  • GPU架构简介
    • GPC, TPC, SM, CUDA Core
    • 流多处理器 SM 的架构
  • 线程组的分派
    • SM和线程组
    • 线程组的数量选择
    • 线程组的分派和线程数量规划
    • 线程组的执行单位:warp

关于

本文从GPU架构去理解Computer Shader的线程组概念,分析了线程组和线程的数量如何规划,以及Dispatch函数和numthreads的参数的含义。(目前还是初步的理解,有可能存在错误,此文会进行迭代)

GPU架构简介

以nvidia为例, nvidia的GPU架构从老到新有Tesla, Fermi, Kepler, Maxwell, Pascal, Volta, Turing, Ampere等。本文以Pascal架构作为例子,GTX1060就是Pascal架构的。另外Nintedo Switch使用的是Maxwell架构的Tegra X1芯片。
参考:Pascal架构白皮书

GPC, TPC, SM, CUDA Core

  • GPU包含若干GPC (Graphics Processing Cluster, 图形处理簇)组成的阵列。
  • GPC又包含若干TPC (Texture Processing Cluster)
  • TPC中包含若干SM (Stream Multiprocessor,流多处理器)
  • SM中包含若干CUDA Core
    下图是Pascal架构的GP100图,可以看到它有6个GPC,每个GPC中有5个TPC,每个TPC中有2个SM,因此每个GPC有10个SM。GP100一共有30个 TPC, 60个SM。而每个SM包含64个CUDA Core(32位)和4个纹理单元。因此GP100的60个SM,一共有3840个CUDA核心和240个纹理单元。

流多处理器 SM 的架构


Pascal架构的SM中的核心被分为两组processing blocks,每组各有一个Instructoin Buffer, 一个Warp Scheduler,两个Dispatch Unit,一个Register File(寄存器堆) 以及32个Core。SM内部共享指令缓存,Texture/L1缓存,纹理单元(4个)以及64KB共享内存。

线程组的分派

SM和线程组

我们知道GPU有很多很多的核心,这种架构可以同时执行大量的操作,但是这些操作是如何组织的呢?从前面的GPU架构简介中我们已经知道,这些核心被组织成一个个的流多处理器SM(当然SM上层还有TPC和GPC,先忽略这些细节)。既然一个SM有若干core,那么SM当然是用来并行执行若干操作用的。所谓的操作就是线程,而这若干线程组成一个线程组,因此一个线程组运行在一个SM上。

线程组的数量选择

既然一个线程组运行在一个SM上,那么GPU有很多SM,所以我们可以同时执行很多的线程组。那么我们应该使用多少个线程组呢?根据DX12龙书的描述,每个SM至少应该拥有两个线程组,即线程组的数量应该为SM数量的2倍,比如如果GPU有16个SM,那么我们就应该至少将任务分解为32个线程组。使用2倍是因为为了保证处理的并行性,至少为每个SM分派两个线程组,当SM正在执行的一个线程组处于等待的状态时(比如等待纹理的处理结果),SM可以切换到另一个线程组执行。

线程组的分派和线程数量规划

DX12的Compute Shader使用Dispatch(x,y,z)函数分派一个线程组网格。参数x,y,z相乘就是线程组的数量,比如我们要分派32个线程组,可以使用Dispatch(8,4,1)进行分配。那么是否也可以使用Dispatch(4,8,1)呢?当然也可以了。那么这儿x,y,z的选择究竟有什么讲究呢?我理解这是为了方便线程的规划和使用。如果我们使用Compute shader对输入的贴图进行处理,由于贴图是2维的,思考一下如何让若干核心并行操作贴图的每个像素?肯定最好是每个像素分配一个核心,也就是一个线程进行处理,当然实际上核心数量可能没那么多,但是不要紧,我们分配的是线程嘛,一个核心可以轮着执行不同的多个线程。所以假设我们的贴图分辨率是512512,那么我们使用8列4行(x=8,y=4)的布局来规划这32个线程组,那么对于每个线程组中,我们在x方向需要512/8=64个线程,y方向需要512/4=128,即compute shader中使用[numthreads(64,128,1)]定义线程数量。这样在compute shader中,就可以使用SV_DispatchThreadID.xy来直接访问一个像素了,含义就是当前总体线程网格的(x,y)位置处理的那个像素,我们可以这么使用就是因为我们按照贴图的分辨率定义了x,y,z方向线程组和线程的数量。线程组相当于在贴图上划分了(a,b)个大格子,线程相当于在每个大格子里面再细分(c,d)个小格子,每个小格子就是一个像素,那么最终我们就有(ac, bd)个像素,而DispatchThreadID就是所有格子(像素)的x,y,z坐标。当然这儿的线程数还是有一个限制,对于nvidia显卡来说,线程组中的总线程数(即cd)应该为warp大小(32)的倍数,而AMD的显卡应该为wavefront尺寸(64)的整数倍,所以我们应该让线程组中的线程总数为64的整数倍。使用compute shader基本理解到这儿就可以了,可以按照需要规划线程组和线程数量了。但是为了研究执行时的效率问题,还要再看一下线程组具体如何调度执行的。

线程组的执行单位:warp

一个线程组包含n个线程,这是我们的静态设定。但是运行时,这n个线程不大可能同时并行执行,当然核心数往往也没那么多。SM在执行线程组时,会进一步将这n个线程分成多个warp(线程簇)来执行,每个warp会同时运行32个线程。比如我们上面定义的64*128=8192个线程,会被分为8192/32=256个warp。插一句,是不是感觉warp有点多啊,确实,因为上面假定的GPU只有16个SM,因此我们只规划了32个线程组,所以造成每个线程组的线程数超级多,正常一个SM才32个核心,warp太多了肯定性能不行啊,得来回切换。看上面的pascal架构,有60个SM,这样就可以规划至少120个线程组,这样每个线程组的线程数量就大大减少了。
总之,线程组按照warp为单位进行执行。下图中我们可以看到warp是被Warp Scheduler调度管理的,Warp调度器其实就是在不停的切换Warp执行不同的指令,而指令是由指令调度单元去分配给每个核心,每个warp调度器可以有一或多个指令调度单元,下图是一对一,上面的pascal架构是一对二,因此指令分配的更快。
指令调度单元(Dispatch Unit)从指令缓存中取出shader中的操作指令,分配给每个Core去执行,调度单元分配给每一个Core的指令都是相同的,因此一个Warp中同一时刻所有线程执行的是相同的指令。不过虽然指令相同,每个Core操作的数据是不同的,这就是所谓的SIMT(单指令多线程)。一个Warp中,所有的32个线程是同步执行的,这种方式叫做lock-step,所有线程执行相同指令,执行完当前指令后,Dispatch Unit再发送下一条指令给大家执行,所有线程齐头并进。
下图右边,是两个warp执行线程的情况,warp1是0到31号线程,由于shader程序中存在分支,部分线程执行if分支,另外一部分执行else分支,由于warp需要同步执行指令,因此结果是先执行完if再执行else,这就造成了性能的损失。而第2个warp中执行的函数没有分支,因此所有线程可以同步执行。另外第2个warp的shader代码中有可能也有if/else语句,但是所有的线程都只执行if或else,那么也不需要等待了,因为另外一个分支没有线程执行。看下图中箭头的颜色,貌似warp2所有线程执行的都是else。

GPU架构和Compute Shader线程规划相关推荐

  1. GPU架构(三十三)

    一.导言 对于大多数图形渲染开发者,GPU是既熟悉又陌生的部件,熟悉的是每天都需要跟它打交道,陌生的是GPU就如一个黑盒,不知道其内部硬件架构,更无从谈及其运行机制. 本文以NVIDIA作为主线,将试 ...

  2. Compute Shader次世代优化方案

    这是侑虎科技第498篇文章,感谢作者凯奥斯供稿.欢迎转发分享,未经作者授权请勿转载.如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨.(QQ群:793972859) 作者主页:https://z ...

  3. AMD统一渲染GPU架构 历程回顾与评测

    AMD统一渲染GPU架构 历程回顾与评测     前言:NVIDIA公司历经长时间酝酿的Fermi架构高端产品GTX480/GTX470发布已经结束,经历了长达一个月的忙碌,我们已经了解到了这款产品的 ...

  4. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader)...

    Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader) 原文: Int ...

  5. android device monitor命令行窗口在哪里_Vulkan在Android使用Compute shader

    oeip 相关功能只能运行在window平台,想移植到android平台,暂时选择vulkan做为图像处理,主要一是里面有单独的计算管线且支持好,二是熟悉下最新的渲染技术思路. 这个 demo(git ...

  6. CUDA ---- GPU架构(Fermi、Kepler)

    GPU架构 SM(Streaming Multiprocessors)是GPU架构中非常重要的部分,GPU硬件的并行性就是由SM决定的. 以Fermi架构为例,其包含以下主要组成部分: CUDA co ...

  7. Directx 计算着色器(compute shader)

    原文 :http://www.cnblogs.com/Ninputer/archive/2009/12/11/1622190.html 博者注:计算着色器调试(http://msdn.microsof ...

  8. NVIDIA GPU 架构梳理

    文中图片大部分来自NVIDIA 产品白皮书 TODO:英伟达显卡型号梳理 目录: 一.NVIDIA GPU的架构演变历史 二.Tesla 架构 三.Fermi架构 四.Kepler架构 五.Maxwe ...

  9. 光影之路 GPU架构发展史(3/4)

    5.2003年:Radeon 9800击败GeForce FX 5800 2002年11月,NVIDIA发布代号为NV30的GeForce FX 5800 Ultra,这款产品被NVIDIA视作夺回市 ...

  10. CUDA编程——GPU架构,由sp,sm,thread,block,grid,warp说起

    目录 1.从硬件看 2.从软件看 3.对应关系 4.SIMT和SIMD 掌握部分硬件知识,有助于程序员编写更好的CUDA程序,提升CUDA程序性能,本文目的是理清sp,sm,thread,block, ...

最新文章

  1. Blockchain Patent Players and domain
  2. Pyhton为什么这么厉害?无意中从一道奥数题发现Python真的爽翻了
  3. HoloLens开发手记-全息Hologram
  4. java掌握_掌握Java 11的Constantdynamic
  5. 以计算机谈人文科学,阅读下面一段文字,完成问题   自20世纪80年代以来,世界都在谈“软科学技术”,何谓软科学?经常听人说:“脑子不够使。”这其实就是对软科学的需求。于是,从古至今,...
  6. 对比关系生成模型(Comparative Relation Generative Model)
  7. maya崩溃自动保存路径_xgen 分享在maya里制作头发失败经验
  8. JS:ES6-11 数值扩展与对象扩展
  9. 使用MTL库求解矩阵特征值和特征向量
  10. MPLS virtual private network路由信息的发布过程
  11. 酒精传感器实验-传感器原理及应用实验
  12. arcgis栅格数据绘制等值线_ArcGIS教程:绘制等值线的工作原理
  13. BZOJ4567 [SCOI2016]背单词
  14. UE4Possess切换控制Pawn
  15. 云开发谁是卧底线下小游戏发牌助手微信小程序源码-亲测可用
  16. 1.1. 内容创作不再是少数“业内人”的工作,而是多数“普通人”的生活。
  17. 论文阅读13:ENHANCING COLLABORATIVE FILTERING MUSIC RECOMMENDATION BY BALANCING EXPLORATION AND EXPLOITAT
  18. Go学习笔记 -- 方法
  19. 杭州市建筑工程职称评审工作
  20. 全球与中国射频仪表市场深度研究分析报告

热门文章

  1. 家用计算机按键不灵怎么修,空格键失灵了怎么办?电脑键盘按键失灵的解决办法...
  2. spss变量视图转数据视图_SPSS的数据视图和变量视图
  3. LA4487 Exclusive-OR (加权并查集)
  4. python两个表格相同数据筛选的方法_浅谈pandas筛选出表中满足另一个表所有条件的数据方法...
  5. [haoi2009]毛毛虫 树形dp
  6. 阿里云平台购买域名 域名配置 域名解析步骤
  7. 嵌入式系统开发与应用——Linux系统Socket网络编程
  8. ArrayList源码分析--底层扩容机制
  9. 环境风险模型总结及实现方案
  10. Linux设置小红点键盘,debian linux上安装thinkpad小红点驱动/Installing Debian On Thinkpad – Trackpoint...