转自: 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. oracle asm 概念

    automated storage management ,即自动存储管理,简称asm .. 在oracle 10g 这个版本之前,管理一个大型数据库成千上万的数据文件对数据库管理员来说是一个既无技术 ...

  2. Git 常用命令2

    Git 常用命令 Git 是一个很强大的分布式版本控制系统.它不但适用于管理大型开源软件的源代码,管理私人的文档和源代码也有很多优势. Git常用操作命令: 1) 远程仓库相关命令 检出仓库:$ gi ...

  3. JAVA Io 缓冲输入输出流

    java中提供带缓冲的输入输出流.在打开文件进行写入或读取操作时,都会加上缓冲,提高了IO读写性能. 1. BufferedInputStream 缓冲输入流 2. BufferedOutputStr ...

  4. BPMN流程图的绘制的注意要点

    1.分支网关的表达式,是在选择的线上设置. 2.在分支网关上,可以设置一个默认线的id. 3.并行网关,必须有开始,有结束.

  5. BZOJ1452——[JSOI2009]Count

    1.题目大意: 就是给一个n×m的方格,然后一些平面上的 求和 修改操作 2.分析:二维树状数组裸题 #include <cstdio> #include <cstdlib> ...

  6. @SerializedName注解

    在Android中解析Gson解析json数据是很方便快捷的,可以直接将json数据解析成java对象或者集合. Gson解析json的方法我这里就不详细说明了,网上一大把的例子,我这里主要说一下使用 ...

  7. H5canvas赛车游戏-基于lufylegend引擎

    lufylegend引擎是canvas游戏中,比较简单的引擎之一,它不需要配置环境,类似引入jquery包的方式,引用对应js文件即可 lufylegend官方网站:http://www.lufyle ...

  8. POJ 3641 快速幂+素数

    http://poj.org/problem?id=3641 练手用,结果念题不清,以为是奇偶数WA了一发 #include<iostream> #include<cstdio> ...

  9. Python类的特点 (1):构造函数与方法

    Python中,类的特点: #encoding:utf-8 class Parent(object): x=1 #x是Parent类的属性(字段) def __init__(self): print ...

  10. 解决file_get_contents无法请求https连接的方法

    PHP.ini默认配置下,用file_get_contents读取https的链接,就会报如下错误,本文给出解决方法 错误: Warning: fopen() [function.fopen]: Un ...