一:GPU 编程技术的发展历程及现状

1.冯诺依曼计算机架构的瓶颈

曾经,几乎所有的处理器都是以冯诺依曼计算机架构为基础的。该系统架构简单来说就是处理器从存储器中不断取指,解码,执行。

但如今这种系统架构遇到了瓶颈:内存的读写速度跟不上 CPU 时钟频率。具有此特征的系统被称为内存受限型系统,目前的绝大多数计算机系统都属于此类型。

为了解决此问题,传统解决方案是使用缓存技术。通过给 CPU 设立多级缓存,能大大地降低存储系统的压力:

然而随着缓存容量的增大,使用更大缓存所带来的收益增速会迅速下降,这也就意味着我们要寻找新的办法了。

2.对 GPU 编程技术发展具有启发意义的几件事

1. 70年代末期,克雷系列超级计算机研制成功 (克雷1当年耗资800万美元)。

此类计算机采用若干内存条的共享内存结构,即这些内存条可以与多个处理器相连接,从而发展成今天的对称多处理器系统 (SMD)。

克雷2是向量机 - 一个操作处理多个操作数。

如今的 GPU 设备的核心也正是向量处理器。

2. 80年代初期,一家公司设计并研制了一种被称为连接机的计算机系统。

该系统具有16个 CPU 核,采用的是标准的单指令多数据 (SIMD) 并行处理。连接机通过这种设计能够消除多余的访存操作,并将内存读写周期变为原来的 1/16 。

3. CELL 处理器的发明

这类处理器很有意思,其架构大致如下图所示:

在此结构中,一个 PPC 处理器作为监管处理器,与大量的 SPE流处理器相连通,组成了一个工作流水线。

对于一个图形处理过程来说,某个 SPE 可负责提取数据,另一个 SPE 负责变换,再另一个负责存回。这样可构成一道完完整整的流水线,大大提高了处理速度。

顺便提一句,2010年超级计算机排名第三的计算机就是基于这种设计理念实现的,占地面积达560平方米,耗资 1.25 亿美元。

3.多点计算模型

集群计算是指通过将多个性能一般的计算机组成一个运算网络,达到高性能计算的目的。这是一种典型的多点计算模型。而 GPU 的本质,也同样是多点计算模型。

其相对于当今比较火的Hadoop/Spark集群来说:“点”由单个计算机变成了 单个SM (流处理器簇),通过网络互连变成了通过显存互连 (多点计算模型中点之间的通信永远是要考虑的重要问题)。

4.GPU 解决方案

随着 CPU "功耗墙" 问题的产生,GPU 解决方案开始正式走上舞台。

GPU 特别适合用于并行计算浮点类型的情况,下图展示了这种情况下 GPU 和 CPU 计算能力的差别:

但这可不能说明 GPU 比 CPU 更好,CPU应当被淘汰。 上图的测试是在计算可完全并行的情况下进行的。

对于逻辑更灵活复杂的串行程序,GPU 执行起来则远不如 CPU 高效 (没有分支预测等高级机制)。

另外,GPU 的应用早已不局限于图像处理。事实上 CUDA 目前的高端板卡 Tesla 系列就是专门用来进行科学计算的,它们连 VGA 接口都没。

5.主流 GPU 编程接口

1. CUDA

是英伟达公司推出的,专门针对 N 卡进行 GPU 编程的接口。文档资料很齐全,几乎适用于所有 N 卡。

本专栏讲述的 GPU 编程技术均基于此接口。

2. Open CL

开源的 GPU 编程接口,使用范围最广,几乎适用于所有的显卡。

但相对 CUDA,其掌握较难一些,建议先学 CUDA,在此基础上进行 Open CL 的学习则会非常简单轻松。

3. DirectCompute

微软开发出来的 GPU 编程接口。功能很强大,学习起来也最为简单,但只能用于 Windows 系统,在许多高端服务器都是 UNIX 系统无法使用。

总结,这几种接口各有优劣,需要根据实际情况选用。但它们使用起来方法非常相近,掌握了其中一种再学习其他两种会很容易。

二:从 GPU 的角度理解并行计算

1.并行计算中需要考虑的三个重要问题

1. 同步问题

在操作系统原理的相关课程中我们学习过进程间的死锁问题,以及由于资源共享带来的临界资源问题等,这里不做累述。

  2. 并发度

有一些问题属于 “易并行” 问题:如矩阵乘法。在这类型问题中,各个运算单元输出的结果是相互独立的,这类问题能够得到很轻松的解决 (通常甚至调用几个类库就能搞定问题)。

然而,若各个运算单元之间有依赖关系,那问题就复杂了。在 CUDA 中,块内的通信通过共享内存来实现,而块间的通信,则只能通过全局内存。

CUDA 并行编程架构可以用网格 (GRID) 来形容:一个网格好比一只军队。网格被分成好多个块,这些块好比军队的每个部门 (后勤部,指挥部,通信部等)。每个块又分成好多个线程束,这些线程束好比部门内部的小分队,下图可帮助理解:

3. 局部性

在操作系统原理中,对局部性做过重点介绍,简单来说就是将之前访问过的数据 (时间局部性) 和之前访问过的数据的附近数据 (空间局部性) 保存在缓存中。

在 GPU 编程中,局部性也是非常重要的,这体现在要计算的数据应当在计算之前尽可能的一次性的送进显存,在迭代的过程中一定要尽可能减少数据在内存和显存之间的传输,实际项目中发现这点十分重要的。

对于 GPU 编程来说,需要程序猿自己去管理内存,或者换句话来说,自己实现局部性。

2.并行计算的两种类型

1. 基于任务的并行处理

这种并行模式将计算任务拆分成若干个小的但不同的任务,如有的运算单元负责取数,有的运算单元负责计算,有的负责...... 这样一个大的任务可以组成一道流水线。

需要注意的是流水线的效率瓶颈在于其中效率最低的那个计算单元。

  2. 基于数据的并行处理

这种并行模式将数据分解为多个部分,让多个运算单元分别去计算这些小块的数据,最后再将其汇总起来。

一般来说,CPU 的多线程编程偏向于第一种并行模式,GPU 并行编程模式则偏向于第二种。

3.常见的并行优化对象

1. 循环

这也是最常见的一种模式,让每个线程处理循环中的一个或一组数据。

这种类型的优化一定要小心各个运算单元,以及每个运算单元何其自身上一次迭代结果的依赖性。

2. 派生/汇集模式

该模式下大多数是串行代码,但代码中的某一段可以并行处理。

典型的情况就是某个输入队列当串行处理到某个时刻,需要对其中不同部分进行不同处理,这样就可以划分成多个计算单元对改队列进行处理 (也即派生),最后再将其汇总 (也即汇集)。

这种模式常用于并发事件事先不定的情况,具有 “动态并行性”。

3. 分条/分块模式

对于特别庞大的数据 (如气候模型),可以将数据分为过个块来进行并行计算。

4. 分而治之

绝大多数的递归算法,比如快速排序,都可以转换为迭代模型,而迭代模型又能映射到 GPU 编程模型上。

特别说明:虽然费米架构和开普勒架构的 GPU 都支持缓冲栈,能够直接实现递归模型到 GPU 并行模型的转换。但为了程序的效率,在开发时间允许的情况下,我们最好还是先将其转换为迭代模型。

GPU 并行编程的核心在于线程,一个线程就是程序中的一个单一指令流,一个个线程组合在一起就构成了并行计算网格,成为了并行的程序,下图展示了多核 CPU 与 GPU 的计算网格:

我们前面已经大概的介绍了CUDA执行模型的大概过程,包括线程网格,线程束,线程间的关系,以及硬件的大概结构,例如SM的大概结构,而对于硬件来说,CUDA执行的实质是线程束的执行,因为硬件根本不知道每个块谁是谁,也不知道先后顺序,硬件(SM)只知道按照机器码跑,而给他什么,先后顺序,这个就是硬件功能设计的直接体现了。
从外表来看,CUDA执行所有的线程,并行的,没有先后次序的,但实际上硬件资源是有限的,不可能同时执行百万个线程,所以从硬件角度来看,物理层面上执行的也只是线程的一部分,而每次执行的这一部分,就是我们前面提到的线程束。

线程束和线程块

线程束是SM中基本的执行单元,当一个网格被启动(网格被启动,等价于一个内核被启动,每个内核对应于自己的网格),网格中包含线程块,线程块被分配到某一个SM上以后,将分为多个线程束,每个线程束一般是32个线程(目前的GPU都是32个线程,但不保证未来还是32个)在一个线程束中,所有线程按照单指令多线程SIMT的方式执行,每一步执行相同的指令,但是处理的数据为私有的数据,下图反应的就是逻辑,实际,和硬件的图形化

线程块是个逻辑产物,因为在计算机里,内存总是一维线性存在的,所以执行起来也是一维的访问线程块中的线程,但是我们在写程序的时候却可以以二维三维的方式进行,原因是方便我们写程序,比如处理图像或者三维的数据,三维块就会变得很直接,很方便。
在块中,每个线程有唯一的编号(可能是个三维的编号),threadIdx。
网格中,每个线程块也有唯一的编号(可能是个三维的编号),blockIdx
那么每个线程就有在网格中的唯一编号。
当一个线程块中有128个线程的时候,其分配到SM上执行时,会分成4个块:

warp0: thread  0,........thread31
warp1: thread 32,........thread63
warp2: thread 64,........thread95 warp3: thread 96,........thread127
 

该图表示,计算网格由多个流处理器构成,每个流处理器又包含 n 多块。

下面进一步对 GPU 计算网格中的一些概念做细致分析。

1. 线程

线程是 GPU 运算中的最小执行单元,线程能够完成一个最小的逻辑意义操作。

2. 线程束

线程束是 GPU 中的基本执行单元。GPU 是一组 SIMD 处理器的集合,因此每个线程束中的线程是同时执行的。这个概念是为了隐藏对显存进行读写带来的延迟所引入的。

目前英伟达公司的显卡此值为 32,不可改动,也不应该对其进行改动。

3. 线程块

一个线程块包含多个线程束,在一个线程块内的所有线程,都可以使用共享内存来进行通信、同步。但一个线程块能拥有的最大线程/线程束,和显卡型号有关。

4. 流多处理器

流多处理器就相当于 CPU 中的核,负责线程束的执行。同一时刻只能有一个线程束执行。

5. 流处理器

流处理器只负责执行线程,结构相对简单。

GPU 和 CPU 在并行计算方面的不同

1. 任务数量

CPU 适合比较少量的任务,而 GPU 则适合做大量的任务。

2. 任务复杂度

CPU 适合逻辑比较复杂的任务,而 GPU 则适合处理逻辑上相对简单的任务 (可用比较少的语句描述)。

3. 线程支持方式

由于 CPU 中线程的寄存器组是公用的,因此CPU 在切换线程的时候,会将线程的寄存器内容保存在 RAM 中,当线程再次启动的时候则会从 RAM 中恢复数据到寄存器。

而 GPU 中的各个线程则各自拥有其自身的寄存器组,因此其切换速度会快上不少。

当然,对于单个的线程处理能力来说,CPU 更强。

      4. 处理器分配原则

CPU 一般是基于时间片轮转调度原则,每个线程固定地执行单个时间片;而 GPU 的策略则是在线程阻塞的时候迅速换入换出。

      5. 数据吞吐量

GPU 中的每个流处理器就相当于一个 CPU 核,一个 GPU 一般具有 16 个流处理器,而且每个流处理器一次能计算 32 个数。

CUDA是用于GPU计算的开发环境,它是一个全新的软硬件架构,可以将GPU视为一个并行数据计算的设备,对所进行的计算进行分配和管理。在CUDA的架构中,这些计算不再像过去所谓的GPGPU架构那样必须将计算映射到图形API(OpenGL和Direct 3D)中,因此对于开发者来说,CUDA的开发门槛大大降低了。CUDA的GPU编程语言基于标准的C语言,因此任何有C语言基础的用户都很容易地开发CUDA的应用程序。

与CUDA相关的几个概念:thread,block,grid,warp,sp,sm。

sp: 最基本的处理单元,streaming processor  最后具体的指令和任务都是在sp上处理的。GPU进行并行计算,也就是很多个sp同时做处理

sm:多个sp加上其他的一些资源组成一个sm,  streaming multiprocessor. 其他资源也就是存储资源,共享内存,寄储器等。

warp:GPU执行程序时的调度单位,目前cuda的warp的大小为32,同在一个warp的线程,以不同数据资源执行相同的指令。

grid、block、thread:在利用cuda进行编程时,一个grid分为多个block,而一个block分为多个thread.其中任务划分到是否影响最后的执行效果。划分的依据是任务特性和GPU本身的硬件特性。

 

转载于:https://www.cnblogs.com/klausage/p/10323245.html

GPU的并行运算与CUDA的简介相关推荐

  1. GPU(CUDA)学习日记(十三)------ CUDA内存简介

    GPU(CUDA)学习日记(十三)------ CUDA内存简介 标签: cuda存储线程结构 2012-12-07 16:53 2902人阅读 评论(0)收藏 举报 分类: GPU(16) CUDA ...

  2. CUDA编程(一):GPU计算与CUDA编程简介

    CUDA编程(一):GPU计算与CUDA编程简介 GPU计算 GPU硬件资源 GPU软件资源 GPU存储资源 CUDA编程 GPU计算 NVIDIA公司发布的CUDA是建立在GPU上的一个通用并行计算 ...

  3. DL之IDE:深度学习环境安装之CUDA的简介(显卡GPU/驱动/CUDA间的关系)、安装(根据本地电脑的NVIDIA显卡驱动版本去正确匹配CUDA版本)之详细攻略

    DL之IDE:深度学习环境安装之CUDA的简介(显卡GPU/驱动/CUDA间的关系).安装(根据本地电脑的NVIDIA显卡驱动版本去正确匹配CUDA版本)之详细攻略 目录 CUDA的简介 1.显卡GP ...

  4. CUDA Libraries简介

    CUDA Libraries简介 上图是CUDA 库的位置,本文简要介绍cuSPARSE.cuBLAS.cuFFT和cuRAND,之后会介绍OpenACC. cuSPARSE线性代数库,主要针对稀疏矩 ...

  5. win11动手学深度学习安装过程(GPU版)( CUDA Anaconda Mxnet )

    win11,动手学深度学习安装过程(GPU版)( CUDA / Anaconda / Mxnet )(备忘) 一.检查及安装CUDA 首先检查显卡支持的cuda: 直接搜索NVIDIA,选择NVIDI ...

  6. GPU编程自学2 —— CUDA环境配置

    深度学习的兴起,使得多线程以及GPU编程逐渐成为算法工程师无法规避的问题.这里主要记录自己的GPU自学历程. 目录 <GPU编程自学1 -- 引言> <GPU编程自学2 -- CUD ...

  7. 显卡、GPU、CPU、CUDA、显存、RTX/GTX及查看方式

    学习资源: CPU和GPU到底有什么区别?https://zhuanlan.zhihu.com/p/156171120 看完就懂:GPU和显卡的关系,GPU和CUDA有什么关系?https://blo ...

  8. CUDA 编程简介(上)

    参考资料: NVIDIA CUDA Programming Guide, NVIDIA. (https://docs.nvidia.com/cuda/cuda-c-programming-guide/ ...

  9. pytorch在调用GPU的时候出现cuda runtime error (2) : out of memory at ..\aten\src\THC\THCGeneral.cpp:50

    这是因为GPU中的显存占满了,在任务管理器中关闭程序即可 @[TOC](pytorch在调用GPU的时候出现cuda runtime error (2) : out of memory at -\at ...

最新文章

  1. SSL For Free 申请免费https SSL 凭证
  2. ping -c3 baidu.com  ping过去是这样,代表网络畅通
  3. Practice:在2008 core上部署和管理DHCP服务器
  4. 不全?MySQL数据类型精讲,定点日期枚举文本字符串,json二进制,空间,选择建议,完整详细可收藏
  5. [logstash-input-log4j]插件使用
  6. EFCore-一对一配置外键小记
  7. python项目结构图_python项目
  8. npm查找依赖包版本
  9. java servlet容器有哪些_Java Web —— servlet 容器
  10. 在语义层面构建的对抗样本SemanticAdv: Generating Adversarial Examples via Attribute-conditioned Image Editing
  11. mysql 解决1062报错
  12. 量化投资学习——经济周期
  13. 计算机应用能力考试科目,全国专业技术人员计算机应用能力考试科目Word
  14. 微博和qq说说定时发送畅想
  15. 英语学习得六大黄金原则
  16. android定时锁定,定时冻结(无需root冻结应用)
  17. 计算机/软件专业属于工学还是理学?为什么?
  18. 【IF=10.812 Molecular Plant】HDA9和WRKY53共同在植物胁迫中起拮抗调节作用
  19. 基于遗传算法解决TSP问题(Matlab代码实现)
  20. mac 无法连接到 windows 计算机.,每次登录都出现“此mac无法连接到iCloud”的解决方法...

热门文章

  1. Cannot download sources的问题复现及解决
  2. Android设置Edittext只能输入数字字母并弹出英文键盘
  3. 一个故事一首歌——《枯叶之蝶…
  4. coco2017 数据集下载链接 及姿态关键点的数据处理
  5. Vocabulary Tree 词汇树算法
  6. 二手车O2O电商模式引领汽车消费新时尚
  7. 多媒体计算机能代替幻灯吗,多媒体计算机幻灯片课件.ppt
  8. 【操作系统·考研】信号量机制/PV操作
  9. lpk.dll usp10.dll 感染病毒专杀工具 lpk usp10
  10. 视频剪辑调色软件:达芬奇18正式版 for mac