前面扯了很多,不过大多都是在讲CUDA 在软体层面的东西;接下来,虽然Heresy 自己也不熟,不过还是来研究一下硬体的部分吧~毕竟要最佳化的时候,好像还是要大概知道一下相关的东西的。这部分主要参考资料是:

在研究硬体架构前,可能须要先回去看《nVidia CUDA简介》,稍微回顾一下在CUDA中thread、thread block、block grid的意义:一个CUDA的平行化的程式会被以许多个thread来执行,数个thread会被群组成一个block,而多个thread
block则会再构成grid。也就是一个kernel程式会有一个grid,grid底下有数个block,每个block都是一群thread的群组。而在同一个block中的thread可以透过shared memory来沟通,也可以同步。

硬体基本架构

实际上在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 都处理结束。

建议的数值?

在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)这些数字了~ 

而官方的建议则是一个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能使用的资源更少。因此,这点也就是在最佳化时要做取舍的了。

转自:

http://kheresy.wordpress.com/2008/07/09/cuda-%E7%9A%84-threading%EF%BC%9Ablock-%E5%92%8C-grid-%E7%9A%84%E8%A8%AD%E5%AE%9A%E8%88%87-warp/


【并行计算-CUDA开发】CUDA软件架构与Nvidia硬件对应关系的更多相关文章

  1. CUDA开发 - CUDA 版本

    "CUDA runtime is insufficient with CUDA driver"CUDA 9.2: 396.xx CUDA 9.1: 387.xx CUDA 9.0: ...

  2. 【并行计算与CUDA开发】英伟达硬件加速编解码

    硬件加速 并行计算 OpenCL OpenCL API VS SDK 英伟达硬件编解码方案 基于 OpenCL 的 API 自己写一个编解码器 使用 SDK 中的编解码接口 使用编码器对于 OpenC ...

  3. 【并行计算-CUDA开发】英伟达硬件解码器分析

    这篇文章主要分析 NVCUVID 提供的解码器,里面提到的所有的源文件都可以在英伟达的 nvenc_sdk 中找到. 解码器的代码分析 SDK 中的 sample 文件夹下的 NvTranscoder ...

  4. 【并行计算与CUDA开发】英伟达硬件加速解码器在 FFMPEG 中的使用

    目录(?)[-] 私有驱动 编译 FFMPEG 使用 nvenc 这篇文档介绍如何在 ffmpeg 中使用 nvenc 硬件编码器. 私有驱动 nvenc 本身是依赖于 nvidia 底层的私有驱动的 ...

  5. 【视频开发】【CUDA开发】FFMPEG硬件加速-nvidia方案

    1.目标 <1>显卡性能参数: <2>方案可行性: 2.平台信息 2.1.查看当前显卡信息 命令:  lspci |grep VGA  信息:  01:00.0 VGA com ...

  6. 【视频开发】【CUDA开发】ffmpeg Nvidia硬件加速总结

    原文链接:https://developer.nvidia.com/ffmpeg GPU-accelerated video processing integrated into the most p ...

  7. 【并行计算-CUDA开发】有关CUDA当中global memory如何实现合并访问跟内存对齐相关的问题

    ps:这是英伟达二面面的一道相关CUDA的题目.<NVIDIA CUDA编程指南>第57页开始          在合并访问这里,不要跟shared memory的bank conflic ...

  8. 【CUDA开发】CUDA的安装、Nvidia显卡型号及测试

    说明:想要让Theano在Windows8.1下能利用GPU并行运算,必须有支持GPU并行运算的Nvidia显卡,且要安装CUDA,千万不要电脑上是Intel或AMD的显卡,却要编写CUDA. 文中用 ...

  9. Windows平台CUDA开发之前的准备工作

    CUDA是NVIDIA的GPU开发工具,眼下在大规模并行计算领域有着广泛应用. windows平台上面的CUDA开发之前.最好去NVIDIA官网查看说明,然后下载对应的driver. ToolKits ...

随机推荐

  1. SpringBoot集成Druid实现监控

    application.properties文件完整信息 #连接数据库 spring.datasource.driver-class-name=org.mariadb.jdbc.Driver spri ...

  2. nginx静态资源配置(转发)

    传统的web项目,一般都将静态资源存放在 webroot的目录下,这样做很方便获取静态资源,但是如果说web项目很大,用户很多,静态资源也很多时,服务器的性能 或许就会很低下了.这种情况下一般都会需要 ...

  3. HDU 6102 - GCDispower | 2017 Multi-University Training Contest 6

    个人感觉题解的复杂度很玄,参不透,有没有大佬讲解一下- - /* HDU 6102 - GCDispower [ 数论,树状数组] | 2017 Multi-University Training C ...

  4. 用CSS实现梯形图标

    遇到需要实现如下图标 由图形分析,梯形,平行四边形等都可以由矩形变形而来. 而想要实现梯形,需要进行3D变换,需要使用css3的 perspective属性. 属性 perspective指定了观察者 ...

  5. 2018CCPC桂林站JStone Game

    题目描述 Alice and Bob are always playing game! The game today is about taking out stone from the stone ...

  6. 【luoguP1182】数列分段 Section II

    题目描述 对于给定的一个长度为N的正整数数列A-i,现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列4 2 4 5 1要分成3段 将其如下分段: [4 ...

  7. kubernetes 的configMap和sercet配置信息

    简介: 启动pod,pod启动时可以将configMap资源关联到当前pod上来,从中读一个数据c传递给pod内的容器的一个变量.任然是变量注入的方式来给容器传配置信息. 把每一个configMap当 ...

  8. 6.RabbitMQ--事物

    RabbitMQ之消息确认机制 如何防止消息丢失? 如何防止消息是否正确送达? 有些业务场景需要我们对于消息的幂等性要求是比较高的,需要消息不能丢失,在使用RabbitMQ的时候,我们可以通过消息持久 ...

  9. Python中的变量、对象

    由于没时间系统学习下Python 只能见一个问题探究一个问题了 一.初级 - 对象 关于Python中的数据类型,今天重新认识了下.[参考] 首先,Python中,对象才有类型, 变量是没有类型的,它 ...

  10. MySQL5.7 创建及查看数据库

    1.创建数据库语句create database语句是在MySQL实例上创建一个指定名称的数据库.create schema语句的语义和create database是一样的. 2.语法解析 CREA ...