转自: http://blog.csdn.net/augusdi/article/details/12529247

CUDA编程模型
  1. CUDA编程模型将CPU作为主机,GPU作为协处理器(co-processor)或设备。在这个模型中,CPU负责逻辑性强的事务处理和串行计算,GPU则专注于高度线程化的并行处理任务。CPU、GPU各自拥有相互独立的存储器地址空间。
  2. 一旦确定了程序中的并行部分,就可以考虑把这部分计算工作交给GPU。
  3. kernel:运行在GPU上的C函数称为kernel。一个kernel函数并不是一个完整的程序,而是整个CUDA程序中的一个可以被并行执行的步骤。当调用时,通过N个不同的CUDA线程执行N次。
  4. 一个完整的CUDA程序是由一系列的设备端kernel函数并行步骤和主机端的串行处理步骤共同组成的。
  5. 一个kernel函数中存在两个层次的并行,即Grid中的block间并行和block中的thread间并行。
硬件映射
 
计算单元
  1. 计算核心:GPU中有多个流多处理器(Stream Multiprocessor, SM),流多处理器即计算核心。每个流多处理器又包含8个标量流处理器(Stream Processor),以及少量的其他计算单元。SP 只是执行单元,并不是完整的处理核心。拥有完整前端的处理核心,必须包含取指、解码、分发逻辑和执行单元。隶属同一 SM 的8个 SP共用一套取指与射单元,也共用一块共享存储器。
  2. CUDA 中的 kernel 函数是以 block 为单元执行的,同一 block 中的线程需要共享数据,因此必须在同一个 SM 中发射,而 block 中的每一个 thread 则被送到一个 SP 上执行
  3. 一个 block 必须被分配到一个 SM 中,但一个 SM 中同一时刻可以有多个活动线程块(active block)在等待执行,即在一个 SM 中可同时存在多个 block 的上下文。在一个 SM 中放入多个线程块是为了隐藏延迟(latency),更好地利用执行单元的资源。当一个 block 进行同步或访问显存等高延迟操作时,另一个 block 就可以“乘虚而入”,占用 GPU 执行资源。
  4. 限制 SM 中活动线程块数量的因素包括:SM中的活动线程块数量不超过 8 个;所有活动线程块中的 warp 数之和在计算能力 1.0/1.1 设备中不超过 24,在计算能力 1.2/1.3 设备中不超过 32;所有活动线程块使用的寄存器和存储器之和不超过 SM 中的资源限制。
线程结构(Thread Hierarchy)
  1. CUDA中以线程网格(Grid)的形式组织,每个线程网格由若干个线程块(block)组成,而每个线程块又由若干个线程(thread)组成
  2. threadIdx:CUDA中使用了dim3类型的内建变量threadIdx和blockIdx。threadIdx是一个包含3个组件的向量,这样线程可以用一维、二维或三维线程索引进行识别,从而形成一个一维、二维或三维线程块。一个线程的索引和它的线程ID之间的关系非常直接:
    1. 对于一个一维的块,线程的threadIdx就是threadIdx.x;
    2. 对于一个二维的大小为(Dx,Dy)的块,线程的threadIdx就是(threadIdx.x + threadIdx.y * Dx);
    3. 对于一个三维的大小为(Dx,Dy,Dz)的块,线程的threadIdx是(threadIdx.x + threadIdx.y * Dx + threadIdx.z * Dx * Dy)。
  3. 一个block中的线程数量不能超过512个。
  4. 在同一个block中的线程可以进行数据通信。CUDA中实现block内通信的方法是:在同一个block中的线程通过共享存储器(shared memory)交换数据,并通过栅栏同步保证线程间能够正确地共享数据。具体来说,可以在kernel函数中需要同步的位置调用__syncthreads()函数。
  5. 一个block中的所有thread在一个时刻执行指令并不一定相同。例如,在一个block中可能存在这样的情况:有些线程已经执行到第20条指令,而这时其他的线程只执行到第8条指令的第21条语句的位置通过共享存储器共享数据,那么只执行到第8条语句的线程中的数据可能还没来得及更新,就被交给其他线程去处理了,这会导致错误的计算结构。而调用__syncthreads()函数进行栅栏同步(barrier)以后,就可以确保只有当block中的每个线程都运行到第21条指令以后,程序才会继续向下进行。
  6. 每个线程块中的线程数量、共享存储器大小和寄存器数量都要受到处理核心硬件资源的限制,其原因是:
    1. 在GPU中,共享存储器与执行单元的物理距离必须很小,处于同一个处理核心中,以使得共享存储器的延迟尽可能小,从而保证线程块中的各个线程能够有效协作。
    2. 为了在硬件上用很小的代价就能实现__syncthreads()函数,一个block中所有线程的数据都必须交由同一处理核心进行处理。
Kernel函数的定义与调用
 
  1. 内核函数必须通过__global__函数类型限定符定义,并且只能在主机端代码中调用。在调用时,必须声明内核函数的执行参数。例如:
  2. // Define kernel
    __global__ void VecAdd(float * A, float * B, float * C)
    {
    int i = threadIdx.x;
    C[i] = A[i] + B[i];
    }
     
    int main
    {
    // Call kernel
    VecAdd<<<1, N>>>(A, B, C);
    }
  3. 必须先为Kernel中用到的数组或变量分配好足够的空间,再调用kernel函数。否则,在GPU计算时会发生错误。
  4. 在设备端运行的线程之间是并行执行的,其中的每个线程按指令的顺序串行执行一次kernel函数。每一个线程有自己的block ID和thread ID用于与其他线程相区分。block ID和thread ID只能在kernel中通过内建变量访问。内建变量是由设备中的专用寄存器提供的,是只读的,且只能在GPU端的kernel函数中调用。

cuda编程基础的更多相关文章

  1. CUDA编程

    目录: 1.什么是CUDA 2.为什么要用到CUDA 3.CUDA环境搭建 4.第一个CUDA程序 5. CUDA编程 5.1. 基本概念 5.2. 线程层次结构 5.3. 存储器层次结构 5.4. ...

  2. CUDA编程-(1)Tesla服务器Kepler架构和万年的HelloWorld

    结合CUDA范例精解以及CUDA并行编程.由于正在学习CUDA,CUDA用的比较多,因此翻译一些个人认为重点的章节和句子,作为学习,程序将通过NVIDIA K40服务器得出结果.如果想通过本书进行CU ...

  3. CUDA编程之快速入门

    CUDA(Compute Unified Device Architecture)的中文全称为计算统一设备架构.做图像视觉领域的同学多多少少都会接触到CUDA,毕竟要做性能速度优化,CUDA是个很重要 ...

  4. CUDA编程(二) CUDA初始化与核函数

    CUDA编程(二) CUDA初始化与核函数 CUDA初始化 在上一次中已经说过了,CUDA成功安装之后,新建一个project还是十分简单的,直接在新建项目的时候选择NVIDIA CUDA项目就能够了 ...

  5. CUDA编程之快速入门【转】

    https://www.cnblogs.com/skyfsm/p/9673960.html CUDA(Compute Unified Device Architecture)的中文全称为计算统一设备架 ...

  6. 第二章 Matlab面向对象编程基础

    DeepLab是一款基于Matlab面向对象编程的深度学习工具箱,所以了解Matlab面向对象编程的特点是必要的.笔者在做Matlab面向对象编程的时候发现无论是互联网上还是书店里卖的各式Matlab ...

  7. [.net 面向对象编程基础] (1) 开篇

    [.net 面向对象编程基础] (1)开篇 使用.net进行面向对象编程也有好长一段时间了,整天都忙于赶项目,完成项目任务之中.最近偶有闲暇,看了项目组中的同学写的代码,感慨颇深.感觉除了定义个类,就 ...

  8. Android开发4: Notification编程基础、Broadcast的使用及其静态注册、动态注册方式

    前言 啦啦啦~(博主每次开篇都要卖个萌,大家是不是都厌倦了呢~) 本篇博文希望帮助大家掌握 Broadcast 编程基础,实现动态注册 Broadcast 和静态注册 Broadcast 的方式以及学 ...

  9. T-Sql编程基础

    T-sql编程 入门小游戏 T-sql编程基础,包括声明变量,if判断,while循环,以及使用一些基本函数. 记得在学校的时候,写过一个二人对打的文字输出游戏. 上代码 alter proc usp ...

随机推荐

  1. PHP get_class_methods函数用法

    get_class_methods — 返回由类的方法名组成的数组 说明 array get_class_methods ( mixed $class_name ) 返回由 class_name 指定 ...

  2. HPC Linux

    HPC也就是高性能计算,网格计算.服务器集群等前些日子听了Dr. Allen D. Malony讲座结束时得到两张光盘:一个HPC Linux的live cd,一个virtual box的ova镜像文 ...

  3. View和ViewImage设置图片

    1.view类的设置背景android:background --setBackgroundResource(int) --A drawable to use as the background. s ...

  4. Android学习笔记(十四)——自定义广播

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 我们除了可以通过广播接收器来接收系统广播, 还可以在应用程序中发送自定义的广播.下面我们来分别试一试发送自定义 ...

  5. const 和宏的区别

    参考:http://blog.sina.com.cn/s/blog_79b01f6601018xdg.html (1) 编译器处理方式不同 define宏是在预处理阶段展开. const常量是编译运行 ...

  6. COGS 2479 偏序 题解

    [题意] 给定一个有n个元素的序列,元素编号为1~n,每个元素有三个属性a,b,c,求序列中满足i<j且ai<aj且bi<bj且ci<cj的数对(i,j)的个数. 对于30%的 ...

  7. Objective C 快速入门学习四

    类 1.合成存取器方法 @property   成员变量 @synthesize 成员变量 可以让编译器自动合成 设置和获取函数的方法,不用手动生成set成员变量,Get成员变量 @interface ...

  8. scp和rsync限制传输速度

    1.scp 限速100KB/s scp -l 1000 test root@192.168.1.104 此时的传输速率就是1M/8=100KB左右 2.rsync 限速100KB/s rsync -a ...

  9. linux下的shell运算(加、减、乘、除)

    linux下的shell运算(加.减.乘.除) 标签: linuxshell运算加减乘除 2014-03-12 16:25 15127人阅读 评论(0) 收藏 举报 分类: linux(17) ((i ...

  10. do{...}while(0)的意义和用法

    linux内核和其他一些开源的代码中,经常会遇到这样的代码: do{ ... }) 这样的代码一看就不是一个循环,do..while表面上在这里一点意义都没有,那么为什么要这么用呢? 实际上,do{. ...