GPU体系架构浅析

学号:20021210854    姓名:王昊天

原文链接:https://www.cnblogs.com/hellobb/p/11023873.html#4280592

 https://www.cnblogs.com/hellobb/p/10695915.html

【嵌牛导读】浅析GPU体系架构

【嵌牛鼻子】CPU   GPU   CUDA    并行计算

【嵌牛正文】

GPU体系架构(一):数据的并行处理

GPU根据厂商的不同,显卡型号的不同,GPU的架构也有差别,但是大体的设计基本相同,原理的部分也是相通的。下面我们就以NVIDIA的Fermi架构为蓝本,从降低延迟的角度,来讲解一下GPU到底是如何利用数据的并行处理来提升性能的。

无论是CPU还是GPU,都在使用各种各样的策略来避免停滞(stall)。CPU的优化路线有很多,包括使用pipeline,提高主频,在芯片上集成访问速度更快的缓存,减少内存访问的延迟等等。在减少stalls的路上,CPU还采用了很多聪明的技术,比如分支预测,指令重排,寄存器重命名等等。

GPU则采用了另一种不同的策略:throughput。它提供了大量的专用处理器,由于GPU端数据的天然并行性,所以通过数据的大规模并行化处理,来降低延迟。这种设计优点是通过提高吞吐量,数据的整体处理时间减少,隐藏了处理的延迟。但是由于芯片上集成的核越多,留给其他设备的空间就越小,所以像memory cache和logical control这样的设备就会变少,导致每一路shader program的执行变得延迟很高。了解这个特性,我们来看一个例子,以此来说明如何利用GPU的架构,写出更高效的代码。

假如我们有一个mesh要被渲染,光栅化后生成了2000个fragment,那么我们需要调用一个pixel shader program 2000次,假如我们的GPU只有一个shader core(世界最弱鸡GPU),它开始执行第一个像素的shader program,执行一些算数指令,操作一下寄存器上的值,由于寄存器是本地的,所以此时并不会发生阻塞,但是当程序执行到某个纹理采样的操作时,由于纹理数据并不在程序的本地寄存器中,所以需要进行内存的读取操作,该操作可能要耗费几百甚至几千个时钟周期,所以会阻塞住当前处理器,等待读取的结果。如果真的只是这样设计这个GPU,那它真的就是太弱鸡了,所以为了让它稍微好点,我们需要提升它的性能,那如何降低它的延迟呢?我们给每个fragment提供一些本地存储和寄存器,用来保存该fragment的一些执行状态,这样我们就可以在当前fragment等待纹理数据时,切换到另一个fragment,开始执行它的shader program,当它遇到内存读取操作阻塞时,会再次切换,以此类推,直到2000个shader program都执行到这里。这时第一个fragment的颜色已经返回,可以继续往下执行了。使用这种方式,可以最大化的提高GPU的效率,虽然在单个像素来看,执行的延迟变高了,但是从2000个像素整体来说,执行的延迟减少了。

现代GPU当然不会弱鸡到只有一个shader core,但是它们也同样采用了这种方式来减低延迟。现代GPU为了提高数据的并行化,使用了SIMT(Single Instruction Multi Thread,SIMD的更高级版本),执行shader program的最小单位是thread,执行相同program的threads打包成组,NVIDIA称之为warp,AMD称之为wavefront。一个warp/wavefront在特定数量的GPU shader core上调度执行,warps调度器调度的基本单元就是warp/wavefront。

假如我们有2000个fragment需要执行shader program,以NVIDIA为例,它的GPU包含32个thread,所以要执行这些任务需要2000/32 = 62.5个warps,也就是说要分配63个warps,有一个只使用一半。

一个warp的执行过程跟单个GPU shader core的执行过程是类似的,32个像素的shader program对应的thread,会在32个GPU shader core上同时以lock-step的方式执行,当着色器程序遇到内存读取操作时,比如访问纹理(非常耗时),因为32个threads执行的是相同的程序,所以它们会同时遇到该操作,内存读取意味着该线程组将会阻塞(stall),全部等待内存读取的结果。为了降低延迟,GPU的warp调度器会将当前阻塞的warp换出,用另一组包含32个线程的warp来代替执行。换出操作跟单核的任务调度一样的快,因为在换入换出时,每个线程的数据都没有被触碰,每个线程都有它自己的寄存器,每个warp都负责记录它执行到了哪条指令。换入一个新的warp,不过是将GPU 的shader cores切换到另一组线程上继续执行,除此之外没有其他额外的开销。该过程如下图所示:

在我们这个简单的例子中,内存读取的延迟(latency)会导致warp被换出,在实际的应用中,可能更小的延迟就会导致warp的换出操作,因为换入换出的操作开销非常低。warp-swapping的策略是GPU隐藏延迟(latency)的主要方式。但是有几个关键因素,会影响到该策略的性能,比如说,如果我们只有很少的threads,也就是只能创建很少的warp,会使隐藏延迟出现问题。

shader program的结构是影响性能的主要角色,其中最大的一个影响因素就是每个thread需要的寄存器的数量。在上面例子的讲解过程中,我们一直假设例子中的2000个thread都是同时驻留在GPU中的。但是实际上,每个thread绑定的shader program中需要的寄存器越多,产生的threads就越少(因为寄存器的数量是固定的),能够驻留在GPU中的warp就越少。warps的短缺也就意味着无法使用warp-swapping的策略减缓延迟。warps在GPU中存在的数量称之为占用率,高占用率意味着有更多的warps可以用来执行,低占用率则会严重影响GPU的并行效率。

另一个影响GPU性能的因素就是动态分支(dynamic branching),主要是由if和循环引进的。因为一个warp中的所有线程在执行到if语句时,就会出现分裂,如果大家都是执行的相同的分支,那也没什么,但但凡有一个线程执行另一个分支,那么整个warp会把两个分支都执行一遍,然后每个线程扔掉它们各自不需要的结果,这种现象称为thread divergence

了解了上面的基本原理,我们可以看出,整个GPU的设计其实也是一种trade-off,用单路数据的高延迟,来换整体数据的吞吐量,以此来最大化GPU的性能,降低stall。在实际的编码过程中,尤其是shader的编写过程中,也要严肃影响GPU优化策略的几个因素,只有这样,才能写出更加高效的代码,真正发挥出GPU的潜力。

GPU体系架构(二):GPU存储体系

GPU是一个外围设备,本来是专门作为图形渲染使用的,但是随着其功能的越来越强大,GPU也逐渐成为继CPU之后的又一计算核心。但不同于CPU的架构设计,GPU的架构从一开始就更倾向于图形渲染和大规模数据的并行计算处理。而大规模的并行计算,离不开大规模的数据传输,只有深入了解了GPU的存储体系,才能真正发挥GPU的威力,写出高性能的软件产品。但是由于GPU存储体系相关的资料非常少,加之非常分散,所以在看了大量的零散资料后,想通过这篇文章,总结一下关于GPU存储相关的知识点,以期达到加深理解的目的。

GPU存储体系的设计哲学是更大的内存带宽,而不是更低的访问延迟。该设计原则不同于CPU依赖多级Cache来降低内存访问延迟的策略,GPU则是通过大量的并行线程来规避或者叫隐藏内存访问的延迟,具体来说就是GPU在等待某个内存数据到来的时候,会运行成百上千个其他与该数据无关的线程,来处理另外的数据请求,这就是GPU存储体系内存访问的特点:高带宽,高延迟。

正式开始之前,我们需要了解几个基础的概念。我们通常在讲内存时,多数情况下都是指CPU的专用存储,从GPU存储的角度来说,CPU的内存一般称之为主存(main memory),GPU自己的存储则称为local memory,即GPU的本地存储,有时候也称为video memory。

GPU的存储体系根据GPU的类型不同,可以是逻辑上的,也可以是物理上的。对于集成显卡(即integrated GPU)而言,例如Intel HD Graphics,GPU和CPU位于同一die中,所以它没有自己的物理存储设备,而是共享CPU的存储空间,即Unified Memory Architecture(一致性存储架构),通常是从CPU的存储中划分一部分出来作为该GPU的local memory;另一种显卡称为独立显卡(即dedicated GPU),像Nvidia和AMD生产的GPU就属于这类,它们都拥有自己的物理存储设备,是我们日常使用最多的GPU类型了。无论哪种GPU,它都拥有自己的一套地址空间,且独立于CPU的虚拟内存地址空间。GPU地址空间的管理是通过内核态驱动来完成的,例如Windows上的KMD(Kernel-Mode Driver)

对于integrated gpu而言,因为GPU和CPU处于同一die中,所以GPU和CPU很多时候是共享总线的。除了GPU自己的local memory之外,CPU和GPU之间有时候需要共享一些数据,例如在渲染的时候,CPU将顶点数据放入主存当中,供GPU使用。由于主存的内容对GPU来说是不可见的,所以GPU是不能直接访问这些数据的。为了让GPU访问CPU主存的内容,业界引入了一个叫GART(即Graphic Address Remapping Table)的技术。GART是一个I/O memory management unit(IOMMU) ,说白了就是一个内存地址的映射表,可以将CPU的内存地址重新映射到GPU的地址空间,这样就可以让显卡直接访问(DMA,direct memory access)host system memory。

反过来,CPU如何访问GPU的存储空间呢?因为integrated gpu的存储空间是从主存分出的一部分,一般情况下都比较小,OS可以将GPU的整个存储空间映射到CPU的地址空间。但是对于dedicated gpu来说,这种方式就不行了,因为独立显卡的显存一般比较大,一个32位的OS整个地址空间也才4GB。所以独立显卡拥有与integrated gpu不同的地址空间映射机制,用于解决这个问题。一种比较常用的方式是映射一部分GPU存储空间到CPU的地址空间,典型大小为256MB/512MB,这段地址空间会通过PCIe的bar获取一个CPU可见的地址空间。最新的PCIe支持 resize bar技术,支持该技术的GPU可以动态调整映射区域的大小。

简单介绍完GPU的存储体系后,我以OpenGL程序为例,来分析一下OpenGL中数据的upload和download过程,从而了解GPU存储体系在实际程序中的运用。

OpenGL更新数据的常用函数家族是:glBuffer*Data和glMapBuffer*。更准确的说是CPU需要更新数据给GPU使用时,顶点数据的更新,纹理数据的上传等等,需要CPU到GPU的数据传输,这个过程称为streaming。这个数据传输的过程有两种方式:

l  glBufferData/glBufferSubData

通过这两个函数,可以将数据从main memory拷贝到pinned memory,一旦拷贝完成,就会发起一次异步的DMA(Direct Memory Access)传输,将数据传输给GPU,然后就会从函数调用返回,一旦函数返回,你就可以对原来CPU主存中的数据做任何处理,修改或者删除。

l  glMap*/glUnmap*

通过mapping的方式传输数据,你可以获取一个指向pinned memory的指针,通过该指针你可以拷贝main memory上的数据到pinned memory,然后调用glUnmap通知driver你已经完成数据的更新,这种方式看似跟上面的glBufferData/glBufferSubData一样,但是你可以获得更多的控制权。

该例子中的pinned memory就是CPU内存上的一块专门用于GART的存储区域,DMA传输则是通过上文提到的PCIe bar来实现的,了解了GPU的存储体系,在使用图形API进行渲染绘制时,才能清晰的了解数据的归属和流向,从而避免不必要的错误和性能损失。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容