c++ - 在 64 位(或 32 位)Windows 上以 32 位进程访问 >2,3,4GB 文件

标签 c++ windows memory-management out-of-memory memory-mapped-files

免责声明:我为这个问题的冗长道歉(虽然我认为这是一个有趣的问题!),但我不知道如何更简洁地表达它。

我已经对解决在 64 位 Windows 7 上的 32 位进程中访问多 GB 文件的问题的显然无数方法进行了数小时的研究,范围从 /LARGEADDRESSAWAREVirtualAllocEx敬畏。我对在 Windows 中编写多 View 内存映射系统(CreateFileMapping、MapViewOfFile 等)感到有些自在,但仍然无法完全摆脱对这个问题有更优雅的解决方案的感觉。此外,我非常了解 Boost 的进程间和 iostream 模板,尽管它们看起来相当轻巧,需要类似的努力来编写仅使用 Windows API 调用的系统(更不用说我已经有了内存的事实-使用 Windows API 调用半实现的映射架构)。

我正在尝试处理大型数据集。该程序依赖于预编译的 32 位库,这就是为什么目前该程序本身也在 32 位进程中运行,即使系统是 64 位,具有 64 位操作系统。我知道有很多方法可以围绕这个添加包装库,但是,鉴于它是更大代码库的一部分,这确实是一项艰巨的任务。我设置了二进制 header 以允许 /LARGEADDRESSAWARE (以减少内核空间为代价?),这样我每个进程可以获得大约 2-3 GB 的可寻址内存,给予或接受(取决于堆碎片等)。

问题是:数据集是 4+GB,并且在它们上面运行 DSP 算法,这些算法基本上需要对文件进行随机访问。指向从文件生成的对象的指针在 C# 中处理,但文件本身在 C++ 中加载到内存中(使用这个部分内存映射系统)(它是 P/Invoked)。因此,不幸的是,我认为该解决方案并不像简单地调整窗口以访问我需要访问的文件部分那么简单,因为本质上我仍然希望将整个文件抽象为一个指针,我可以从中调用方法访问文件中几乎任何位置的数据。

显然,大多数内存映射架构依赖于将单个进程拆分为多个进程..因此,例如,我将访问一个 6 GB 的文件,其中包含 3 个进程,每个进程持有一个 2 GB 的文件窗口。然后,我需要添加大量逻辑来从这些不同的窗口/进程中提取和重新组合数据。 VirtualAllocEx显然提供了一种增加虚拟地址空间的方法,但我仍然不完全确定这是否是最好的方法。

但是,假设我希望这个程序像 64 位系统上的单一 64 位进程一样“轻松”地运行。假设我不关心抖动,我只想能够操作系统上的一个大文件,即使任何时候只有 500 MB 加载到物理 RAM 中。有没有办法获得这个功能而不必手工编写一个有点荒谬的手动内存系统?或者,有没有比我迄今为止通过结合 SO 和互联网发现的更好的方法?

这就引出了一个次要问题:有没有办法限制此进程将使用多少物理 RAM?例如,如果我想限制进程在任何时候只将 500 MB 加载到物理 RAM 中(同时将多 GB 文件保持在磁盘上分页)怎么办?

对于这个长问题,我很抱歉,但我觉得这是对我在 SO 和整个网络上发现的许多问题(只有部分答案)的一个不错的总结。我希望这可以成为一个明确答案(或至少一些优点/缺点)的领域,我们都可以在这个过程中学到一些有值(value)的东西!

最佳答案

您可以编写一个访问器类,并为其提供基地址和长度。如果出现错误情况(越界等),它会返回数据或抛出异常(或者您想通知错误情况)。

然后,任何时候您需要从文件中读取,访问器对象都可以使用 SetFilePointerEx() 调用前 ReadFile() .然后,您可以将访问器类传递给您在读取文件时创建的任何对象的构造函数。然后对象使用访问器类从文件中读取数据。然后它将数据返回给对象的构造函数,该构造函数将其解析为对象数据。

如果稍后您可以编译为 64 位,则只需更改(或扩展)访问器类即可从内存中读取。

至于限制进程使用的 RAM 量.. 这主要是确保
A)您没有内存泄漏(尤其是淫秽的)并且
B) 销毁您目前不需要的对象。即使您稍后需要它,但数据不会改变......只需销毁对象即可。然后在您需要时重新创建它,允许它从文件中重新读取数据。

关于c++ - 在 64 位(或 32 位)Windows 上以 32 位进程访问 >2,3,4GB 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15797341/

相关文章:

.net - 混合托管/非托管程序集加载顺序

c++ - 使用析构函数删除动态对象? C++

algorithm - 优先分配算法如何减少内存碎片?

c++ - 计算两个等长字符串之间的不同字符数

c++ - 连续内存分配

c++ - 为什么我的游戏场景是白色的?

windows - 如何从命令提示符快速打开当前目录?操作系统 - Windows

c++ - C++ 中基于前向的光线追踪器

c++ - 错误 undefined reference `BP::Device::Create(std::string const&)'

java - 解释 jstat 结果