您的位置:首页 > 其它

真实案例分析:游戏线程处理,在英特尔® 处理器上获得高性能

2013-12-29 23:04 731 查看
(未验证) 于 星期日, 11/05/2008 - 17:06 提交

介绍

作者:英特尔公司软件解决方案事业部 Sara Sarmiento

您为何需要对游戏进行线程处理?并行性是在多平台上实现扩展的最简单、最经济高效的方式。当处理器可支持多线程时,对软件应用执行线程具备固有的性能优势。单处理器系统中很难体现线程的性能优势,因为在执行这一进程或交换进出的线程时,成本相当高昂。但是,在支持多线程的处理器(比如市场上现有的几种处理器)上进行线程,可为线程应用带来诸多优势。通过线程代码库,应用可更充分地使用在利用中的硬件资源。线程还使应用可在下一代多核处理器进行扩展,并支持线程应用。随着硬件的发展和持续改进,线程软件的性能也将不断完善。

前言

并行性有两种不同的形式,一种是域分解(数据级并行性),另一种是功能分解(任务级并行性)。数据级并行性是指对不同系列的数据执行相同独立的操作。任务级并行性是指独立的工作被映射至不同的线程上异步执行。该篇将详细探讨这些方式,并将以游戏引擎和游戏字幕(它们通过在应用中引进线程会获得显著的性能优势)为例来进行说明。

数据级并行性

描绘一下当地一家快餐公司的车道服务窗口。现在,假设有一排车在等候点菜,付账、取快餐。如果是一排车队在一个窗口如此等候,要比分两队在两个窗口耗时的多。由此吞吐量可能增加至近两倍。同样,该原理可以应用到通过数据级并行性执行的数据处理中。



数据根据处理器可处理的线程数划分为 N 个分区,以此来提高指令吞吐量。将数据分配到线程有静态和动态两种不同的分配方式。在静态分配方式中,迭代被分为大小为 chunk_size 的多个数据块,这些数据块按线程号码顺序以轮询方式静态地分配至组中的线程。注意,最后分配的数据块可能有较少的迭代。

当数据块数目不确定时,迭代空间将被分为近似相同大小的数据块,每个线程至多分配一个数据块。

在动态分配方式中,迭代被分为数据块大小和数据块数目,当线程要求时每个数据块才被分配。线程执行迭代的数据块,然后请求另一个数据块,直至再没有需要分配的数据块。注意,最后分配的数据块可能有更小数目的迭代。(OpenMP* 规范)静态分配形式的 CPU 费用很低,动态分配的 CPU 费用要稍高一些,但它提供了潜在的更好的工作负载平衡。以下是两个案例研究,采用的是在解决方案中执行数据并行性而获得显著的性能优势的游戏引擎。

案例研究:

Codemasters/SixByNine Colin McRae Rally 4*,原名为 Xbox*,它是一个在 PC 机上的不在路面驾驶模拟。为支持多平台运行,设计了 3D 引擎,但从建筑学层次很难改变游戏的设计。开发商的目的是找到一个引擎的具体部件来从数据级并行性获益,而不影响周围的代码。确定线程的部分是天气系统的计算,用以增加 3D 引擎产生粒子的数量。

天气系统由两个获益于数据级并行性的环路组成。第一个环路用来计算每个帧的新位置,第二个环路用来决定引擎产生离子在周围地形情况下的碰撞。为了在这些环路中执行线程,该游戏的开发商取消了粒子产生环路所有的全局变量,然后设置局部变量以避免数据使用时的竞态状态。通过使用带英特尔® 编译器的高性能可用设置,环路的速度性能增加了 5%。粒子系统内的数据级并行性使天气系统的速度又另外提高了 7-8%。开发商也使用了英特尔® 线程分析器,用它来检查线程应用中的负载不平衡情况以及所有同步开销。



利用优化的速度提升和个人电脑上超线程(HT)技术中更高的时钟速度,开发人员能够将受粒子影响区域的运行速度提升 4 倍,与游戏最初的 Xbox 版本相比,粒子的密度增加
8 倍。

这样,在游戏中就产生了更加出色的视觉效果。

任务级并行

设想一下,如果更早的推行车道服务窗口(drive-thru window),就无需为两条车道设立两个不同的窗口。在快餐车道服务流程中,每个窗口负责不同的工作。第一个窗口负责在开始处接收定单和付款,第二个窗口则同时将订单分发给用户。



一般来说,性能的优势由线程之间的数据独立性和负载平衡确定。如果在一种线程应用中,一条线程执行的任务远远多于其它线程,那么,该应用几乎不会获得性能增益。这依赖于软件设计师和开发人员对于在应用中处理任务的方式,以及在线程中平均分配这些任务的理解。在以下游戏应用示例中可以看到,他们的解决方案中支持多线程(执行任务级并行)的处理器上所获得的性能优势。

案例研究:Lego/Argonaut Bionicle*

Bioncle 是由 Lego 公司推出的第三人称动作类游戏,该游戏由 Argonaut Software 公司开发,与 Lego 公司专利玩具具有相同的名称。


在不同的线程上运行 Bioncle 游戏。主线程用于更新空间并进行渲染。工作线程用于处理“更新天空”。天空中有很多云层(一般为两层,但可能多达四层)。每一层对应一个线程,如下图所示。



主游戏界面很简单,因为他们仅需要将消息传达给 Update Sky Module(更新天空模块),以便在渲染时对图形和纹理进行更新。根据主游戏线程的命令,资源加载器继续传输数据。

该游戏的性能优势是,它在电信设备制造商(TEM)之间建立了通用的代码,并且能够降低代码复杂性。此外,资源加载器和解压处于不同的线程上,可通过多线程封锁的 I/O 获得额外的性能增益。

关键问题是它们使用常规的阻断 IO 操作系统调用,但只发生在次级线程上。大多数操作系统支持交迭 IO 或无阻断 IO,但这些执行情况与 API(应用编程接口)的执行情况差别很大。在这种情况下,线程用于文件加载,以便为 Win9X* 和 Windows* XP 提供一个通用异步的 API。这种方法的缺点是中止文件加载操作十分困难,这将对程序随机交换流数据的能力产生影响。

案例研究:Codemasters/1C/KD-Lab

Perimeter* 是一部先进的科幻即时战略游戏。它具有深入刻画的现实主义场景、建筑物和游戏单元,在这些单元里,地形不断地重整并发生变化,从而提高玩家的游戏体验。

当仅可利用一个处理器时,该游戏利用单线程通过 CPUID 进行检测。当检测到两个或多个处理器时,它利用两个线程。

在单线程模式中,如下图所示,“更新空间”和“渲染”出现在相同的线程上。在多线程案例中,游戏逻辑中的“更新空间”和 AI 在单独的线程上运行,以便来渲染引擎 — 包括渲染和用户界面。


在更新图形数据之前需要对线程之间要求数据独立性的线程方法进行处理和并行。“更新空间”中的逻辑需要将适当的变化传达给逻辑对象,以渲染引擎,这样,这些变化将被传输至“更新缓冲器”,然后在下一个时间间隔内被更新。GUI
内所有相关的逻辑信息也需要更新,同时,玩家的活动也在“更新空间”中进行批处理并发送至逻辑单元,以便对这些变化进行处理。

线程处理的结果是,在采用超线程(HT)技术的系统中,“更新空间”和“渲染空间”游戏的帧速率能够提高 25-50%。除了帧速率获得提高外,线程处理渲染的负面影响是帧速率变得越来越统一。当评估用户最终体验时,一定会在限定其是否为最重要的因素时引起争议。在多线程设计的单线程系统中,在渲染帧之间连续调用“更新空间”时,帧速率会上下波动。这不再是帧速率主要取决于逻辑控制时间的情况。

逻辑和 GUI 之间的同步并不简单,依赖性会限制可获得的性能数量。尽可能少地减少同步开销的数量,并确保线程之间的平衡将会获得最佳结果。一种简洁的模块化设计将帮助分离线程之间需要进行同步化的重要数据。

案例研究:Virtools* Dev 2.1

Virtools Dev 2.1 是一种 3D 编辑工具,在 3D 引擎和游戏的部署中使用。在这个特殊的示例中,我们关注“更新空间”,但对粒子系统尤其关注。

下图为引擎的原始设计。在“更新空间”中,需要确定是否在渲染屏幕对象之前在“粒子系统”上进行重要的计算。


任务级并行用于对该应用进行线程化。在主线程上进行“更新空间”计算,工作线程用于计算“粒子系统”。

当正在计算“粒子系统”时,“更新空间”会继续执行其渲染。直到“粒子系统”渲染和结果同步化后,时间 t+1 的渲染便结束。需要指出的是,该系统下的渲染系统(DirectX* 或 OpenGL*)都无需在多线程模式下运行。

在次线程上构建粒子的原始列表并按字母排序,但主线程上仍能够进行渲染。



如果负载不平衡,则会对利用这个模块的情况发出警告。如果“更新空间”上的计算超出“粒子系统”的计算范围,那么引擎就不会获得显著的性能增益,反之亦然。但对于 Virtools 而言,每个线程上分配的工作相对平衡,支持多线程的处理器就能获得显著的性能增益。您会在最需要的时候——也就是,突然受到较大的粒子触发影响时获得最佳的性能增益。

如下图所示,Virtools Dev 2.1 应用在采用超线程(HT)技术的系统中实现了 13% 的性能增益,在双处理器系统上则获得了 33% 的性能增益。



图:采用超线程(HT)技术的戴尔 Dual 2.2 GHz Xeon 处理器;512MB 内存;NVIDIA GeForce* 3 64MB;处理器配置 BIOS 转换(SP、HT、DP)

案例研究:期待交互式的 Lejendary Adventures*

Lejendary Adventures 游戏由 Dreams Interactive 开发***。

在这个游戏的设计中,开发人员在支持多线程的处理器上对应用进行了有效地线程化和扩充。

在这个游戏中,“更新空间”被分解为两个线程,第一个处理“更新空间”中的渲染,另一个则处理 DirectX 3D 渲染。


与英特尔合作后,他们通过创建第三条线程处理“地形”和“程序上的纹理”,使其作为来自“更新空间”线程的单独任务,获得额外的性能增益。



这样做能够使该游戏在采用超线程(HT)的处理器和双处理器系统上获得额外的性能增益。采用超线程(HT)的处理器后,该游戏可获得 19% 的性能增益,在双处理器系统上则可获得 24% 的性能增益。



图:采用超线程(HT)技术的戴尔 Dual 2.2 GHz Xeon 处理器;512MB 内存;NVIDIA GeForce* 3 64MB;处理器配置 BIOS 转换(SP, HT, DP)

案例研究:SCI / Pivotal Conflict Vietnam*

Conflict Vietnam 是一个每秒帧数(FPS)游戏,该游戏发生在越南的丛林地区。该游戏包括在不同的地理环境下需要完成的不同任务,如密林战和水战。该游戏使用切割边缘图形技术,如利用 DirectX 9 对光晕和景深进行修饰。

在原始的游戏设计中,主线程执行逻辑和渲染操作,同时单独的线程实现压缩的音频的混频。由于主线程发出的命令,利用较低开销的临界区(Critical Section)保持音频线程轻便,并对其进行处理,因此两个线程之间的同步开销保持就可最低值。在 PC 上,程序上的天空纹理渲染在单独的工作线程上执行,这样就替代了单核处理器电脑上使用的静态纹理。


这个游戏的开发人员利用英特尔® 线程分析器来识别线程执行中的区域,这种执行能够被合理地调整。对于程序上的天空,当天空纹理为高精度或“更新空间”的计算尤为轻便时,线程分析器显示出主线程受到“更新天空”线程的阻断。由于对更新天空例程进行线程化,在主线程中对天空纹理进行计算需要花费更多的计算,因此,为了进一步提高线程性能,采用的解决方案是缩短主线程中的阻断时间。与线程相比,“更新天空”仅与游戏逻辑相对应,“更新空间”中调用的“渲染空间”和游戏逻辑并行作用下的线程被更改。



在采用超线程(HT)技术的系统中,与有序性为 25% 的程序上的天空相比而言,执行线程的此次变化提高了 15% 的性能,进而获得了整体的性能提高。此外,与执行原始的静态纹理相比,通过感官体验天空的效果,程序上天空的变化支持更有效的控制。

结论

在游戏中采用线程技术并非易事。就技术和商业观点而言,几种因素确定线程是否可行。在现有的应用中,一般来说,执行线程需要高水平的设计更新。当规划未来的发行版本时需要融入这种思路,这将帮助我们充分利用下一代处理器。请谨记代码基础本身也需具有灵活性和模块化,从而支持线程的推出。游戏引擎的设计具有有序性,并包含多个全局变量;模块之间的数据相关性很难被线程化。

现在的处理器已能够支持多线程技术,并且在未来一代英特尔台式机处理器中将持续支持这种技术。很重要的一点是,您需要理解基础架构以及它处理指令的方式,从而能够充分利用多处理器的性能。能够实现这一目标的方式之一是,使用英特尔产品并研究英特尔的技术软件支持站点,从而发现充分利用英特尔台式机处理器多线程性能的技巧和技术。

更多参考

OpenMP 体系结构评审委员会(OpenMP Architecture Review Board)、OpenMP C 和 C++ 应用编程接口,pp13。/sites/default/files/m/c/2/2/cspec20.pdf


作者简介


Sara Sarmiento 是英特尔公司软件解决方案事业部的技术营销工程师。奥尔良州立大学毕业后,Sara 拥有计算机科学专业理学学士学位。她于
2000 年 10 月加入英特尔,目前倾力于研究面向当前和未来一代客户机台式机处理器的软件支持。

View
entire article (PDF 199KB)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: