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. [android] 界面切换的核心方法

    根据效果图拆分界面 主体部分 View ==> ViewGroup ==> RelativeLayout,主体部分使用RelativeLayout作为占位 View和ViewGroup的区 ...

  2. Hibernate学习1--对象持久化的思想

    前些天开始接触hibernate,想想以前直接用c3p0进行笨拙而繁杂的数据库操作就觉得生无可恋了,也正因如此,在刚刚接触hibernate的我,便强烈地喜欢上这种偷懒而优雅的面向对象式操作数据库的方 ...

  3. SQL练习(一)

    查找今天过生日的同学 这里表中已经存储了生日,所以思路是取出date_birth去今天的日期相比较 SELECT NAME,date_birth FROM org_mhi_studentfiles W ...

  4. POJ 2923(状态集合背包)

    http://www.cnblogs.com/kuangbin/archive/2012/09/14/2685430.html #include <iostream> #include & ...

  5. spring和jdbc结合的一个小例子

    1.新建一个SpringJdbc的maven项目. 2.引入需要的jar包的依赖 <span style="white-space:pre"> </span> ...

  6. jQuery filter() , end()

    1. jquery filter(condition) :  过滤指定对象中符合条件的元素: 2.  jquery  end() : 回到原来的操作对象 3.  example : <body& ...

  7. hdu 4513 吉哥系列故事——完美队形II (manachar算法)

    吉哥系列故事——完美队形II Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) P ...

  8. codeforces之始

    很早就听说acmer界的CF嘞!还记得刚开始听到神犇们在讨论CF的时候我还以为是网游CF(穿越火线)呢... 今年刚开学的时候就打算开始打cf的,由于一些事情耽搁了.之后又要准备省赛所以就一直拖到现在 ...

  9. Winform访问本地SQLServer数据库文件

    Winform访问本地SQLServer数据库文件 1.项目中添加config配置,如下: <configuration> <connectionStrings> <ad ...

  10. linux常用命令(50个)

    1. find 基本语法参数如下: find [PATH] [option] [action] # 与时间有关的参数: -mtime n : n为数字,意思为在n天之前的“一天内”被更改过的文件: - ...