前言

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

  • 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. css3动画功能介绍

    一:过渡动画---Transitions 含义:在css3中,Transitions功能通过将元素的某个属性从一个属性值在指定的时间内平滑过渡到另一个属性值来实现动画功能. Transitions属性 ...

  2. zookeeper&acticemq&redis&tomcat安装

    zookeeper安装  配置hosts  下载 wget http://apache.fayea.com/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar. ...

  3. CSS grid layout

      CSS网格布局用于将页面分割成数个主要区域,或者用来定义组件内部元素间大小.位置和图层之间的关系. 像表格一样,网格布局让我们能够按行或列来对齐元素. 但是,使用CSS网格可能还是比CSS表格更容 ...

  4. CSS3注意点

    1.background-Origin属性指定了背景图像的位置区域.content-box, padding-box,和 border-box区域内可以放置背景图像.注意:背景色是不起作用的 2.ba ...

  5. CAN总线优势

    CAN总线优势 RS-485基于R线构建的分布式控制系统而言, 基于CAN总线的分布式控制系统在以下方面具有明显的优越性: 首先,CAN控制器工作于多主方式,网络中 的各节点都可根据总线访问优先权(取 ...

  6. solr服务器搭建与Tomact整合及使用

    一:solr服务器的搭建 1:搭建全新的为solr专用的solr服务器: 在自己电脑上搭建两台Tomact服务器,一台仍为应用服务器,一台作为solr服务器,应用服务器按照正常Tomact服务器搭建即 ...

  7. Android“寄生兽”漏洞技术分析

    一.关于app的缓存代码 安卓的应用程序apk文件是zip压缩格式的文件,apk文件中包含的classes.dex文件相当于app的可执行文件,当app运行后系统会对classes.dex进行优化,生 ...

  8. ASP HUOSHAN VIDEO

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  9. 20155229《网络对抗技术》Exp5:MSF基础应用

    实验内容 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 一个主动攻击实践,如ms08-067; 一个针对浏览器的攻击,如ms11-050: 一个针对 ...

  10. 【转】CentOS 5 上安装git

    转自 http://www.cnblogs.com/Neddy/archive/2011/02/28/1967548.html 注意安装的时候 都要以root身份 //先安装git依赖的包 yum i ...