CUDA的Threading:Block和Grid设定

硬件基本架构  实际上在 nVidia 的 GPU 里,最基本的处理单元是所谓的 SP(Streaming Processor),而一颗 nVidia 的 GPU 里,会有非常多的 SP 可以同时做计算;而数个 SP 会在附加一些其他单元,一起组成一个 SM(Streaming Multiprocessor)。几个 SM 则会在组成所谓的 TPC(Texture Processing Clusters)。
  在 G80/G92 的架构下,总共会有 128 个 SP,以 8 个 SP 为一组,组成 16 个 SM,再以两个 SM 为一个 TPC,共分成 8 个 TPC 来运作。而在新一代的 GT200 里,SP 则是增加到 240 个,还是以 8 个 SP 组成一个 SM,但是改成以 3 个 SM 组成一个 TPC,共 10 组 TPC。下面则是提供了两种不同表示方式的示意图。(可参考《NVIDIA G92终极状态!!》、《NVIDIA D10U绘图核心》)
   对应到 CUDA
  而在 CUDA 中,应该是没有 TPC 的那一层架构,而是只要根据 GPU 的 SM、SP 的数量和资源来调整就可以了。
  如果把 CUDA 的 Grid - Block - Thread 架构对应到实际的硬件上的话,会类似对应成 GPU - Streaming Multiprocessor - Streaming Processor;一整个 Grid 会直接丢给 GPU 来执行,而 Block 大致就是对应到 SM,thread 则大致对应到 SP。当然,这个讲法并不是很精确,只是一个简单的比喻而已。
   SM 中的 Warp 和 Block
  CUDA 的 device 实际在执行的时候,会以 Block 为单位,把一个个的 block 分配给 SM 进行运算;而 block 中的 thread,又会以「warp」为单位,把 thread 来做分组计算。目前 CUDA 的 warp 大小都是 32,也就是 32 个 thread 会被群组成一个 warp 来一起执行;同一个 warp 里的 thread,会以不同的数据,执行同样的指令。此外,在 Compute Capability 1.2 的硬件中,还加入了 warp vote 的功能,可以快速的进行 warp 内的简单统计。
  基本上 warp 分组的动作是由 SM 自动进行的,会以连续的方式来做分组。比如说如果有一个 block 里有 128 个 thread 的话,就会被分成四组 warp,第 0-31 个 thread 会是 warp 1、32-63 是 warp 2、64-95 是 warp 3、96-127 是 warp 4。
  而如果 block 里面的 thread 数量不是 32 的倍数,那他会把剩下的 thread 独立成一个 warp;比如说 thread 数目是 66 的话,就会有三个 warp:0-31、32-63、64-65。由于最后一个 warp 里只剩下两个 thread,所以其实在计算时,就相当于浪费了 30 个 thread 的计算能力;这点是在设定 block 中 thread 数量一定要注意的事!
  一个 SM 一次只会执行一个 block 里的一个 warp,但是 SM 不见得会一次就把这个 warp 的所有指令都执行完;当遇到正在执行的 warp 需要等待的时候(例如存取 global memory 就会要等好一段时间),就切换到别的 warp 来继续做运算,藉此避免为了等待而浪费时间。所以理论上效率最好的状况,就是在 SM 中有够多的 warp 可以切换,让在执行的时候,不会有「所有 warp 都要等待」的情形发生;因为当所有的 warp 都要等待时,就会变成 SM 无事可做的状况了~
  下图就是一个 warp 排程的例子。一开始是先执行 thread block 1 的 warp1,而当他执行到第六行指令的时候,因为需要等待,所以就会先切到 thread block 的 warp2 来执行;一直等到存取结束,且刚好有一个 warp 结束时,才继续执行 TB1 warp1 的第七行指令。


                               
登录/注册后可看大图

  实际上,warp 也是 CUDA 中,每一个 SM 执行的最小单位;如果 GPU 有 16 组 SM 的话,也就代表他真正在执行的 thread 数目会是 32*16 个。不过由于 CUDA 是要透过 warp 的切换来隐藏 thread 的延迟、等待,来达到大量平行化的目的,所以会用所谓的 active thread 这个名词来代表一个 SM 里同时可以处理的 thread 数目。
  而在 block 的方面,一个 SM 可以同时处理多个 thread block,当其中有 block 的所有 thread 都处理完后,他就会再去找其他还没处理的 block 来处理。假设有 16 个 SM、64 个 block、每个 SM 可以同时处理三个 block 的话,那一开始执行时,device 就会同时处理 48 个 block;而剩下的 16 个 block 则会等 SM 有处理完 block 后,再进到 SM 中处理,直到所有 block 都处理结束。
  为一个多处理器指定了一个或多个要执行的线程块时,它会将其分成warp块,并由SIMT单元进行调度。将块分割为warp的方法总是相同的,每个warp都包含连续的线程,递增线程索引,第一个warp中包含全局线程过索引0-31。每发出一条指令时,SIMT单元都会选择一个已准备好执行的warp块,并将指令发送到该warp块的活动线程。Warp块每次执行一条通用指令,因此在warp块的全部32个线程执行同一条路径时,可达到最高效率。如果一个warp块的线程通过独立于数据的条件分支而分散,warp块将连续执行所使用的各分支路径,而禁用未在此路径上的线程,完成所有路径时,线程重新汇聚到同一执行路径下,其执行时间为各时间总和。分支仅在warp块内出现,不同的warp块总是独立执行的--无论它们执行的是通用的代码路径还是彼此无关的代码路径。
   建议的数值?
  在 Compute Capability 1.0/1.1 中,每个 SM 最多可以同时管理 768 个 thread(768 active threads)或 8 个 block(8 active blocks);而每一个 warp 的大小,则是 32 个 thread,也就是一个 SM 最多可以有 768 / 32 = 24 个 warp(24 active warps)。到了 Compute Capability 1.2 的话,则是 active warp 则是变为 32,所以 active thread 也增加到 1024。
  在这里,先以 Compute Capability 1.0/1.1 的数字来做计算。根据上面的数据,如果一个 block 里有 128 个 thread 的话,那一个 SM 可以容纳 6 个 block;如果一个 block 有 256 个 thread 的话,那 SM 就只能容纳 3 个 block。不过如果一个 block 只有 64 个 thread 的话,SM 可以容纳的 block 不会是 12 个,而是他本身的数量限制的 8 个。
  因此在 Compute Capability 1.0/1.1 的硬件上,决定 block 大小的时候,最好让里面的 thread 数目是 warp 数量(32)的倍数(可以的话,是 64 的倍数会更好);而在一个 SM 里,最好也要同时存在复数个 block。如果再希望能满足最多 24 个 warp 的情形下,block 里的 thread 数目似乎会是 96(一个 SM 中有 8 个 block)、128(一个 SM 中有 6 个 block)、192(一个 SM 中有 4 个 block)、256(一个 SM 中有 3 个 block) 这些数字了~
  Compute Capability 1.0/1.1 的硬件上,每个grid最多可以允许65535×65535个block。每个block最多可以允许512个thread,但是第三维上的最大值为64。而官方的建议则是一个 block 里至少要有 64 个 thread,192 或 256 个也是通常比较合适的数字(请参考 Programming Guide)。
  但是是否这些数字就是最合适的呢?其实也不尽然。因为实际上,一个 SM 可以允许的 block 数量,还要另外考虑到他所用到 SM 的资源:shared memory、registers 等。在 G80 中,每个 SM 有 16KB 的 shared memory 和 8192 个 register。而在同一个 SM 里的 block 和 thread,则要共享这些资源;如果资源不够多个 block 使用的话,那 CUDA 就会减少 Block 的量,来让资源够用。在这种情形下,也会因此让 SM 的 thread 数量变少,而不到最多的 768 个。
  比如说如果一个 thread 要用到 16 个 register 的话(在 kernel 中宣告的变量),那一个 SM 的 8192 个 register 实际上只能让 512 个 thread 来使用;而如果一个 thread 要用 32 个 register,那一个 SM 就只能有 256 个 thread 了~而 shared memory 由于是 thread block 共享的,因此变成是要看一个 block 要用多少的 shread memory、一个 SM 的 16KB 能分给多少个 block 了。
  所以虽然说当一个 SM 里的 thread 越多时,越能隐藏 latency,但是也会让每个 thread 能使用的资源更少。因此,这点也就是在优化时要做取舍的了。

cuda-Block和Grid设定相关推荐

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

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

  2. Cuda 程序设计中 Grid 和 Block 维度设置的注意事项

    1. Cuda 线程的 Grid 架构 Cuda 线程分为 Grid 和 Block 两个级别,Grid.Block.Thread 的关系如下图. 一个核函数目前只包括一个 Grid,也就是图中的 G ...

  3. 贤者之路,Cuda block内部矩阵求逆,mxm矩阵 复杂度为O(m)

    在做线性变换上经常要用到NXN的矩阵求逆.在CUDA用的是高斯消元比较适合并行计算. 下面是3X3Cuda实现矩阵求逆的Device函数,也就是说可以直接写到你的kernel函数上去.当然也可以是任何 ...

  4. CUDA学习----sp, sm, thread, block, grid, warp概念

    CUDA学习----sp, sm, thread, block, grid, warp概念 2017-01-11 17:14:28|  分类: HPC&CUDA优化 |  标签:cuda  g ...

  5. CUDA软件架构—网格(Grid)、线程块(Block)和线程(Thread)的组织关系以及线程索引的计算公式

    网格(Grid).线程块(Block)和线程(Thread)的组织关系 CUDA的软件架构由网格(Grid).线程块(Block)和线程(Thread)组成,相当于把GPU上的计算单元分为若干(2~3 ...

  6. CUDA编程之快速入门-----GPU加速原理和编程实现

    转载:https://www.cnblogs.com/skyfsm/p/9673960.html CUDA(Compute Unified Device Architecture)的中文全称为计算统一 ...

  7. CUDA精进之路(零):CUDA开篇

    前言 着手机器视觉项目时接触到了并行编程这一概念,那时候的目的是为了在图像识别的时候通过多个线程同时对多张传入的图片进行并行处理以达到加速程序运行速度,运用的方法主要是利用了C++自带的future库 ...

  8. CUDA编程(一) —— 相关概念基础知识

    CUDA(Compute Unified Device Architecture)的中文全称为计算统一设备架构.做图像视觉领域的同学多多少少都会接触到CUDA,毕竟要做性能速度优化,CUDA是个很重要 ...

  9. CUDA C++ Programming Guide( v11.2.0)部分翻译+笔记

    笔记对有些较为简单的部分做了省略,有些原文中表达比较拗口的地方,重新组织了话叙,由于部分内容并不是完全翻译,所以不建议作为主要学习资料,建议作为学习对比参考使用,如有不明白的地方或觉得有问题的地方,欢 ...

最新文章

  1. inline-block 和 float 的区别
  2. Java嵌套构造函数造成的stack overflow异常
  3. 跳板机连接数据库_跳板数据科学职业生涯回顾
  4. VIM之Project 项目管理工具
  5. PHP 基础篇 - PHP 中 DES 加解密详解
  6. TCP粘包问题分析和解决(全)
  7. python length-1_TypeError:使用基本操作时,只有length1数组可以转换为Python标量
  8. java 指令接口架构,JavaSE 基础大纲
  9. 如何在JAVA编程语言程序开发中更好的利用数据库中2两张表?
  10. 容器转换类型,列表,集合,字典推导式
  11. scala Trait及其与抽象类的比较
  12. C#中RestoreDirectory属性
  13. Okhttp之CacheInterceptor简单分析
  14. C语言复变函数PPT,复变函数的孤立点及其应用.doc
  15. Eclipse中文版之完美汉化教程(详细图解)
  16. OPPO三星苹果影像“硬碰硬”,没想到Reno6 Pro+夜拍竟略胜一筹
  17. 解决火狐浏览器提示连接不安全或证书错误的问题
  18. 把AS代码链接到fla文件
  19. jmeter(二十一)jmeter常用插件介绍
  20. Python与人工神经网络(5)——交叉熵成本函数

热门文章

  1. 研究生申请:就一个字
  2. 13.3的MacBook air 8g内存还是有点吃力
  3. 移动平台MOBA发热与帧率优化
  4. .NET和UNITY版本问题
  5. 【摘录】UNITY优化-有关骨骼数量的上限问题
  6. Redis过期策略及实现原理
  7. 带入gRPC:gRPC Streaming, Client and Server
  8. windows配置java运行环境
  9. LeadTools Android 入门教学——运行第一个Android Demo
  10. 关于C++默认拷贝构造函数产生的问题的讨论