前面扯了很多,不过大多都是在讲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. spark_rdd 一波怼完面试官系列

    Resilient Distributed dataset , 弹性分布式数据集. 分布式内存的抽象使用,实现了以操作本地集合的方式来操作分布式数据集的抽象实现. RDD是Spark最核心的东西,它表 ...

  2. HDU 6070 - Dirt Ratio | 2017 Multi-University Training Contest 4

    比赛时会错题意+不知道怎么线段树维护分数- - 思路来自题解 /* HDU 6070 - Dirt Ratio [ 二分,线段树 ] | 2017 Multi-University Training ...

  3. 记录 vant Picker 选择器,实现三级联动,传对应省市区code值

    最近使用vant UI写移动端,感觉还不错 功能挺全的,带的还有省市区三级联动. 但是 突然遇到一个 产品要传的 省市区的code码,还和vant的 邮编不一样,我*****. 看了一下vant UI ...

  4. FPGA数据舍入方式

    1,在Verilog代码中,常用的代码写法为直接截位: 2,在Vivado的IP核中常见的两种舍入方式为Truncation和Rounding, 3,在Matlab中常见的四种舍入函数为floor, ...

  5. encodeURI()、encodeURIComponent()、escape()

    URI的通用格式如下: /*** 协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数1=值1&参数2=值2+值3#标志 **/ /*** http://use ...

  6. 路由器配置——基于区域的OSPF简单认证

    一.实验目的:掌握区域的OSPF简单认证 二.拓扑图: 三.具体步骤配置: (1)R1路由器配置 Router>enable Router#configure terminal Enter co ...

  7. Java进阶知识09 Hibernate一对多单向关联(Annotation+XML实现)

    1.Annotation 注解版 1.1.在一的一方加Set 1.2.创建Customer类和Order类 package com.shore.model; import java.util.Hash ...

  8. 【CUDA 基础】6.1 流和事件概述

    title: [CUDA 基础]6.1 流和事件概述 categories: - CUDA - Freshman tags: - 流 - 事件 toc: true date: 2018-06-10 2 ...

  9. 安装mongodb-window10版

    第一.下载mongodb 官方地址:https://www.mongodb.com/ 第二步mongodb安装 运行mongodb-win32-x86_64-2008plus-ssl-v3.4-lat ...

  10. LG2216 理想的正方形

    题意 有一个\(a \times b\)的整数组成的矩阵,现请你从中找出一个\(n \times n\)的正方形区域,使得该区域所有数中的最大值和最小值的差最小 思路 对于每一列,都用两个单调队列维护 ...