http://blog.csdn.net/canhui_wang/article/details/51730264

摘要

本文主要讲述CUDA的threadIdx。

1. Grid,Block和Thread三者的关系

其中,一个grid包含多个blocks,这些blocks的组织方式可以是一维,二维或者三维。任何一个block包含有多个Threads,这些Threads的组织方式也可以是一维,二维或者三维。举例来讲:比如上图中,任何一个block中有10个Thread,那么,Block(0,0)的第一个Thread的ThreadIdx是0,Block(1,0)的第一个Thread的ThreadIdx是11;Block(2,0)的第一个Thread的ThreadIdx是21,......,依此类推,不难整理出其中的映射公式(表达式已在代码中给出)。

2. GridID,BlockID,ThreadID三者的关系

ThreadID是线性增长的,其目的是用于在硬件和软件上唯一标识每一个线程。CUDA程序中任何一个时刻,每一个线程的ThreadIdx都是特定唯一标识的!grid,block的划分方式不同,比如一维划分,二维划分,或者三维划分。显然,Threads的唯一标识ThreadIdx的表达方式随着grid,block的划分方式(或者说是维度)而不同。下面通过程序给出ThreadIdx的完整的表达式。其中,由于使用的时候会考虑到GPU内存优化等原因,代码可能也会有所不同,但是threadId的计算的表达式是相对固定的。

  1. /**************************************************************/
  2. // !!!!!!!!!!!!!!注意!!!!!!!!!!!!!!!!
  3. /**************************************************************/
  4. // grid划分成a维,block划分成b维,
  5. // 等价于
  6. // blocks是a维的,Threads是b维的。
  7. // 这里,本人用的是第一中说法。
  8. /**************************************************************/
  9. // 情况1:grid划分成1维,block划分为1维。
  10. __device__ int getGlobalIdx_1D_1D() {
  11. int threadId = blockIdx.x *blockDim.x + threadIdx.x;
  12. return threadId;
  13. }
  14. // 情况2:grid划分成1维,block划分为2维。
  15. __device__ int getGlobalIdx_1D_2D() {
  16. int threadId = blockIdx.x * blockDim.x * blockDim.y
  17. + threadIdx.y * blockDim.x + threadIdx.x;
  18. return threadId;
  19. }
  20. // 情况3:grid划分成1维,block划分为3维。
  21. __device__ int getGlobalIdx_1D_3D() {
  22. int threadId = blockIdx.x * blockDim.x * blockDim.y * blockDim.z
  23. + threadIdx.z * blockDim.y * blockDim.x
  24. + threadIdx.y * blockDim.x + threadIdx.x;
  25. return threadId;
  26. }
  27. // 情况4:grid划分成2维,block划分为1维。
  28. __device__ int getGlobalIdx_2D_1D() {
  29. int blockId = blockIdx.y * gridDim.x + blockIdx.x;
  30. int threadId = blockId * blockDim.x + threadIdx.x;
  31. return threadId;
  32. }
  33. // 情况5:grid划分成2维,block划分为2维。
  34. __device__ int getGlobalIdx_2D_2D() {
  35. int blockId = blockIdx.x + blockIdx.y * gridDim.x;
  36. int threadId = blockId * (blockDim.x * blockDim.y)
  37. + (threadIdx.y * blockDim.x) + threadIdx.x;
  38. return threadId;
  39. }
  40. // 情况6:grid划分成2维,block划分为3维。
  41. __device__ int getGlobalIdx_2D_3D() {
  42. int blockId = blockIdx.x + blockIdx.y * gridDim.x;
  43. int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)
  44. + (threadIdx.z * (blockDim.x * blockDim.y))
  45. + (threadIdx.y * blockDim.x) + threadIdx.x;
  46. return threadId;
  47. }
  48. // 情况7:grid划分成3维,block划分为1维。
  49. __device__ int getGlobalIdx_3D_1D() {
  50. int blockId = blockIdx.x + blockIdx.y * gridDim.x
  51. + gridDim.x * gridDim.y * blockIdx.z;
  52. int threadId = blockId * blockDim.x + threadIdx.x;
  53. return threadId;
  54. }
  55. // 情况8:grid划分成3维,block划分为2维。
  56. __device__ int getGlobalIdx_3D_2D() {
  57. int blockId = blockIdx.x + blockIdx.y * gridDim.x
  58. + gridDim.x * gridDim.y * blockIdx.z;
  59. int threadId = blockId * (blockDim.x * blockDim.y)
  60. + (threadIdx.y * blockDim.x) + threadIdx.x;
  61. return threadId;
  62. }
  63. // 情况9:grid划分成3维,block划分为3维。
  64. __device__ int getGlobalIdx_3D_3D() {
  65. int blockId = blockIdx.x + blockIdx.y * gridDim.x
  66. + gridDim.x * gridDim.y * blockIdx.z;
  67. int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)
  68. + (threadIdx.z * (blockDim.x * blockDim.y))
  69. + (threadIdx.y * blockDim.x) + threadIdx.x;
  70. return threadId;
  71. }

3. GPU Threads与CPU Threads的比较

GPU Threads的生成代价小,是轻量级的线程;CPU Threads的生成代价大,是重量级的线程。CPU Threads虽然生成的代价高于GPU Threads,但其执行效率高于GPU Threads,所以GPU Threads无法在个体的比较上取胜,只有在数量上取胜。在这个意义上来讲,CPU Threads好比是一头强壮的公牛在耕地,GPU Threads好比是1000头弱小的小牛在耕地。因此,为了保证体现GPU并行计算的优点,线程的数目必须足够多,通常至少得用上1000个GPU线程或者更多才够本,才能很好地体现GPU并行计算的优点!

4. GPU Threads的线程同步

线程同步是针对同一个block中的所有线程而言的,因为只有同一个block中的线程才能在有效的机制中共同访问shared memory。要知道,由于每一个Thread的生命周期长度是不相同的,Thread对Shared Memory的操作可能会导致读写的不一致,因此需要线程的同步,从而保证该block中所有线程同时结束。

GPU CUDA之——深入理解threadIdx的更多相关文章

  1. GPU,CUDA,cuDNN的理解

    最近用到这方面的知识,感觉这篇文章写的很好,为了方便自己查阅,就搬运了过来,如果牵涉到侵权,请联系我,我会删除该博文!!! 我们知道做深度学习离不开GPU,不过一直以来对GPU和CPU的差别,CUDA ...

  2. 真实机下 ubuntu 18.04 安装GPU +CUDA+cuDNN 以及其版本选择(亲测非常实用)【转】

    本文转载自:https://blog.csdn.net/u010801439/article/details/80483036 ubuntu 18.04 安装GPU +CUDA+cuDNN : 目前, ...

  3. GPU CUDA编程中threadIdx, blockIdx, blockDim, gridDim之间的区别与联系

    前期写代码的时候都会困惑这个实际的threadIdx(tid,实际的线程id)到底是多少,自己写出来的对不对,今天经过自己一些小例子的推敲,以及找到官网的相关介绍,总算自己弄清楚了. 在启动kerne ...

  4. [GPU] CUDA for Deep Learning, why?

    又是一枚祖国的骚年,阅览做做笔记:http://www.cnblogs.com/neopenx/p/4643705.html 这里只是一些基础知识.帮助理解DL tool的实现. 最新补充:我需要一台 ...

  5. OpenCV GPU CUDA OpenCL 配置

    首先,正确安装OpenCV,并且通过测试. 我理解GPU的环境配置由3个主要步骤构成. 1. 生成关联文件,即makefile或工程文件 2. 编译生成与使用硬件相关的库文件,包括动态.静态库文件. ...

  6. GPU CUDA 经典入门指南

    转自:http://luofl1992.is-programmer.com/posts/38830.html CUDA编程中,习惯称CPU为Host,GPU为Device.编程中最开始接触的东西恐怕是 ...

  7. GPU/CUDA程序初体验 向量加法

    现在主要的并行计算设备有两种发展趋势: (1)多核CPU. 双核,四核,八核,...,72核,...,可以使用OpenMP编译处理方案,就是指导编译器编译为多核并行执行. (2)多线程设备(GP)GP ...

  8. ubuntu16.04+caffe+GPU+cuda+cudnn安装教程

    步骤简述: 1.安装GPU驱动(系统适配,不采取手动安装的方式) 2.安装依赖(cuda依赖库,caffe依赖) 3.安装cuda 4.安装cudnn(只是复制文件加链接,不需要编译安装的过程) 5. ...

  9. GPU && CUDA:主机和设备间数据传输测试

    数据传输测试,先从主机传输到设备,再在设备内传输,再从设备传输到主机. H-->D D-->D D-->H // moveArrays.cu // // demonstrates C ...

随机推荐

  1. 深入理解JavaScript系列(42):设计模式之原型模式

    介绍 原型模式(prototype)是指用原型实例指向创建对象的种类,并且通过拷贝这些原型创建新的对象. 正文 对于原型模式,我们可以利用JavaScript特有的原型继承特性去创建对象的方式,也就是 ...

  2. [转].NET Core dotnet 命令大全

    本文转自:http://www.cnblogs.com/linezero/p/dotnet.html https://docs.microsoft.com/en-us/dotnet/articles/ ...

  3. BDD框架之Cucumber研究

    BDD框架之Cucumber研究 引用链接:http://kongqingyun123.blog.163.com/blog/static/6377283520134158437813/ Cucumbe ...

  4. 一分钟认识:Cucumber框架

    一分钟认识:Cucumber框架(一) 转自:https://www.cnblogs.com/dami520/p/3168864.html 个人感觉这个框架非常适合UI自动化测试,他不仅能把用例中的测 ...

  5. java中list、set、map区别(转)

    Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap└WeakHashMap Collecti ...

  6. 使用多说评论&加网分享

    多说评论: <div data-thread-key=" class="ds-thread"></div><script>var du ...

  7. Java集合 之List(ArrayList、LinkedList、Vector、Stack)理解(new)

    一. ArrayList底层实现原理 对比 和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOn ...

  8. Scrapy框架的使用

    Scrapy框架的安装 pip install pywin32 下载 Twisted 包       pip install Twisted包的路径 pip insatll scrapy Scrapy ...

  9. Linux基础之-元字符

    Bash中的特殊字符,键盘上能敲出来的特殊字符都有其特殊意义,强调一点:元字符是被shell解释的. 1. '',取命令的执行结果 [root@MiWiFi-R3-srv ~]# ls4.txt an ...

  10. Codeforces Round #412 A Is it rated ?

    A. Is it rated? time limit per test  2 seconds memory limit per test  256 megabytes Is it rated? Her ...