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. C指针总结

    取内容* 从右至左 取地址& 从右至左 同类型指针变量关系运算是有意义的. 指针变量和数组名都表示数组的地址,但是数组名是地址常量. *p++和(*p)++不同.*p++的赋值结果跟*p相同, ...

  2. springboot jpa 多条件查询(单表)

    需要实现的功能: 多个搜索输入框:全部不填,则查出所有列表:填了条件,就按条件查找:填的条件个数不定. 方法实现的核心:jpa自带的Specification<T> (目前只需要单表,多表 ...

  3. python监控linux内存并写入mongodb

    (需要安装psutil 用来获取服务器资源,以及pymongo驱动)#pip install psutil #pip install pymongo #vim memory_monitory.py 文 ...

  4. 五、cent OS防火墙常用命令

    查看防火墙开闭状态systemctl status firewalld 开启防火墙systemctl start firewalld 关闭防火墙systemctl stop firewalld 查看已 ...

  5. jmeter简单使用示例

    1.下载后解压,运行bin目录下的jmeter.bat 2.add ThreadGroup 3.add request 4.add listener

  6. git记住提交密码的技巧

    修改.git包里面的config文件,添加 [credential] helper = store

  7. jdk动态代理与cglib代理、spring Aop代理原理-代理使用浅析

    原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...

  8. linux系统下php扩展的安装

    0. 这里以php安装redis扩展为例 1. 首先下载并解压redis扩展包 [root@xxx ~]# cd /usr/local/src [root@xxx src]# wget https:/ ...

  9. Javascript 多物体淡入淡出(透明度变化)

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  10. 广告点击率预测(CTR) —— 在线学习算法FTRL的应用

    FTRL由google工程师提出,在13的paper中给出了伪代码和实现细节,paper地址:http://www.eecs.tufts.edu/~dsculley/papers/ad-click-p ...