22

我不太了解商业游戏在内部是如何运作的,但我遇到的开源游戏似乎并没有大量使用线程。大多数其他桌面应用程序也是如此,通常似乎使用两个或三个线程(例如程序逻辑和 GUI 更新)。

为什么游戏没有很多线程?例如,物理、声音、图形、AI 等的单独线程?

4

10 回答 10

25

我不知道你玩过哪些游戏,但大多数游戏都在单独的线程上运行声音。网络代码,至少套接字侦听器在单独的线程上运行。

但是,游戏引擎的其余部分通常在单个线程中运行。这是有原因的。例如,游戏中的大多数处理都运行一个依赖链。图形取决于物理引擎的状态,人工智能也是如此。为多线程设计意味着您必须在各个子系统之间设置帧延迟以实现并发。如果这些子系统在每一帧中线性计算,您将获得更快的响应时间和更快的游戏体验。游戏中从并行化中受益最多的部分当然是渲染子系统,它被卸载到高度并行化的图形加速卡上。

于 2009-02-21T00:35:19.200 回答
15

主要原因是,尽管听起来很优雅,但在像 3D 游戏一样复杂的程序中使用多个线程确实非常非常困难。此外,在最近引入低成本多核系统之前,使用多线程并没有提供太多的性能激励。

于 2009-02-21T00:32:28.240 回答
15

你需要想一想,线程的实际好处是什么?请记住,在单核机器上,线程实际上并不允许并发执行,只是对它的印象。在幕后,CPU 在不同线程之间进行上下文切换,每次都做一些工作。因此,如果我有几个不涉及等待的任务,并发运行它们(在单个内核上)不会比线性运行它们快。事实上,它会更慢,因为频繁的上下文切换会增加开销。

如果是这样的话,为什么还要在单核机器上使用线程呢?首先,因为有时任务可能需要长时间等待某些外部资源(例如磁盘或其他硬件设备)变得可用。当任务处于等待阶段时,线程允许其他任务继续,从而更有效地利用 CPU 的时间。

其次,任务可能有某种完成的最后期限,特别是当它们响应事件时。典型的例子是应用程序的用户界面。计算机应该尽可能快地响应用户操作事件,即使它正忙于执行一些其他长时间运行的任务,否则用户会变得烦躁并可能认为应用程序已经崩溃。线程允许这种情况发生。

至于游戏,我不是游戏程序员,但我的理解是这样的:3D游戏创造了游戏世界的程序化模型;玩家、敌人、物品、地形等。这个游戏世界会根据自上次更新以来经过的时间以离散的步骤进行更新。因此,如果自上次游戏循环以来已经过去了 1 毫秒,则通过使用其速度和经过的时间来确定 delta 来更新对象的位置(显然物理比这要复杂一些,但你会得到主意)。AI 和输入键等其他因素也可能有助于更新。当一切都完成后,更新的游戏世界被渲染为一个新的帧,这个过程又开始了。这个过程通常每秒发生多次。

当我们以这种方式考虑游戏循环时,我们可以看到引擎实际上正在实现与线程非常相似的目标。它有许多长时间运行的任务(更新世界物理、处理用户输入等),并且通过将它们分解成小块并交错排列,给人的印象是它们是同时发生的,而不是依赖于CPU或操作系统来管理每个花费的时间,它自己做。这意味着它可以保持所有不同的任务正确同步,并避免真正线程带来的复杂性:锁、抢占、重入代码等。这种方法也没有性能影响,因为正如我们所说无论如何,单核机器只能真正线性地执行代码。

当拥有多核系统时,情况会发生变化。现在,任务可以真正并发运行,使用线程来处理游戏世界更新的不同部分确实有好处,只要我们能够设法同步结果以渲染一致的帧。因此,我们预计,随着多核系统的出现,游戏引擎开发人员将致力于此。事实证明,他们是。Valve,Half Life 的制造商,最近在他们的 Source Engine 中引入了多处理器支持,我想许多其他引擎开发人员也会效仿。

嗯,结果比我预期的要长一点。我不是线程或游戏专家,但我希望我没有犯任何特别明显的错误。如果我有我相信人们会纠正我:)

于 2009-02-21T01:43:09.987 回答
14

如今,许多游戏都在使用“任务”或“作业”系统进行并行处理。也就是说,游戏会产生固定数量的工作线程,用于多个任务。工作被分成小块并排队,然后在工作线程可用时发送给它们进行处理。

这在游戏机上变得尤为普遍。PS3 基于 Cell 架构,因此您需要使用并行处理来获得系统的最佳性能。Xbox 360 可以模拟为 PS3 设计的任务/作业设置,因为它具有多个内核。您可能会发现,对于大多数游戏来说,很多系统设计在 360、PS3 和 PC 代码库之间共享,因此 PC 很可能使用相同的策略。

虽然很难编写线程安全代码,但正如许多其他答案所表明的那样,我认为您所看到的事情还有其他一些原因:

  • 首先,许多开源游戏已经有几年历史了。尤其是在这一代控制台中,并行编程正变得流行,甚至是必要的,如上所述。
  • 其次,似乎很少有开源项目关心获得尽可能高的性能。正如 John Carmack 在犹他州 GLX 项目中指出的那样,高度优化的代码通常比未优化的代码更难维护,因此后者通常在开源环境中更受欢迎。
  • 第三,我不会认为游戏创建的少量线程意味着它没有很好地使用并行作业。
于 2009-02-21T10:04:35.587 回答
1

我正要发布与威廉相同的内容,但我想稍微扩展一下。为未来编写最佳代码非常困难。考虑到编写可以扩展到您没有的硬件的东西与编写可以在您拥有的硬件上运行的东西之间的选择,大多数人会选择后者。由于单核范式已经存在了很长时间,因此大多数已编写的代码(尤其是对于有极大压力的游戏)都不是未来的证明。

x86 对游戏程序员非常友好,因为我们不必考虑不太宽容的硬件平台的后果。

于 2009-02-21T00:39:16.227 回答
1

除了多核编程的技术挑战之外,商业游戏必须在没有多核的低端系统上运行良好才能赚钱。

既然多核处理器已经出现了一段时间,并且主要的游戏机都有多核,那么双核出现在 PC 游戏的最低系统要求列表中只是时间问题。

这是来自英特尔的 Orion Granatir 采访的链接,他谈到让游戏开发人员利用多线程。

于 2009-02-21T01:31:40.513 回答
1

这里的每个人都正确地声称多线程很难,这一事实非常可悲。我们迫切需要简化并发系统。

我个人认为我们将需要范式转变和新工具。

于 2009-02-21T01:34:05.580 回答
0

使用大量线程时,竞争条件和数据锁定存在许多问题。由于游戏的不同部分相互依赖,因此进行使用大量线程所需的所有额外工程没有多大意义。

于 2009-02-21T00:37:09.833 回答
0

毫无问题地使用线程是非常困难的,而且大多数 GUI API 无论如何都是基于事件驱动的编码。线程要求使用锁定机制,这会增加代码的延迟,并且该延迟通常是不可预测的,具体取决于当前持有锁的人。

对我来说,让单个(或者可能很少)线程以事件驱动的方式处理事物而不是数百个线程都导致奇怪和不可重复的错误似乎是明智的。

于 2009-02-21T00:49:08.650 回答
0

线程已经死了,宝贝。

实际上,在游戏开发中,线程除了卸载非常专用的任务(如网络和加载)之外,并没有扩展。作业系统似乎是唯一的出路,因为 8 CPU 系统甚至在 PC 上也变得越来越普遍。而且您几乎可以保证即将推出的超多核系统(如英特尔的Larrabee )将基于作业系统。

这对于 Playstation3 和 XBOX360 项目来说是一个有点痛苦的认识,现在看来,甚至苹果公司也加入了他们在雪豹中的“革命性”中央调度系统。

线程有它们的位置,但是“把所有东西都放在一个线程中,它会运行得更快”的天真承诺在实践中根本行不通。

于 2009-06-16T04:44:44.997 回答