CUDA 3 ---- 线程配置

前言

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

  • 2D grid 2D block

线程索引

一般,一个矩阵以线性存储在global memory中的,并以行来实现线性:

在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_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[0]);
  // set up device
  int dev = 0;
  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 = 1<<14;
  int ny = 1<<14;
  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, 0, nBytes);
  memset(gpuRef, 0, 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 = 32;
  int dimy = 32;
  dim3 block(dimx, dimy);
  dim3 grid((nx+block.x-1)/block.x, (ny+block.y-1)/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 (0);
}

编译运行:

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

输出:

./a.out Starting...
Using Device 0: Tesla M2070
Matrix size: nx 16384 ny 16384
sumMatrixOnGPU2D <<<(512,512), (32,32)>>> 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

时间: 2024-12-24 05:54:30

CUDA 3 ---- 线程配置的相关文章

Linux平台CUDA+OpenCV3.4配置

前段时间,在TX2上装了OpenCV3.4,TX2更新源失败的问题,OpenCV内部很多函数都已经实现了GPU加速,但是我们手动写的函数,想要通过GPU加速就需要手动调用CUDA进行加速.下面介绍Linux平台的环境配置以及与OpenCV混合编译. Linux平台CUDA+OpenCV3.4配置 1 环境安装 首先需要安装OpenCV及CUDA环境安装,有TX2平台下OpenCV和CUDA参考百度.注意TX2自带了OpenCV2.14,如果需要安装高版本的OpenCV话需要注意多版本管理的问题.

CUDA安装及配置:Windows 7 64位环境

最近又有新的项目要做了,这次是关于CUDA---多核高性能计算的问题,所以最近一直在学习CUDA的编程问题,昨天安装软件完毕,运行第一个程序的时候还是遇到很多问题.所以这里给大家一起分享一下, 有和我一样初学CUDA的同志一起来吧. 安装 你需要的软件有四种: 其中,cuda的devdriver是不用安装的,当然,你可以下载最新版本安装一下. 然后就是下载,注意,你下载的所有的软件和你计算机上的VS所用的位数要匹配,例如,我的手提是64位的,VS也是64位的,所以我下载的软件都是64位的.(如果

Deep Learning 学习总结(一)&mdash;&mdash; Caffe Ubuntu14.04 CUDA 6.5 配置

Caffe (Convolution Architecture For Feature Extraction)作为深度学习CNN一个非常火的框架,对于初学者来说,搭建Linux下的Caffe平台是学习深度学习关键的一步,其过程也比较繁琐,回想起当初折腾的那几天,遂总结一下Ubuntu14.04的配置过程,方便以后新手能在此少走弯路. 1. 安装build-essentials 安装开发所需要的一些基本包 sudo apt-get install build-essential 2. 安装NVID

Tomcat6 内存和线程配置

1.修改启动时内存参数.并指定JVM时区 (在windows server 2008 下时间少了8个小时) 在Tomcat上运行j2ee项目代码时,经常会出现内存溢出的情况,解决办法是在系统参数中增加系统参数: window下, 在catalina.bat最前面 set JAVA_OPTS=-XX:PermSize=64M -XX:MaxPermSize=128m -Xms512m -Xmx1024m 一定加在catalina.bat最前面 即set "CURRENT_DIR=%cd%"

CUDA 计算线程索引的一般公式

CUDA thread index: int blockId = blockIdx.z * (gridDim.x*gridDim.y)                    + blockIdx.y * gridDim.x                    + blockIdx.x; int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)                      + threadIdx.z * (blo

theano+CUDA安装与配置

为了加深对深度学习算法的理解,打算跑一下几个经典的算法.LISA实验室有一个Python库Theano封装了常用的优化算法,用着非常方便.但是之前不了解Python,打算一点一点摸索. 下面说一下这两天搭建平台的过程,当然其中遇到了不少问题,但最后还是成功实现gpu运算. 首先要安装theano.theano的安装非常麻烦,因为其需要许多附属工具包,幸运的是,现在有许多开源的python平台已经集成好了这些常用的附属包.我使用的是AnacondaCE,下载安装后,再安装Windows insta

【软件安装与环境配置】ubuntu16.04+caffe+nvidia+CUDA+cuDNN安装配置

参考 1. ubuntu16.04+caffe+GPU+cuda+cudnn安装教程; 完 原文地址:https://www.cnblogs.com/happyamyhope/p/10592227.html

CUDA学习日志:windows开发环境配置

接触CUDA的时间并不长,最开始是在cuda-convnet的代码中接触CUDA代码,当时确实看的比较痛苦.最近得空,在图书馆借了本<GPU高性能编程 CUDA实战>来看看. Jeremy Lin 什么是CUDA CUDA(Compute Unified Device Architecture)是一种专门为提高并行程序开发效率而设计的计算架构.在构建高性能应用程序时,CUDA架构能充分发挥GPU的强大计算能力.更多的介绍,可以参考NVIDIA的ABOUT PAGE. CUDA开发环境配置 在开

Ubuntu 14.04 64位机上不带CUDA支持的Caffe配置编译操作过程

Caffe是一个高效的深度学习框架.它既可以在CPU上执行也可以在GPU上执行. 下面介绍在Ubuntu上不带CUDA的Caffe配置编译过程: 1.      安装BLAS:$ sudo apt-get install libatlas-base-dev 2.      安装依赖项:$ sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-devlibopencv-dev libboost-all-dev libhdf5-s