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进行渲染绘制时,才能清晰的了解数据的归属和流向,从而避免不必要的错误和性能损失。
参考链接:
https://www.makeuseof.com/tag/can-shared-graphics-finally-compete-with-a-dedicated-graphics-card/
https://lwn.net/Articles/257417/
https://zhuanlan.zhihu.com/p/35891701
https://fgiesen.wordpress.com/2011/07/01/a-trip-through-the-graphics-pipeline-2011-part-1/
GPU体系架构(二):GPU存储体系的更多相关文章
- 深入GPU硬件架构及运行机制
目录 一.导言 1.1 为何要了解GPU? 1.2 内容要点 1.3 带着问题阅读 二.GPU概述 2.1 GPU是什么? 2.2 GPU历史 2.2.1 NV GPU发展史 2.2.2 NV GPU ...
- android体系架构
android体系架构总结: android体系架构分为四层 第一层:应用层:applications 第二层:开发层 第三层:
- hbase的存储体系
一.了解hbase的存储体系. hbase的存储体系核心的有Split机制,Flush机制和Compact机制. 1.split机制 每一个hbase的table表在刚刚开始的时候,只有一个regio ...
- NUMA 体系架构
NUMA 体系架构 SMP 体系架构 NUMA 体系架构 NUMA 结构基本概念 Openstack flavor NUMA 策略 Nova 实现 NUMA 流程 1. SMP 体系架构 CPU 计算 ...
- 2020再见&新的计划(建立Android体系架构)
2020,再见 关于2020,我心中有四个关键词: 疫情 年初突如其来的疫情,打破了原本生活的节奏,也没想到会笼罩全世界整整一年,希望这个世界早点好起来吧. 科比 初三的早晨,噩耗传来,我一度不敢相信 ...
- GPU体系架构(一):数据的并行处理
最近在了解GPU架构这方面的内容,由于资料零零散散,所以准备写两篇博客整理一下.GPU的架构复杂无比,这两篇文章也是从宏观的层面去一窥GPU的工作原理罢了 GPU根据厂商的不同,显卡型号的不同,GPU ...
- InnoDB体系架构(二)内存
InnoDB体系架构(二)内存 上篇文章 InnoDB体系架构(一)后台线程 介绍了MySQL InnoDB存储引擎后台线程:Master Thread.IO Thread.Purge Thread. ...
- MySQL InnoDB存储引擎体系架构 —— 索引高级
转载地址:https://mp.weixin.qq.com/s/HNnzAgUtBoDhhJpsA0fjKQ 世界上只两件东西能震撼人们的心灵:一件是我们心中崇高的道德标准:另一件是我们头顶上灿烂的星 ...
- F2工作流引擎这工作流引擎体系架构(二)
F2工作流体系架构概览图 为了能更好的了解F2工作流引擎的架构体系,花了些时间画了整个架构的体系图.F2工作流引擎遵循参考WFCM规范,目标是实现轻量级的工作流引擎,支持多种数据库及快速应用到任何基于 ...
随机推荐
- postman发送请求的简单操作
发送请求常用的是post和get 两者的区别是: 1.post比get安全,因为参数直接暴露在url中,不能用来传递敏感信息 2.get参数通过url传递,post放在request body中 3. ...
- springcloud ActiveMQ设置多个并行消费者
还是结合实际项目说把,最近在做跟保险公司和第三方借贷平台对接的项目: 其中需要第三方借贷平台借款并和保险挂对勾,也就是每次借钱的时候可以做一次保: 这里面正常情况下的逻辑场景: 借贷平台:借贷审核通过 ...
- AcWing 789.数的范围
AcWing 789.数的范围 题目描述 给定一个按照升序排列的长度为n的整数数组,以及 q 个查询. 对于每个查询,返回一个元素k的起始位置和终止位置(位置从0开始计数). 如果数组中不存在该元素, ...
- Unreal Engine 4 蓝图完全学习教程(三)—— 节点的基本知识
Ⅰ.节点的种类 ①标题:在节点的上方显示着节点的标题,标题部分会根据节点类型显示不同的颜色. ②输入:用于从其他节点接收数据以获取必要的数值. ③输出:将这个节点计算出结果用于传递数值到其他节点. ( ...
- 为什么Netflix没有运维岗位?
Netflix 是业界微服务架构的最佳实践者,其基于公有云上的微服务架构设计.持续交付.监控.稳定性保障,都为业界提供了大量可遵从的原则和实践经验. 在运维这个细分领域,Netflix 仍然是最佳实践 ...
- 《 Java 编程思想》CH02 一切都是对象
用引用操纵对象 尽管Java中一切都看作为对象,但是操纵的标识符实际上对象的一个"引用". String s; // 这里只是创建了一个引用,而不是一个对象 String s = ...
- Codeforces_822
A.小的那个数的阶乘. #include<bits/stdc++.h> using namespace std; int a,b; int main() { ios::sync_with_ ...
- 初见shell
在写了一段时间的java后,发现要一次性执行多个java很麻烦,因此想到了用shell脚本去调用.但是因为之前没有学过shell,所以一切都是重新开始.在此,简单的记录下意思的基础性知识. 参数相关的 ...
- Codeforces_711_A
http://codeforces.com/problemset/problem/711/A 忙了一天没做题,做到水题,我这水平也只能做水题了= = ! #include<iostream> ...
- js变量和函数提升
写在前面: 变量提升是 声明提升,初始化不会提升,比如说 var a=1; console.log(a); 实际是这样执行(个人理解,仅供参考) var a; console.log(a); a=1; ...