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. 下面我将随机抽取一名幸运女生,XXXXX

    个人在经过长久以来(约等于4小时)的奋战,终于实现了一个上课老师提问并抽奖的小程序.希望这个程序变得非常非常实用 课程的理解:在我的项目开始之前,先学习了一下UML项目类图的画法,和类与类之间的关系. ...

  2. Codeforces 550D —— Regular Bridge——————【构造】

     Regular Bridge time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  3. 级联sql

    select ID, PID, NAME,KEY from HS_DICT start with KEY = 'HS_EXP_WORK_LOCATION'connect by prior ID = P ...

  4. JavaScript使用Object.defineProperty方法实现双数据绑定

    Object.defineProperty这个方法非常值得学习,很多mvc框架中的双向数据绑定就是通过它来实现的. 本着互联网分享精神,今天我就将我自己的见解分享给大家,希望能有所帮助. 开始使用 O ...

  5. requirejs和seajs使用感受

    这几天看了下前端模块化的知识,主要是requirejs和seajs相关的知识,还未看es6的模块化知识. 由于目前项目组内的开始推广使用vue,并且开始简单的封装组件,但发现组件js的使用方式依然是原 ...

  6. html元素两种分类。替换元素和不可替换元素;块级元素和行内元素

    根据元素本身特点来分类: 替换元素替换元素根据其标签和属性来决定元素的具体显示内容.有<img><input><textarea><select>< ...

  7. linux免密登录ssh验证配置方法及常见错误解决

    目标:从服务器A免密登录服务器B [配置方法] 1.在服务器A生成密钥文件,直接使用以下命令: ssh-keygen 中间遇到输入内容一路回车即可,完成后会在 ~/.ssh 目录下生成两个文件:id_ ...

  8. 我的Chrome插件---纪录

    1.极简图床 写博客的时候用的上. 2.谷歌翻译 阅读英文文档直接选中翻译 3.OneTab 把当前网页集成一个tab,它有个好处就是,在写博客的时候,需要上不同的网站,写了一半有其他的事,这是可以集 ...

  9. [C]逗号运算符

    https://baike.baidu.com/item/%E9%80%97%E5%8F%B7%E8%BF%90%E7%AE%97%E7%AC%A6/7959271?fr=aladdin

  10. mysql中的find_in_set的使用

    原文 http://www.php-note.com/article/detail/383 举个例子来说: 有个文章表里面有个type字段,它存储的是文章类型,有 1头条.2推荐.3热点.4图文... ...