游戏快报

如何不再浪费你的CPU功率

如何不再浪费你的CPU功率

作者:James Hicks(本文转自游戏邦)

不管是来自《天际》还是《矮人要塞》的所有内容都会消耗我的设备,windows会提醒我CPU功率只剩11%至13%了。在一台伴随着超线程的4核装备中,这意味着事实上剩下25%左右,可能更少一点,因为每一款游戏都在消耗我的CPU,所以所有的内容都被我的CPU限制在其最大性能中——不管是帧速率还是实际的游戏速度。

同时,我的GPU几乎都是空闲的——因为游戏受限于单核处理能力,所以它的最大潜能从未被超越。

当这种情况出现时,我的CPU便是基于4.3千兆赫运行着,这是一个合理的现代英特尔设计。所以问题并不在于我的硬件。

而是软件。部分问题是源于游戏设计。它们将所有的一切内容标记成非线程安全,似乎没人想要扩展自己的引擎去克服这一问题。

但是另外一半的问题是关于游戏开发者出于某些原因拒绝正视引擎中的一些局限,或者拒绝以全新方式去使用其它适合的核装备。

我将尽可能简单地解释我们该如何做到这两点。首先,我想要创造一些不同寻常的内容。也许许多人在这时候会说:“但是James,我们使用了其它线程。”其实你并未这么做。如果你的游戏仍然陷在一核中,那么我便不会在乎你将多小的内容,如声音处理或flibbit gibbling用于另一个线程中——从根本上看你仍然面对的是一个单一的线程应用。

strange-gas-giant(from gamasutra)
strange-gas-giant(from gamasutra)

在上图的右边是一个拥有程序生成纹理的气体巨星。比起捆绑一些我找不到适当的美术师去添加到《Ascent – The Space Game》中的纹理,我们为游戏中的每个行星和卫星(实际上有无数个)生成了纹理,并且是基于其它线程做到这点。当你的飞船更加靠近行星,线程将反复运行,创造出具有更高分辨率的纹理。

但对此还有一个技巧;《Ascent》是基于Unity引擎进行创造,这并不能让你在另一个线程去修改纹理。这里的技巧并不是关于修改火箭——Unity让你能够输入一组颜色到一个纹理中,而我们只是在另外一个线程上致力于我们的颜色数组。

这意味着有些时候,《Ascent》将同时使用两核,三核,甚至是四核,就像我们创造了一个带有一些卫星的巨大行星。这让我们可以无需影响帧速率而做到这点—-实际上在大多数硬件中,我们的主要线程通常是空闲的,你可以基于最大FPS,或者是有限的GPU。当我们在主要线程加载颜色数组到纹理时,你将会受到一定的影响,这是我不能避免的,除非Unity发现了线程。

我将提供另一个例子。

terrain-engine4(from gamasutra)
terrain-engine4(from gamasutra)

上图是我们关于一个行星表面的地形引擎。实际上这是一张有点过时的图片;今天的地形引擎版本更加巧妙,但是你能从中看到发生了什么。玩家位于底部中心位置,几乎就是在地面上,我们正从上方50公里处看着这一场景。因为这是地形引擎的显著代表,所以许多高速数字运算都在运行着。但非典型的情况是没有什么能够影响到帧速率(除了你撞见GPU放慢速度—-因为所有的那些三角形),因为我们是在另一个线程进行思考。

再一次地,Unity并未让你在另一个线程中改变网格,如上述我们的地形范围。这都必须在主线程中完成——但再一次地,我们将网格分解成一些构成数据结构(游戏邦注:至高点,三角形,法线和切线),在我们的其它线程中基于这些结构进行创造,并定期传回这一数据,在主要线程中基于它们去改变网格。

对此存在两个巨大的优势—-首先,比起每帧只能分割一些地形(游戏邦注:因为怕阻塞了主线程并减慢帧速率),我们可以根据自己的想法做任何我们想做的事。结果是我们的地形细节中的两大主要限制分别为GPU功率,以及Unity对于每65k网格的三角形的限制。

第二个优势,也是我认为真正有效的线程优势便是能够提供给我们真正无限制的CPU功率。我们可以考虑许多三角形,并且无需担心游戏的性能(只要我们不创造太多便可)。最终我们将拥有一个能够在球体上渲染某些地球般大小的内容的地形引擎,并且无需使用高度图作为元数据,因为它带有可行的CPU能够生成其自身的高度图。更棒的是,伴随着所有额外的CPU,这一地形引擎并不只是考虑地貌的形状,还会持续平衡行星的基本纹理与地形的细节——有时候纹理比地形更加详细,而有时候则相反。引擎拥有CPU grunt能够识别这点并通过着色器将其传递给GPU。这是关于我们如何在游戏中创造无数巨大的行星(要么是18百万字节要么是31百万字节,这也是取决于你是在哪个平台下载它的)的方法的一大部分。

还有一些较特殊的例子。我经常听到的便是关于AI。开发者总是会说他们的AI受限于CPU功率。如今少于两核的手机已经很少了。当我们着眼于AI时发现,它带有两个层面(MMO带有三层,但在这里为了更简单地说明我选择了两层)——“活跃的”AI将处理实际的移动,射击,机器人/人/坦克/船只/飞机等等的控制,然后还有“战术”或“思考”AI——即没人编码的部分,因为不存在可行的CPU功率?

combat1(from gamasutra)
combat1(from gamasutra)

想象如果存在无所事事的完整的核,只是等着开始思考面对你的AI的完整境况的话会怎样?想象如何那些核能够基于一定深度去思考每种境况,而不会影响帧速率的话会怎样?好吧,你并不用想象任何内容,这都是真实发生的境况。

暂时不考虑服务器AI,《Ascent》便是基于这种方式去管理本地客户端AI。在任何特定时刻,一艘NPC舰船将拥有一个暂时的任务,或者一个同时包含两件事的任务模式。它将始终保持移动,为自己树立一个更困难的目标,但是它的移动可能是100%在逃避,同时它将装载自己的武器或盾牌,它有可能真的逃走或者展开攻击。

如果它将展开攻击,那么它会使用怎样的武器瞄准你?如果选择了逃避,那么它会选择朝哪个方向远离你?它又会何时回来攻击你并瞄准哪里?它会在何时判断自己输掉战斗并逃离这里?它是否会为了细调控制中拥有重力锚或为了抵消其横向速度,或消灭最大加速度?好吧,这些问题都是基于战术—-如果你能够好好思考线程便能够得到答案。

每隔四分之一秒,思考线程便会与主线程进行交流,并潜在地改变其当前的互动模式,目标,以及与你的距离,它所使用或不适用的武器。然后它将回来分析任何深度的情景和我们想要看到的细节。对于未来,这意味着你可以保持加载情报到我们的本地AI并无需担心帧速率。这代表某些与我们的服务器完全不同的内容,但这并不是今天我们要讨论的话题。

这是如何影响我们的AI?再一次地让我们暂时不要考虑服务器,实际上这是为了让《Ascent》的太空战斗能够更适合人类游戏,所以我必须严格地牵制AI的舰船。这是对的,比起让我们的AI像其他人那样作弊,我必须将所有优势呈现在玩家面前。AI可以基于一小部分的速度移动并转向——在更高端的战斗中们如果你眨眼,你便会输掉比赛。我尝试着基于同样的条件与AI战斗,尽管作为开发者,我却发现很难战胜它。它的性能近乎完美。它从未犯错,它总是会在我的大脑反应过来钱便对任何情况变化做出回应。结果便是在《Ascent》中与一个NPC战斗更像是在其它游戏中与人类对手战斗。这更具有沉浸感,且具有更大的挑战性。

所以追根究底的话—-执行线程到底有多难?在我看来,如果你保持它的简单性的话倒是会很轻松。这比只是在主线程中完成所有内容复杂些,但却比将所有内容添加到主线程后尝试着优化一款复杂游戏来的简单。我想要给你们的一点建议便是,当你在执行线程时最好跳到严格的OO盒外进行思考。暂时将所有的一切当成数据和指令,如此你将获得更多直觉感—-可能因为这便是CPU核如何思考一切内容的原因。从根本上看来你正在撕掉一层抽象内容,这是有帮助的,因为搞砸线程将是一场噩梦,当你将其搞砸时,你便会希望这场噩梦能够简单些,且更短些。

我每次遵循的过程都很简单:

1.为主线程和派生线程设置数据结构进行分析。包含告诉所有人哪些内容现在与数据混合在一起的bool。当派生线程完成了自己的任务时,bool便是关于主线程如何知道是否该打开其“圣诞礼物”。

2.创造一个线程并提供给它一个使用代码。再一次地,关于大部分内容的主要功能代码似乎能够让这些内容变成更简单且更加直接,至少对于我来说是这样的。我倾向于使用低优先级,以阻止它们搞砸主线程和帧速率,即使我们需要确保它们同时运行。

3.将我们的bool设置为true

4.开始线程

5.主线程将让步,同时bool将与其相对立

6.派生线程大幅度上升(有时候会让步,但99%的情况下你是不可能放慢速度,因为有许多未使用的CPU grunt,你很快就会恢复。我知道有些人认为如果你的优先顺序设置合理的话是不需要让步的,这也是一个可爱的理论)

7.派生线程完成并将bool设置为false,并知道bool恢复后才算真正完成或让步(取决于你是否想要控制它)

8.在下一帧,主要的线程将看到boot为false,并获取其全新的处理数据

从本质上来看就是这样。在调试过程中会出现一些烦人的事——一些经典的错误代码将阻止它们脱离你的派生代码,但对此也存在一些解决方法。首先你需要确定的是不能跨越数据流——有时候将出现一个线程致力于我们的共享数据结构中。在某些安全的线程结构中你可以打破这一规则(如果你想这么做的话),但我还未找到需要这么做的情况。我们的AI代码的主线程是源自思考线程的变量,这也是我最想打破这些规则的时候。

还有其它方法能够处理线程间的交流,但我发现这一单纯的过程是最简单可靠的。在运行线程时,我希望遇到的漏洞能够尽可能的简单。

所以这是如何帮助《天际》?我并不确定,因为我从未尝试着去描述这款游戏是面向哪些内容使用其主要线程。可能其地形引擎是其中的一部分内容。也有可能《天际》规定如果AI拥有其自身的核便能够拥有更高级的功能。

另一方面,《矮人要塞》可能延伸了10个线程,并在这之间传播矮人和其他角色,从而戏剧性地加速了游戏的帧速率。

总之,我希望在未来,当玩别人的游戏时我的CPU能够超过13%。也许这一天很快就会到来。