前言

线程的组织形式对程序的性能影响是至关重要的,本篇博文主要以下面一种情况来介绍线程组织形式:

  • 2D grid 2D block

线程索引

矩阵在memory中是row-major线性存储的:

在kernel里,线程的唯一索引非常有用,为了确定一个线程的索引,我们以2D为例:

  • 线程和block索引
  • 矩阵中元素坐标
  • 线性global memory 的偏移

首先可以将thread和block索引映射到矩阵坐标:

ix = threadIdx.x + blockIdx.x * blockDim.x

iy = threadIdx.y + blockIdx.y * blockDim.y

之后可以利用上述变量计算线性地址:

idx = iy * nx + ix

上图展示了block和thread索引,矩阵坐标以及线性地址之间的关系,谨记,相邻的thread拥有连续的threadIdx.x,也就是索引为(0,0)(1,0)(2,0)(3,0)...的thread连续,而不是(0,0)(0,1)(0,2)(0,3)...连续,跟我们线代里玩矩阵的时候不一样。

现在可以验证出下面的关系:

thread_id(2,1)block_id(1,0) coordinate(6,1) global index 14 ival 14

下图显示了三者之间的关系:

代码

int main(int argc, char **argv) {
  printf("%s Starting...\n", argv[]);
  // set up device
  int dev = ;
  cudaDeviceProp deviceProp;
  CHECK(cudaGetDeviceProperties(&deviceProp, dev));
  printf("Using Device %d: %s\n", dev, deviceProp.name);
  CHECK(cudaSetDevice(dev));   // set up date size of matrix
  int nx = <<;
  int ny = <<;
  int nxy = nx*ny;
  int nBytes = nxy * sizeof(float);
  printf("Matrix size: nx %d ny %d\n",nx, ny);

  // malloc host memory
  float *h_A, *h_B, *hostRef, *gpuRef;
  h_A = (float *)malloc(nBytes);
  h_B = (float *)malloc(nBytes);
  hostRef = (float *)malloc(nBytes);
  gpuRef = (float *)malloc(nBytes);
  
  // initialize data at host side
  double iStart = cpuSecond();
  initialData (h_A, nxy);
  initialData (h_B, nxy);
  double iElaps = cpuSecond() - iStart;
  memset(hostRef, , nBytes);
  memset(gpuRef, , nBytes);

  // add matrix at host side for result checks
  iStart = cpuSecond();
  sumMatrixOnHost (h_A, h_B, hostRef, nx,ny);
  iElaps = cpuSecond() - iStart;

  // malloc device global memory
  float *d_MatA, *d_MatB, *d_MatC;
  cudaMalloc((void **)&d_MatA, nBytes);
  cudaMalloc((void **)&d_MatB, nBytes);
  cudaMalloc((void **)&d_MatC, nBytes);
  
  // transfer data from host to device
  cudaMemcpy(d_MatA, h_A, nBytes, cudaMemcpyHostToDevice);
  cudaMemcpy(d_MatB, h_B, nBytes, cudaMemcpyHostToDevice);

  // invoke kernel at host side
  int dimx = ;
  int dimy = ;
  dim3 block(dimx, dimy);
  dim3 grid((nx+block.x-)/block.x, (ny+block.y-)/block.y);
  iStart = cpuSecond();
  sumMatrixOnGPU2D <<< grid, block >>>(d_MatA, d_MatB, d_MatC, nx, ny);
  cudaDeviceSynchronize();
  iElaps = cpuSecond() - iStart;
  printf("sumMatrixOnGPU2D <<<(%d,%d), (%d,%d)>>> elapsed %f sec\n", grid.x,
  grid.y, block.x, block.y, iElaps);

  // copy kernel result back to host side
  cudaMemcpy(gpuRef, d_MatC, nBytes, cudaMemcpyDeviceToHost);

  // check device results
  checkResult(hostRef, gpuRef, nxy);
  
  // free device global memory
  cudaFree(d_MatA);
  cudaFree(d_MatB);
  cudaFree(d_MatC);

  // free host memory
  free(h_A);
  free(h_B);
  free(hostRef);
  free(gpuRef);

  // reset device
  cudaDeviceReset();
  return ();
}

编译运行:

$ nvcc -arch=sm_20 sumMatrixOnGPU-2D-grid-2D-block.cu -o matrix2D
$ ./matrix2D

输出:

./a.out Starting...
Using Device : Tesla M2070
Matrix size: nx ny
sumMatrixOnGPU2D <<<(,), (,)>>> elapsed 0.060323 sec
Arrays match.

接下来,我们更改block配置为32x16,重新编译,输出为:

sumMatrixOnGPU2D <<<(512,1024), (32,16)>>> elapsed 0.038041 sec

可以看到,性能提升了一倍,直观的来看,我们会认为第二个配置比第一个多了一倍的block所以性能提升一倍,实际上也确实是因为block增加了。但是,如果你继续增加block的数量,则性能又会降低:

sumMatrixOnGPU2D <<< (1024,1024), (16,16) >>> elapsed 0.045535 sec

下图展示了不同配置的性能;

关于性能的分析将在之后的博文中总结,现在只是了解下,本文在于掌握线程组织的方法。

代码下载:CodeSamples.zip

CUDA ---- 线程配置的更多相关文章

  1. 最优的cuda线程配置

    1 每个SM上面失少要有192个激活线程,寄存器写后读的数据依赖才能被掩盖   2 将 寄存器 的bank冲突降到最低,应尽量使每个block含有的线程数是64的倍数   3 block的数量应设置得 ...

  2. GPU编程自学2 —— CUDA环境配置

    深度学习的兴起,使得多线程以及GPU编程逐渐成为算法工程师无法规避的问题.这里主要记录自己的GPU自学历程. 目录 <GPU编程自学1 -- 引言> <GPU编程自学2 -- CUD ...

  3. Tomcat 内存和线程配置优化

    1. tomcat 的线程配置参数详情如下: 修改conf/server.xml中的<Connector .../> 节点如下: <Connector port="8080 ...

  4. 十五、springboot集成定时任务(Scheduling Tasks)(二)之(线程配置)

    配置类: /** * 定时任务线程配置 * */ @Configuration public class SchedulerConfig implements SchedulingConfigurer ...

  5. 【深度学习】在linux和windows下anaconda+pycharm+tensorflow+cuda的配置

    在linux和windows下anaconda+pycharm+tensorflow+cuda的配置 在linux和windows下anaconda+pycharm+tensorflow+cuda的配 ...

  6. OpenCV GPU CUDA OpenCL 配置

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

  7. CUDA学习笔记(二)——CUDA线程模型

    转自:http://blog.sina.com.cn/s/blog_48b9e1f90100fm5b.html 一个grid中的所有线程执行相同的内核函数,通过坐标进行区分.这些线程有两级的坐标,bl ...

  8. GPU(CUDA)学习日记(十一)------ 深入理解CUDA线程层次以及关于设置线程数的思考

    GPU线程以网格(grid)的方式组织,而每个网格中又包含若干个线程块,在G80/GT200系列中,每一个线程块最多可包含512个线程,Fermi架构中每个线程块支持高达1536个线程.同一线程块中的 ...

  9. 【CUDA】Win10 + VS2017新 CUDA 项目配置

    一.新建项目 打开VS2017 → 新建项目 → Win32控制台应用程序 → “空项目”打钩 二.调整配置管理器平台类型 右键项目 → 属性 → 配置管理器 → 全改为“x64” 三.配置生成属性 ...

随机推荐

  1. PAT B1040 有几个PAT (25 分)

    字符串 APPAPT 中包含了两个单词 PAT,其中第一个 PAT 是第 2 位(P),第 4 位(A),第 6 位(T):第二个 PAT 是第 3 位(P),第 4 位(A),第 6 位(T). 现 ...

  2. (二) DRF 视图

    DRF中的Request 在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等. 比如,区别于Dj ...

  3. Exp7

    实验内容 简单应用SET工具建立冒名网站 kali IP: 192.168.1.160 (原198) win7 IP: 192.168.1.199 1.开启本机Apache服务 (1)查看80端口是否 ...

  4. # 2017-2018-2 20155319『网络对抗技术』Exp7:网络欺诈防范

    2017-2018-2 20155319『网络对抗技术』Exp7:网络欺诈防范 一.原理与实践说明 1.实践目标 本实践的目标是:理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法. 2. ...

  5. 腾讯云CVM服务器怎么建网站

    腾讯云云服务器CVM站在用户的角度看就相当于一台计算机,虽然实际上它是一个虚拟服务器,是一个大的云端服务器集群虚拟出来的一个虚拟服务器,在使用上直接当做一个实际的服务器即可.那么,对于一个新手菜鸟来说 ...

  6. Ms.office2010安装教程

    下面用到的软件下载地址如下:http://pan.baidu.com/s/1c08cxPI 第一步 1. 将压缩包office2010.rar解压解压后,会出现一个office2010文件夹如图1.1 ...

  7. JMeter的下载安装以及运行教程

    一.安装JMeter的必要准备 1.安装JDK JDK下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index.html ...

  8. springboot 前后端分离开发 从零到整(一、环境的搭建)

    第一次写文章,有什么错误地方请大家指正,也请大家见谅. 这次为大家分享我做毕业设计的一个过程,之前没有接触过springboot,一直做的都是Javaweb和前端,做了几个前后端分离的项目.现在听说s ...

  9. 菜鸟凉经(华为、firehome、大华)

    面试通知都是前一天来的,准备的时间很少,所以表现也不是特别满意,来看面经吧: 华为一面(IT应用工程师): 1.自我介绍:(华为面试都是1对1,面前的是个温柔的小哥,挺放松的) 2.你主要会的it技术 ...

  10. 详细聊聊k8s deployment的滚动更新(二)

    一.知识准备 ● 本文详细探索deployment在滚动更新时候的行为 ● 相关的参数介绍:   livenessProbe:存活性探测.判断pod是否已经停止   readinessProbe:就绪 ...