4

问题:大型模拟游戏有大量不同的对象,必须跟踪、更新和用于视觉渲染和逻辑模型更新。只有 4 GB 的地址空间,您只能将这么多的东西放入内存中。如果你求助于磁盘,事情就会开始变慢,除非你很幸运并且不断地访问页面缓存。但即便如此,当文件系统同步到磁盘时,进行大量更新/写入的成本也会很高。

假设用户至少有 32GB 的 RAM(有些人报告说 64GB)并且想要玩一个巨大的模拟,导致模型携带的数据比游戏开发的大多数东西要处理的数据多一个数量级。他们当然有 64 位操作系统(比如说,Windows 7 x64 或 Windows 8 x64)。自然,如果您只是将所有这些模型数据存储在进程中的虚拟地址空间中,即使使用大地址感知,您也会遇到内存不足的情况,即使主机有千兆字节和千兆字节的空闲RAM(因为32 位进程超出虚拟地址空间(VAS))。

我们还假设,由于完全无法控制的原因,您不能将主二进制文件设为 64 位。你依赖于一些专有框架,花费了可笑的工时来编写该框架,并且必须从一开始就重新开始以转移到其他东西。您的框架仅提供 32 位版本,因此您被卡住了。

正确的?

也许。

我有一个随机的想法,这似乎是一个很远的想法,因为我不知道我是否可以让它变得高效或实用。

如果我可以创建一个 64 位子进程,它就能够使用尽可能多的 RAM,无论是今天任何人都可以买得起的内存并插入主板,即使是在非常高端的服务器机箱上也是如此。

现在,我希望能够有效地从模型中存储和检索大量数据,这些数据已被推入子进程,并且不时将这些数据的子部分复制到子进程中。所以基本上,所有千兆字节荣耀的“主”模型(一系列非常巨大的树状和哈希表结构)将位于 64 位进程中,而 32 位进程将在那里窥视,抓住一个大块数据,用它做一些事情(或者我应该让子进程在那里进行一些处理以将其提取出来??),然后摆脱它 - 以保持 32 位进程中的内存使用可管理.

所有模型读取/变异/模拟算法都基于模型在本地进程中可用的假设,因此随机数组访问之类的事情很常见。我很难将我的访问模式从主模型中提炼成几个基于块的顺序读取,而且遍历整个模型也不是很罕见。

我的目标是:

  • 防止该死的东西由于内存不足而崩溃(#1目标)
  • 性能(非常接近 #2,但使用极端复杂性的人可能会接受比模拟更小、更简单游戏的人更差的性能)
  • 现有代码的最小重构(或多或少带有渲染调用和多线程的 vanilla C++)

这似乎是一个相当艰巨的项目,因为从一个连贯的内存模型到必须从一个比我任何时候都能抓住的大得多的模型上看一个孔径,可能需要进行大量的算法重新设计。

我的问题:

  • 这样做有没有先例?
  • 这将如何在 Windows 上最好地完成?是否有某种像 Linux 上的共享内存,或者轻量级的非常高带宽的随机内存访问 IPC,可以通过类似operator[]()实现的东西集成到 C++ 中?
  • 任何 IPC 的性能是否会如此糟糕以至于不值得尝试?我是否应该只依赖磁盘(您知道,数据库或键值或其他)并让操作系统/文件系统弄清楚如何使用 RAM?

请记住,我需要支持非常“健谈”的 IPC 机制,因为许多处理算法(AI 等)都是围绕小内存访问和更新设计的。这在进程中运行得很好,甚至对缓存局部性也有一些关注,但是当您通过 IPC 访问它时,这一切都变得很奇怪。

4

2 回答 2

1

如果正确理解你。

如果您使用多个进程,则窗口仍需要将这些部分分页进出。

这就是我想尝试的方式。

使用内存映射文件来映射您需要的保留在磁盘上的内存空间的视图/部分。您当然需要有一些内部映射方案。

目前我不知道的关键是您是否可以从 32 位访问 64 位 API。

Windows 将神奇而有效地处理分页。无论如何,这就是它对内存映射虚拟内存的作用。我们曾经使用它来处理早期 32 位 NT 系统上的大量数据集,并且该技术可以正常工作。

于 2013-04-16T03:44:21.760 回答
1

我和你的情况类似,GUI 是 32 位的,但需要 x64 代码才能与系统交互。我们采用的方法是使用WM_COPYDATA并通过神奇的进程位边界来回传递数据。自然,它不如使用 dll 快,但这不是一个选择。对于我们的用例,性能折衷是可以接受的。

于 2013-04-28T04:52:41.527 回答