在软件编程中,是否可以使CPU和GPU的负载均达到100%?


43

这是一个关于游戏玩家我感兴趣的主题的普遍问题:CPU / GPU瓶颈和编程。如果我没记错的话,我已经了解到CPU和GPU都可以计算内容,但是由于体系结构的差异,在某些计算中它要比另一种更好。例如,在GPU上破解哈希或进行加密货币挖掘似乎比在CPU上效率更高。

所以我想知道:难道在GPU负载为100%而CPU在50%的情况下运行GPU是不可避免的吗?

或更准确地说:如果第一个计算负载为100%,那么两者通常都达到100%的负载,那么通常由GPU完成的某些计算可以由CPU完成吗?

我已经搜索了一些关于该主题的内容,但是空手而归。我认为并希望它在本小节中有应有的地位,并欢迎您提供给我的任何文档或讲座!


53
使CPU和GPU都同时运行NO-OPs 的无限循环是很简单的,这将导致两者的负载均为100%。
约尔格W¯¯米塔格

17
遵循@Jörg的观点,唯一用CPU%衡量的是没有花费多少时间等待其他处理器。如果程序高效,则100%可能是一件好事,如果程序效率低下,则100%可能是一件坏事。很多时候,人们将注意力集中在CPU%上,就好像它是性能的度量标准—并非如此。
Mike Dunlavey

22
原始的《孤岛危机》做得很好。
CubicleSoft

5
@MikeDunlavey,您提出了一个要点。对于汽车,我们无法通过RPM衡量其性能,而是衡量速度。
曼队长

1
@JörgWMittag:也许是CPU。但是OS和GPU已暂停问题解决程序来处理无限循环。也就是说,如果着色器没有在合理的时间内完成,它将死掉并且GPU重置。
Nicol Bolas

Answers:


62

理论上是可以的,但是实际上很少值得这么做。

CPU和GPU都是图灵完备的,因此可以由一个计算的任何算法也可以由另一个计算。问题是多快和多方便。

尽管GPU擅长在大型数据集的许多数据点上执行相同的简单计算,但CPU在处理具有大量分支的更复杂算法方面却表现出色。对于大多数问题,CPU和GPU实现之间的性能差异非常大。这意味着在停顿时使用一个从另一个工作中去做并不会真正导致性能的显着提高。

但是,为此您需要付出的代价是,您需要对所有内容进行两次编程,一次是对CPU编程,一次是对GPU编程。这是工作量的两倍多,因为您还必须实现切换和同步逻辑。该逻辑极其难以测试,因为其行为取决于当前负载。期望非常模糊,并且不可能重现此特技中的错误。


1
您提到,对于大多数问题,CPU和GPU实现之间的性能差异非常大,实际上,我对性能差距在多大程度上感兴趣。您是否有关于此的任何数字或文章(例如,关于纹理3D渲染的示例)?感谢您的答复和您的时间!
MadWard

2
您可能需要补充一点,即CPU和GPU之间的同步会降低性能,因此通常希望最大程度地减少两者之间的传输次数。同样,天真地为“不要在CPU已经处理过的元素上执行”而添加分支也不会给您带来任何好处,因为GPU线程的运行是同步的。
伊桑(Ethan)2016年

3
@gardenhead Universe中没有任何东西支持无限递归,因为Universe的大小是有限的,并且信息密度是有限的。系统的“转折完整性”通常是关于消除此类约束可能发生的情况的讨论。
Random832 '16

3
我毫不怀疑,现代GPU从技术上讲至少与80年代的PC一样接近Turing完整性...但是,如果您尝试在GPU上运行常规算法,则通常会退化为顺序处理器,因此不会它比80年代的PC快,因此实际上,GPU的图灵完备性几乎比Brainfuck的图灵完备性有用。
大约

7
@leftaroundabout现代GPU 像任何CPU一样平凡地图灵。图灵完整性与:1)性能2)源代码的可读性无关。80年代与TC差不多的CPU还有其他一切:要么是TC,要么不是(后者是胡说八道)。
玛格丽特·布鲁姆

36

它与游戏编程无关。一些科学代码也可以同时使用GPU和CPU。

通过仔细而痛苦的编程(例如,使用OpenCLCUDA),您可以将GPU和CPU加载近100%。很可能您需要为GPU和CPU写不同的代码段(所谓的“内核”代码),以及一些无聊的粘合代码(尤其是将编译后的内核代码发送到GPU中)。

但是,代码很复杂,您可能需要将其调整到所运行的特定硬件,特别是因为GPU和CPU之间的数据传输成本很高。

阅读有关异构计算的更多信息。

另请参见GCC最新版本支持的OpenACC(例如,2016年6月的GCC 6


1
没错,我的标签和标题令人误解,删除了游戏并增加了性能/优化。我并不是说它是游戏独有的,但这就是我注意到的地方。我认为它也必须非常特定于硬件。感谢您的回答和链接!
MadWard

3
最终将有两种算法。我尝试了一次:一次用于GPU的整个图像,一次用于CPU的多个图像(滥用大缓存)。这确实很痛苦,尤其是要维持。
PTwr

11

从超级计算的角度来看,最好不要以百分比的形式考虑CPU / GPU的负载,而应该确定您的问题需要进行多少次操作,然后将其与系统的最高性能进行比较。

如果您获得100%的CPU利用率,则并不一定意味着您可以从系统中获得所有性能。CPU通常可以同时做多种不同的事情,例如除法和加法。如果您可以尽早开始该部门,则该部门可能会与添加部门重叠。您的台式机CPU很可能具有乱序单元,该单元将对语句重新排序,以从此类重叠中受益。或者,如果您具有以下程序:

if (expr1)
    expr2;
else
    expr3;

重新排序的CPU将尝试同时计算三个表达式然后丢弃其中一个的结果。这样总体上更快。如果您的程序中有一些阻止程序,并且您无法重新排序,则您在CPU中使用的通道数较少,但它可能仍显示100%。

然后,在CPU中具有矢量操作的SIMD功能。就像GPGPU-light一样,从某种意义上说,您通常一次只能同时进行四个或八个操作,而GPU却可以同时进行32或64个操作。

错误共享之类的东西可能会导致如此高的同步成本,通常在Linux中会以内核负载的形式显示出来。CPU已被完全使用,但是您的吞吐量没有太大用处。

我已经在IBM Blue Gene / Q机器上完成了一些编程。它具有许多层次结构级别(过时的Blue Gene / L的示意图),因此难以高效编程。您必须使用完整的层次结构直到SIMD和SMT(英特尔将其称为超线程)才能获得性能。

然后网络经常限制您。因此,事实证明,与在网络上进行通信相比,同时在多个CPU上进行计算的时间(挂钟)更快。这将给CPU带来更多负担,并使程序运行得更快。但是实际的程序吞吐量并不如原始数据所示的那样好。

如果您将GPU添加到组合中,那么将很难协调整个过程以产生性能。这将是我几个月后将在我的Lattice QCD硕士论文中开始做的事情之一。


1

您可能有兴趣查看Mozilla Research正在开发的Servo浏览器引擎,尤其是其Web Render(视频)

如其他答案(特别是@Philip)中所述,虽然将任务从CPU动态转移到GPU可能是不切实际的,但提前研究典型工作负载上的CPU / GPU负载并将某些任务切换到通常较少负载的做法是可行的。一。

在Web Render的情况下,新颖之处在于,传统上,浏览器在CPU上执行大多数渲染工作(即,CPU用于计算要显示的对象,在何处剪切等)。GPU通常更胜一筹……除了并非所有用例都能轻松实现(部分剔除,阴影,...和文本)之外,GPU还是更胜一筹。

事实证明,Web Render的初始版本在性能提升方面非常成功,但并未尝试解决文本呈现问题(并且还有其他一些限制)。Mozilla Research现在正在开发第二个版本,该版本旨在减少限制,特别是支持文本渲染。

当然,目标是将渲染过程尽可能多地卸载到GPU,让CPU可以自由执行Javascript,更新DOM和所有其他任务。

因此,尽管没有您的建议那么极端,但它确实将设计思路同时考虑 CPU和GPU 的方向。


0

着重于游戏(因为您在帖子中特别提到了游戏),可以通过一些方法来平衡负载。一个示例是“蒙皮”,即为模型设置动画。对于要渲染的每一帧,您必须为动画的每一帧生成转换矩阵,并将其应用于模型的顶点,以将其转换为所需的姿势。还必须对帧进行插值以获得平滑的运动,除非您希望动画看起来像原始的Quake(即生涩的)。

在这种情况下,您可以在CPU上执行此操作,然后将结果上传到GPU进行渲染,也可以在GPU上进行计算和渲染。我相信现在它是在GPU上完成的(称为“硬件蒙皮”):这样做很有意义,因为您必须执行数千次相对简单的计算,并且自得出结果以来,每个顶点都可以同时计算顶点A的结果与顶点B的结果无关。

但是,从理论上讲,您可以根据在GPU或CPU上过载的程度,在CPU或GPU上进行动态切换。

但是,在所有计算中执行此操作的主要障碍是CPU和GPU的优缺点不同。大规模并行作业最好在GPU上完成,而密集的带有分支的线性任务则最好在CPU上完成。在不严重影响性能的情况下,实际上只能在这两项上完成少量工作。

总体而言,GPU编程(至少使用OpenGL和DirectX 11及以下版本)的主要问题是,您几乎无法控制GPU解释着色器代码的方式。在着色器中进行分支是有风险的,因为如果您不小心在计算之间创建了依赖关系,则GPU可能会决定开始一对一地渲染像素,尽管要渲染的实际数据相同,但仍会瞬间将60fps变为10fps。


0

一个真实的例子是开源的LuxRender渲染引擎,它能够同时完全加载CPU和GPU。此外,它可以同时加载多个GPU,也可以分布在多台计算机上。

LuxRender使用OpenCL来简化此操作,尽管也存在没有OpenCL的构建。

这是可行的,因为LuxRender使用的算法是高度可并行化的。LuxRender使用的最常见算法是路径跟踪,该路径可以相互独立地计算许多单独的光路,这是GPU计算的理想情况,并且不需要计算节点之间的复杂同步。但是,GPU的局限性(较低的内存量,缺少对某些复杂渲染功能的支持以及某些美术师普遍缺乏可用性)确保了对CPU的支持仍然至关重要。


显示此图像的目的是什么,它与提出的问题有什么关系?
t

1
嗯很好 我将其删除。我当时以为它可以轻松演示它是哪种软件。但这也许真的使人分心。(有很多不同类型的渲染引擎;此引擎针对照片级的静态照片。)
PythonNut

0

是的,肯定有可能。

CPU可以执行的任何计算,GPU也可以执行的任何计算,反之亦然。

但这并不常见,因为:

  • 工程复杂性虽然可以在CPU和GPU(例如CUDA)上运行相同的代码,但这些处理器具有不同的功能和性能特征。一种是MIMD;另一种是MIMD。另一种是SIMD。一种是快的,另一种是慢的(例如分支),因此您需要编写单独的代码以最大化性能。

  • 具有成本效益的 GPU总体上比CPU具有强大的功能。GPU的全部思想是使用更便宜,更慢,但数量更多的处理器来执行计算,而执行相同的成本要远远超过CPU。GPU的成本效益提高了一个或两个数量级。

如果您让算法在GPU上运行,则针对这些GPU进行优化并添加所需的数量就更有意义了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.