进程外内存堆可以解决32位地址空间问题

时间:2013-04-16 03:39:58

标签: c++ winapi ipc out-of-memory

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

让我们假设用户拥有至少32GB的RAM(少数已经报告了64个),并希望进行大量的模拟,这使得模型比大多数游戏开发的数据都要多一个数量级的数据处理。它们当然有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访问它时,所有这些都变得奇怪。

2 个答案:

答案 0 :(得分:1)

如果你理解正确的话。

如果您使用多个进程,那么Windows仍然需要进入和退出部分。

这就是我设想的尝试方式。

使用memory mapped files映射您需要的磁盘上保留的内存空间的视图/部分。你当然需要有一些内部映射方案。

此时我不知道的关键是你是否可以从32位访问64位API。

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

答案 1 :(得分:1)

我遇到了类似的情况,GUI是32位但需要x64代码才能与系统连接。我们采用的方法是使用 WM_COPYDATA 并在魔法进程位边界上来回传递数据。当然,它没有使用dll那么快,但这不是一个选择。对于我们的用例,性能权衡是可以接受的。