赞
踩
CUDA的全称是Computer Unified Device Architecture(计算机统一设备架构),它是NVIDIA在2007年推向市场的并行计算架构。CUDA作为NVIDIA图形处理器的通用计算引擎,提供给我们利用NVIDIA显卡进行GPGPU(General Purpose Graphics Process Unit)开发的全套工具。因此,CUDA不只是一种编程语言,它包括NVIDIA对于GPGPU的完整的解决方案:从支持通用计算并行架构的GPU,到实现计算所需要的硬件驱动程序、编程接口、程序库、编译器、调试器等。NVIDIA提供了一种较为简便的方式编写GPGPU代码:CUDA C。CUDA为C程序员提供了一个完整的接口,可以访问本地 GPU 的内存、命令集以及并行计算元素,形成了一个开放的体系结构,并且可以同时运行成千上万个线程。本节详细介绍了CUDA的架构、线程和内存结构以及单指令多线程模式,是利用CUDA并行优化算法的基础知识。
上图所示为CUDA的软件架构。从CUDA编程框架的组成来说,可以分为三个部分:编程接口(API)、运行时需要的runtime库和设备驱动。
提供CUDA给出的应用开发库是API层的主要任务,大规模的并行计算问题由它负责解决。
开发和运行CUDA程序所需要的相关组件和环境主要由Runtime 库提供,其中有各种函数,比如定义各种基本的数据类型、访问设备、转换数据类型、调度函数等等。
GPU己经逐渐成为一个高效的并行通用计算平台,甚至在某些应用领域己经超越了CPU的使用率。基于此,越来越多的研究人员开始热忠于一个新的研究方向:GPGPU主要研宄GPU如何在其他科学计算应用领域内来进行更为广泛的应用计算,从而使得传统的计算技术和算法优化问题在高性能计算平台上可以获得更好的效果。当代可编程GPU己经发展成为了一种计算能力强大、并行性高以及拥有极高的内存带宽的高性能计算设备。
如图所示为CUDA计算模型。基于CUDA的计算模型,我们将一个程序分为两部分:主机端(host)和设备(device)端。主机端的是CPU执行的程序部分,设备端的是GPU上执行的程序部分。内核(kernel)是设备端程序的另外一种叫法。一般情况下,CPU执行主机端的程序会准备好数据并将其复制进显卡内存中,然后设备端的程序由GPU执行完后,主机端程序会将生成的数据结果从显卡的内存中拿回。
CUDA还指基于扩展C编程语言的直观和可扩展的编程模型,该模型将CPU和GPU(所谓的主机和设备)统一到异构计算系统中,在两者中实现最佳优势。具体来说,CUDA-C包含三种类型的函数:
(1) 主机函数,它的调用、执行都仅由主机端来完成;
(2) 内核函数,定义时必须要加上_global_限定符,它由主机端调用,设备端执行;
(3) 设备函数,定义时必须要加上_device_限定符,仅由设备端调用、执行。顺序操作应被编程为主机函数,可并行化操作应被编程为内核函数或者设备函数。主机函数和内核函数都将在main函数中被封装和调用。
事实上,一次内核调用将会在GPU上并行执行大量的线程。取决于计算能力的等级,一个grid对应于一个GPU或者多个多处理器。而一个block中所有的线程在一个流多处理器(SM)上并发地执行。当这个block中的所有线程都执行完毕并终止之后,GPU会激活一个新的block并将其分配到当前空闲的SM上。处于同一个block里的多个block可以在一个SM上同时被激活。
当然在同一个SM上可能会同时被激活,但一个block里的线程不会被拆分并在多个SM上执行。同一个block里的线程可以被同步,并且它们可以访问SM里的共享存储器。SM将每个线程与一个标量处理器核心(SP)映射起来,线程可以在SP上独立地执行任务,并使用独自的指令地址和寄存器。
CUDA线程被组织为“grid-block-thread”的层次结构,具有不同计算能力的GPU有不同的对block和grid维数和尺寸的限制。这样的线程组织在硬件上也对应着一个有层次的实现。一个GPU由一个或多个SM组成,而每个多处理器由多个SP组成。标量处理器又称作CUDA核。每个标量处理器可以独立地执行计算任务并使用指定范围的计算资源。整个系统运作于CUDA的SIMT体系之上。
在CUDA计算结构中,内存的层次机制是一个重要架构技术,内存分为三个层次,分别是块内本地内存、共享内存和全局内存。在同一线程块中,每个线程都有属于自己的块内本地内存,同时幵辟一块共享内存共每一个线程块使用,线程块内的所有线程都可以访问自己块的共享内存,但是不能访问别的线程块所属的共享内存,因此,不同块之间的共享内存是互相隔离的。对于全局内存,在内核程序中的所有线程块中的线程都可以访问。
在运行主机-设备机制的并行计算时,CPU主机的主程序使用设备内核的计算网格,在计算网格上部署的所有线程块不是指定到一个处理器上,而是由CUDA分配给多处理器并执行,这样使得一个线程块中的所有线程可以执行在一个多处理器中。并多处理器管理线程的方式是使用单指令多线程SIMT(Single Instruction MultiThreads)架构实现的,它有一个标量处理器核心,所有线程都映射到这个核心上成为标量线程,每一个标量线程在执行时都是独立地分配和使用各自的寄存器状态和指令地址。
SIMT的模式与单指令多数据SIMD的向量式组织结构相似,虽然是控制多个处理单元,但是用单指令来完成的。不过SIMT让我们可以对独立的标量线程进行线程级细粒度的并行编码,也可以实现数据并行的编码,服务于协同线程,这些是SIMD向量机模式做不到的。
将一个CUDA 应用程序分为主机端和设备端两个部分,主机端一般是指设备宿主主机的CPU处理器,设备端则指CUDA所能访问管理的显卡设备。一般情况下,一个系统最多同时只能拥有一个主机端,但是可以同时拥有多个设备端。主机端程序主要是通过CPU负责实际计算任务的执行,因此,主机端一般负责程序中的串行部分的业务处理,而GPU则主要用于进行并行计算任务的处理,一般以多线程的形式执行,由于主机端和设备端调用不同的处理单元,即前者调用主机的CPU处理单元,后者调用显卡设备的处理单元,因此二者访问的存储器空间是不同的,前者访问主机内存空间,而后者访问显卡设备内存空间。主机端负责的任务除了一般的与显卡设备交互以及CUDA程序的串行部分的计算任务之外,还负责对显卡设备调用前的环境初始化以及相关数据预处理等工作。
一个优秀的CUDA程序应该由主机端负责程序中串行任务的执行,并回收分配给已经执行结束的设备端程序的资源,并初始化下一个设备端内核函数的执行环境启动执行任务,从而减少host与device之间的数据传输,在device上一定时间内执行尽量多的运算。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。