GPU与GPGPU泛淡

2023-11-12

GPU与GPGPU泛淡

GPU(Graphics Processing Unit),也即显卡,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上作图像运算工作的微处理器。它已经是个人PC和移动设备上不可或缺的芯片,有界面有显示的地方,一般就离不开它。高清电视、智能手机、个人电脑。

GPU的产生是为了解决图形渲染效率的问题,但随着技术进步,GPU越来越强大,尤其是shader出现之后(这个允许我们在GPU上编程),GPU能做的事越来越多,不再局限于图形领域,也就有人动手将其能力扩展到其他计算密集的领域,这就是GP(General Purpose)GPU。

考虑到当下,图形领域的技术人员对GPU已经是很熟悉了,其他那些关心GPU的,无非是向往GPU的强大并行运算能力,想利用它做通用计算的,因此,本文会特别提GPGPU。

架构与生态

GPU
第一行为图形引擎/算法库,
第二行为图形标准
第三行为不同型号的GPU

图形标准

开发者直接调用驱动接口是很不方便且不安全的,为此,需要有一套给上游应用开发提供的API,开发者使用这组API,去触发GPU的功能,这一套API就是图形标准。
如图所示:
api
作为开发者,自然非常希望这套API是统一的,不过很不幸,由于历史原因、性能问题及永恒的利益之争,统一似乎是不可能的事情。还好,主流的标准就那么几个,而且编程原理基本上一样,代码封一层去适应下,一般也就可以了。

图形渲染标准

个人PC一般是Windows系统,主要使用Direct3D,一般也支持OpenGL。
服务器、mac等一般是类unix系统(Ubuntu、Redit、macOS),支持开放标准OpenGL。
智能手机、机顶盒等嵌入式设备一般是类unix系统(iOS、Android、阿里云等),支持开放标准OpenGLES(OpenGL标准作裁剪而得),不过苹果觉得OpenGL效率太低,不能充分发挥自家GPU的优势,就搞了一个metal。后面 AMD 也这么认为,搞了一个mantle,到了最后khronos组织也一致这么认为了,就推出了vulkan。

Direct3D只适用于Windows,metal只适用于ios,mantle只适用于AMD的GPU,OpenGL/OpenGL ES及新推出的vulkan是通用开放标准,它们由khronos组织维护,理论上适用于任何操作系统,但需要GPU厂商去支持。

最早的图形标准是联合组织维护的OpenGL,后面微软觉得这个组织效率太低,于是结合自己的系统弄了Direct3D,在后续的较量中渐渐取得了绝对优势(率先推出shader是竞争拐点)。OpenGL在PC端渐渐不行的时候,苹果的iphone及一系列Android机又在移动端拯救了它(开放的好处,移动端只能用OpenGL)。但OpenGL这套标准实在是有硬伤,人们虽然将就着用,并且不断升级改良,也实在到了需要进一步突破的时候,于是就有了 vulkan。

如这篇文章所述:
http://blog.csdn.net/mythma/article/details/50808817
vulkan在设计上无疑是先进的,一是废弃了OpenGL的线程上下文及状态机模式(这导致图形引擎在考虑多线程并发时的设计超痛苦,且很容易出Bug),二是废弃了shader前端、只支持一种叫SPIR-V的shader中间码(一方面防止奇葩低端gpu在编译shader时报语法错误,另一方面,可以对shader代码作一定的产权保护)。不过,引擎开发者、驱动开发者及系统维护者适应这一变更,需要一段时间。

通用计算标准

目前的通用计算标准主要是OpenCL,最新版到2.1,但人们用得最多的是NVIDIA的专属API:CUDA。
Google 一直在Android系统中强推 RenderScript,不在系统层面支持OpenCL,很大程度上限制了移动端的通用计算应用。
这篇文章分析 OpenCL和RenderScript 得比较好:
http://blog.csdn.net/zhuanshenweiliu/article/details/40746873

硬件与驱动

在个人PC、游戏主机及服务器市场,主要是NVIDIA和AMD两强争霸,传统的图形渲染上,不分伯仲;通用计算方面,由于NVIDIA先行了一步,推出CUDA,生态圈已成,拥有绝对优势;不妨看今年据说要爆发的VR(虚拟现实)上,两边的成绩如何。

嵌入式设备市场上,GPU品种要繁多一些,论第一还是首推iphone所采用的powerVR(Imagination公司所产),其次是高通的Adreno系列(如小米、三星S7),继而Arm的mali系列(海思自用图芯吃亏之后,改用mali系列,图形能力脱胎换骨【但还是相对弱势】,不过P6、D2给消费者留下的图形能力不行的阴影至今仍在)。其他份额较少的gpu就不罗列了。

谈到硬件,不妨提一下相应的驱动框架:
参考文章
http://blog.csdn.net/myarrow/article/details/17375483
(这一部分建议没有背景知识的先跳过)
一般来说,gpu的驱动框架类似下图:
driver

1、窗口标准的实现是与操作系统强相关的,它为图形渲染提供目标内存。一般来说,只要支持的标准不变,操作系统更换/升级,对驱动的代码影响就只限在窗口这一块。
2、编译器用于编译shader或kernel,编译kernel需要用llvm预编译,编译器会大一些。低端GPU的编译器特别容易出现各种语法不支持,让写shader的人痛苦万分。
3、通用计算的实现就是把kernel编译后转成任务扔给内核去跑,相对简单。
4、图形渲染的实现则需要考虑到一帧中可能有重复渲染/过度绘制的情况,为了这方面做优化,一帧中的任务有必要做一下组织,因此要有个帧管理器模块。
5、内存管理用于管理显存,但显存不一定是在GPU芯片上(独显和集显的区别)。
6、不管上层玩得多么风生水起,到了内核都是一个个的任务,内核模块执行、调度便是。

图形引擎/算法库

一般而言,应用开发者不会直接去调用图形标准API,而是使用图形引擎/算法库。原因如下:
1、图形标准API非常繁琐难用,需要习惯GPU编程的思想,有必要做适度封装,减轻上层应用的开发难度。
2、如上文所述,图形标准有多种,且不同硬件对同一标准的支持情况也不一定相同,有必要做一个中间层,专门去处理这些问题。
3、一些图形图像算法需要较强的专业知识,得用专业人才去编写。

图形引擎

应用开发者开发界面时,主要是用操作系统提供的View框架。为支持这个框架,操作系统都会实现一套2D引擎,开发者间接使用了图形引擎。

如这个应用间接使用了Android的hwui引擎:
OES

要求界面炫酷的应用,典型如游戏,会去用一些3D引擎。目前手游上主流的游戏引擎是 unity3D和cocos2D,unity3D免费但不开源,cocos2D是做了捕鱼达人游戏的公司公布并开源的。PC游戏方面,以收费商业引擎为主,且一般是基于D3D(这就是为什么linux、类linux系统下游戏那么少),典型如虚幻引擎,特效强大。ogre是主要用于PC的久负盛名的开源引擎,支持OpenGL,完美时空基于ogre做过游戏。

网易的天下HD用的unity3D(没记错的话。。。)
 天下HD

虚幻引擎做的某款游戏:
xuhuan

图形引擎多种多样,这里仅仅是列了很少一部分,毕竟是个大坑,只能简单提一下。

通用计算引擎/算法库

通用计算引擎所见的主要是 ArrayFire,主页:http://arrayfire.com/。它提供了一系列用OpenCL/Cuda加速的算法库,并提供方便的接口去开发GPU加速的算法。

caffe是工业上最常用的深度学习框架,支持多台装配NVIDIA的服务器同时进行深度学习。

opencv 是一个庞大的图像算法库,cl-opencv对其核心算法基于OpenCL作了加速。

PG-Storm 则据说是用 GPU加速的 postsql,具体没看过,SQL查询中的变长字符串处理是GPU优化的难点,以前看过的demo都回避了这一问题,不知道这个是否解决了。

GPU编程

抛开具体的硬件,标准,以及引擎来说,GPU本身代表着和CPU不一样的编程思想:CPU好比几个高智商精英,什么都能做且做得快;而GPU就是一大群低学历农民工,每个人可以做的有限,也不快,但人数优势决定其整体速度完爆精英们。

GPU编程,就像指挥一大群蚂蚁,有几个通用原则:
1、让蚂蚁们做的工作量尽可能相等,因为你要等所有蚂蚁都完成才能进行下一步。
2、不要在意每一只蚂蚁的工作细节,请关注你给蚂蚁准备的粮食。(GPU编程的主要工作是配置参数)
3、蚂蚁们所在的世界和你的世界有矩离,你要教导它们做事(提供shader或kernel),向它们喊话(触发执行API),并提供做事的资源(内存数据传到显存)。

图形渲染

管线

管线是GPU上做图形渲染编程最为重要的概念,GPU就像一个炒菜机,程序员要做的主要事情是给它配原料,至于翻滚、加热等工序,不在程序员的控制之内。
参考:
http://www.360doc.com/content/13/0107/18/9934052_258805453.shtml
简单的记法:
顶点——图元——光栅化——着色

形与色

图形渲染的基本思想就是先定形,再定色,

下图是OpenGL ES 编程流程:
ES_Program

通用计算

数据并行与批量化

使用GPU加速算法,务必做到批量化处理,只处理1条或1行数据,调用GPU接口的交互时间会远远超出计算时间。

减少交流

这里的交流,一方面指的是CPU与GPU之间的数据传输,另一方面指调触发运算的API。

GPGPU应用展望

移动端的通用计算

从事SOC开发的工作时,对此做了许多尝试均告失败。移动端的通用GPU计算实在是很难有进展的一件事情,首先,受限于可怜的GPU性能及弱爆了的内存传输带宽,GPU加速往往被多线程+neon完爆;其次,移动端作密集运算的场景着实有限,最需要运算的也就相机模块与图像编解码,但这么有限的场景厂商完全可以上DSP/ISP,GPU在这时并没太大优势。目前而言,在移动端做优化,主要还是运用OpenGL和neon。
然而随着普适计算、情景智能、图像识别的发展,移动端的通用计算将会变得越来越有意义,更快更准确的机器学习算法的使用,可以让手机更智能。

通用分布式异构计算框架

目前的分布式计算框架,通用型的如hadoop、spark、flink等都是只能利用CPU的(虽然也可以用GPU,但用起来很麻烦且兼容性不好)。

用上了 GPU 的,主要是特定设备上跑固定算法(Deep Learning),不具备通用性。以致于几乎Tesla就是DL的代表,
http://server.yesky.com/es/355/50639355.shtml

若有一个通用的分布式异构计算框架,可以大幅降低机器学习、图像处理、视频制作等计算密集业务在时间和机器上的消耗,其价值是非常大的。
此外,基于此可以设计分布式GPU数据库,大大提升查询的性能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GPU与GPGPU泛淡 的相关文章

  • 法线在 openGL 中表现得很奇怪

    我一直在为 openGl 编写一个 obj 加载器 几何体加载得很好 但法线总是混乱的 我尝试在两个不同的程序中导出模型 但似乎没有任何效果 据我所知 这就是将法线放入 GL TRIANGLES 的方法 glNormal3fv norm1
  • glutPostRedisplay 不在循环内工作

    我试图让一个人在 y 轴上跳跃 所以我使用 2 秒的循环 第一秒它应该向下移动并弯曲膝盖 第二秒它应该向上移动 然后在起始位置完成 现在我刚刚开始让这个人在第一秒内跪下并弯曲膝盖 我还没有编写动画的其余部分 问题是 glutPostRedi
  • QOpenGLFunctions 缺少重要的 OpenGL 函数

    QOpenGLFunctions 似乎缺少重要的函数 例如 glInvalidateFramebuffer 和 glMapBuffer 据我了解 QOpenGLFunctions 加载桌面 OpenGL 函数和 ES 函数的交集 如果是这样
  • OpenGL z轴指向哪里?

    我正在尝试了解 OpenGL 坐标系 我到处都看到它被描述为右撇子 但这与我的经验不符 我尝试绘制一些形状和 3 d 对象 我发现 z 轴显然指向 屏幕 而 x 指向右侧 y 指向上方 这是左手坐标系的描述 我缺少什么 编辑 例如 http
  • 有没有一种有效的方法来优化我的序列化代码?

    这个问题缺乏细节 因此 我决定创建另一个问题而不是编辑这个问题 新问题在这里 我可以并行化我的代码吗 还是不值得 https stackoverflow com questions 17937438 can i parallelize my
  • 从 CUDA 设备写入输出文件

    我是 CUDA 编程的新手 正在将 C 代码重写为并行 CUDA 新代码 有没有一种方法可以直接从设备写入输出数据文件 而无需将数组从设备复制到主机 我假设如果cuPrintf存在 一定有地方可以写一个cuFprintf 抱歉 如果答案已经
  • 无法满足显式设备规范“/device:GPU:0”,因为没有匹配的设备

    我想在我的 Ubuntu 14 04 机器上使用 TensorFlow 0 12 作为 GPU 但是 当将设备分配给节点时 我收到以下错误 InvalidArgumentError see above for traceback Canno
  • CUDA - 将 CPU 变量传输到 GPU __constant__ 变量

    与 CUDA 的任何事情一样 最基本的事情有时也是最难的 所以 我只想将变量从 CPU 复制到 GPUconstant变量 我很难过 这就是我所拥有的 constant int contadorlinhasx d int main int
  • glut 库中缺少 glutInitContextVersion()

    我正在练习一些 opengl 代码 但是当我想通过以下方式强制 opengl 上下文使用特定版本的 opengl 时glutInitContextVersion 它编译过程失败并给出以下消息 使用未声明的标识符 glutInitContex
  • 如何读取 GPU 负载?

    我正在编写一个程序 用于监控计算机的各种资源 例如CPU使用率等 我还想监控 GPU 使用情况 GPU 负载 而不是温度 using System using System Collections Generic using System
  • 如果我用opengl绘图的话SDL Renderer就没用了吗?

    我正在学习 SDL2 但我也在使用使用 OpenGL 调用的 imgui 库 从我在网上各种博客上读到的内容来看 我无法轻松混合 SDL2 渲染器和 opengl 调用 我要么使用其中之一 要么使用另一个 我读过的大多数教程都使用渲染器 所
  • 将四元数旋转转换为旋转矩阵?

    基本上 给定一个四元数 qx qy qz qw 我如何将其转换为OpenGL旋转矩阵 我也对哪个矩阵行是 向上 向右 向前 等感兴趣 我有一个四元数的相机旋转 我需要在向量中 以下代码基于四元数 qw qx qy qz 其中顺序基于 Boo
  • 在 GLUT 中使用鼠标滚轮

    我想在 OpenGL GLUT 程序中使用鼠标滚轮来放大和缩小场景 我怎么做 Freeglut 的 glutMouseWheelFunc 回调与版本相关 并且在 X 中不可靠 使用标准鼠标功能并测试按钮 3 和 4 OpenGlut 对 g
  • 将带有 glut 的点击坐标添加到向量链接列表中

    我想创建一个向量链接列表 并在 GLUT 库的帮助下获取点击的位置并将它们附加到链接列表中 这些是我写的结构 typedef struct vector int x int y Vector typedef struct VectorLis
  • GL_CULL_FACE使所有对象消失

    我正在尝试在 openGL3 3 中创建一些简单的多边形 我有两种类型的对象 具有以下属性 对象 1 10 个顶点 按顺序在下面列出 存储在GL ARRAY BUFFER并使用GL TRIANGLE FAN v x y z w v 0 0
  • GLSL NVidia 方形神器

    当 GLSL 着色器在以下 GPU 上生成不正确的图像时 我遇到了问题 GT 430 GT 770 GTX 570显卡760 但在这些上正常工作 英特尔高清显卡 2500英特尔高清4000英特尔4400显卡740MRadeon HD 631
  • Visual Studio 2010 中的 SOIL 设置

    我无法得到SOIL http www lonesock net soil html正确使用 Visual Studio 2010 我远非 VS 专家 但据我所知 只需执行以下步骤即可使环境正常运行 属性 gt gt C C gt 常规 gt
  • 在 2D 纹理上绘制的红色矩形在绘制后立即消失

    跟随我的另一个问题 https stackoverflow com questions 18477291 render an outlined red rectangle on top a 2d texture in opengl 1847
  • 存储 OpenGL 状态

    假设我正在尝试用 C 制作某种小型 opengl 图形引擎 我读过通过访问 opengl 状态glGet 函数可能非常昂贵 虽然访问 opengl 状态似乎是一个经常操作 并且强烈建议将 opengl 状态的副本存储在具有快速读 写访问权限
  • OpenGL:伽玛校正图像看起来不线性

    我使用 OpenGL 进行渲染 当我将线性值写入默认帧缓冲区 没有任何伽玛校正 时 它们在我的显示器上显示为线性 这违背了我认为我所知道的关于伽马校正的一切 如下所述 http gamedevelopment tutsplus com ar

随机推荐

  • 逻辑设备名到物理设备名的映射实现

    为了实现设备的无关性 当应用程序请求使用I O设备时 应当用逻辑设备名 但系统值识别物理设备名 所以应在系统中需要配置一张逻辑设备表 用于将逻辑设备名映射到物理设备名 逻辑设备表LUT Logical Unit Table 在逻辑设备表中
  • 使用Anaconda创建python环境 & 常见错误

    目录 使用anaconda创建python环境 1 流程 1 使用 cmd 命令打开终端 2 执行 conda 命令进入conda环境 3 执行 conda creat name 环境名 python python版本 命令创建环境 2 常
  • 在vue中使用for循环有异步请求,每次都只获取到最后一个数据解决办法

    我预想是将标签数组 dynamicTags 使用for循环取出每个值 在遍历标签数组将值一一添加到数据库中 奈何for循环结束了 才去执行put请求 这就导致了只添了数组的最后一个值 原因是axios put请求是异步请求 解决方案 使用递
  • 分析整理文献的具体步骤_VOSviewer文献综述

    文献综述在科技论文和学位论文中占据着重要地位 是论文中的一个重要且不可或缺的部分 它是研究者在对某一学科 专业或专题的大量文献进行阅读 整理 筛选 分析 综合和提炼的基础上 用自己的语言综合叙述研究状况的情报研究成果 因此 文献综述的好坏直
  • 计算宽度_桥梁有效宽度计算,看看很有用!

    有效分布宽度实质上是剪力滞效应的反应 由于目前桥梁设计多用二维平面解析 故荷载的有效分布宽度仍需要计算 不过还有很多深层次问题还不能合理解答 有待进一步研究和探讨 各中间跨正弯矩段取该跨计算跨径的0 2倍 边跨正弯矩段取该跨计算跨径的0 2
  • 回溯法-装载问题

    子集树问题 和 子集树的0 1背包问题类似 但是没有考虑价格 include
  • 【Parallels Desktop】解决Sorry, This Application Cannot Be Run Under A Virtual Machine

    问题描述 解决步骤 Win R 或Cmd R 打开 运行 窗口 输入regedit并点击 确定 打开注册表编辑器 依次展开HKEY LOCAL MACHINE HARDWARE ACPI DSDT文件夹 鼠标右键点击PRLS 选择 重命名
  • Redis第二讲 Redis数据持久化AOF和RDB

    RDB快照 snapshot 在默认情况下 Redis 将内存数据库快照保存在名字为 dump rdb 的二进制文件中 你可以对 Redis 进行设置 让它在 N 秒内数据集至少有 M 个改动 这一条件被满足时 自动保存一次数据集 save
  • 【修仙境界】等级划分

    文章目录 一 下境界 1 炼气 一共13层 2 筑基 分初 中 后期和大圆满 3 结丹 分初 中 后期和大圆满 4 元婴 分初 中 后期和大圆满 5 化神 分初 中 后期和大圆满 二 中境界 1 炼虚 分初 中 后期和大圆满 2 合体 分初
  • C++ 编程出错的地方(考试选择题易错点)

    一 int IsSvn int n if n 7 0 return 1 要判断这个数能不能被7整除 你就只返回1吗 那岂不是只返回1 没有0的情况了 应该改为 int IsSvn int n if n 7 0 return 1 else r
  • 2021年电赛模块化程序总结

    文章目录 1 ADC0804 2 LCD1602 3 AD9854 1 ADC0804 集成A D转换器品种繁多 选用时应综合考虑各种因素选取集成芯片 一般逐次比较型A D转换器用的比较多 ADC0804就是这类单片集成A D转换器 ADC
  • 9、HTML:有序列表(ol),无序列表(ul),描述列表(dl、dt、dd)详解

    1 什么是列表 什么是列表 什么是有序列表 什么是无序列表 上面写的 3 句话就是一个列表 你懂得 2 有序列表 有序列表 英文叫做 ordered list 所以标签也是取这个词组的首字母 ol ol标签括起来的范围就是有序列表的范围 而
  • Win11怎么修改c盘用户名?

    Win11怎么修改c盘用户名 不知道的小伙伴们可以学起来了 谨慎操作 以下的方法提供给你 希望对你有所帮助 Win11更改C盘user用户名教程 一 开启Administrator权限并登入 搜索框搜索cmd 右击以管理员身份运行 出现cm
  • C++每日一问:C++ 内存管理——内存泄漏及处理

    2 内存泄漏 2 1 C 中动态内存分配引发问题的解决方案 假设我们要开发一个String类 它可以方便地处理字符串数据 我们可以在类中声明一个数组 考虑到有时候字符串极长 我们可以把数组大小设为200 但一般的情况下又不需要这么多的空间
  • 唯一分解定理(分解质因子)

    唯一分解定理 每个大于一的自然数均可写为质数的积 而且这些素因子按大小排列之后 写法只有一种方式 最简单的写法 include
  • matlab绘制正弦函数、幅度调制初步、Inner matrix dimensions must agree错误

    以sin 2 f t 表达式来绘制正弦图像 必须给定数值序列才能绘制出图像 t必须给定一个数值序列 然后计算出 y sin 函数值序列 以t为横轴 y为纵轴 就绘制出了图像 先给出f 4 在这里是有几个周期 采样率Fs 100 matlab
  • flask从入门到精通,知识讲解+代码演示 day1

    flask从入门到精通 知识讲解 代码演示 day1 文章目录 flask从入门到精通 知识讲解 代码演示 day1 一 flask是什么 二 使用步骤 1 创造flask项目 2 初入flask 3 flask代码初运行 4 flask从
  • Spring Cloud实战(五)-声明式接口模块

    接着上一篇 Spring Cloud实战 四 配置中心 现在开始搭建api模块 一 声明式接口模块api 1 pom xml
  • 数学建模-相关性分析(Matlab)

    注意 代码文件仅供参考 一定不要直接用于自己的数模论文中 国赛对于论文的查重要求非常严格 代码雷同也算作抄袭 如何修改代码避免查重的方法 https www bilibili com video av59423231 清风数学建模 一 基础
  • GPU与GPGPU泛淡

    GPU与GPGPU泛淡 GPU Graphics Processing Unit 也即显卡 是一种专门在个人电脑 工作站 游戏机和一些移动设备 如平板电脑 智能手机等 上作图像运算工作的微处理器 它已经是个人PC和移动设备上不可或缺的芯片