Kad*_*ura 6 c++ windows memory-management out-of-memory memory-mapped-files
免责声明:我为这个问题的冗长而道歉(我认为这是一个有趣的问题!),但我无法弄清楚如何更简洁地说出来.
我已经做了几个小时的研究,以解决在64位Windows 7(从AWE /LARGEADDRESSAWARE
到VirtualAllocEx
AWE)上以32位进程访问多GB文件的问题.我在Windows中编写一个多视图内存映射系统(CreateFileMapping,MapViewOfFile等)时有点舒服,但是不能完全摆脱对这个问题有一个更优雅的解决方案的感觉.此外,我非常了解Boost的进程间和iostream模板,虽然它们看起来相当轻巧,只需要花费相同的努力来编写仅使用Windows API调用的系统(更不用说我已经有了一个内存 - 使用Windows API调用半实现的映射体系结构).
我正在尝试处理大型数据集.该程序依赖于预编译的32位库,这就是为什么目前程序本身也在32位进程中运行,即使系统是64位,64位操作系统.我知道有一些方法可以在其中添加包装库,但是,看到它是更大的代码库的一部分,它确实是一项任务.我设置二进制头是允许的/LARGEADDRESSAWARE
(以减少我的内核空间为代价?),这样我每个进程可以获得大约2-3 GB的可寻址内存,给予或接受(取决于堆碎片等).
问题在于:数据集为4 + GB,并且运行DSP算法,需要对文件进行基本随机访问.指向从文件生成的对象的指针在C#中处理,但文件本身在C++中加载到内存中(使用此部分内存映射系统)(它是P/Invoked).因此,我认为解决方案不仅仅是简单地调整窗口来访问我需要访问的文件部分,因为本质上我仍然希望将整个文件抽象为单个指针,我可以从中调用方法几乎在文件中的任何位置访问数据.
显然,大多数内存映射架构依赖于将单个进程拆分为多个进程.因此,例如,我将访问具有3个进程的6 GB文件,每个进程持有2 GB的文件窗口.然后,我需要添加大量逻辑来从这些不同的窗口/进程中提取和重新组合数据. VirtualAllocEx
显然提供了一种增加虚拟地址空间的方法,但我仍然不能完全确定这是否是最好的方法.
但是,让我们说我希望这个程序在64位系统上像64bit进程一样"轻松"运行.假设我不关心颠簸,我只是想能够操作系统上的大文件,即使在任何时候只有500 MB被加载到物理RAM中.有没有办法获得这个功能,而无需手工编写一个有点荒谬的手动内存系统?或者,有没有比我通过梳理SO和互联网找到的更好的方式?
这有助于提出一个第二个问题:有没有办法限制这个过程使用多少物理RAM?例如,如果我想将进程限制为在任何时候只将500 MB加载到物理RAM中(同时将多GB文件保留在磁盘上),该怎么办?
对于这个冗长的问题,我感到很遗憾,但我觉得这是一个很好的总结,看起来很多问题(只有部分答案)我已经在SO和网络上找到了.我希望这可以成为一个可以充实明确答案(或者至少是一些优点/缺点)的领域,我们都可以在这个过程中学到有价值的东西!
您可以编写一个访问器类,并为其指定基地址和长度。如果出现错误情况(超出范围等),它会返回数据或引发异常(或者您想要通知错误情况的其他情况)。
然后,任何时候您需要从文件中读取数据时,访问器对象都可以SetFilePointerEx()
在调用之前使用ReadFile()
。然后,您可以将访问器类传递给您在读取文件时创建的任何对象的构造函数。然后,对象使用访问器类从文件中读取数据。然后它将数据返回给对象的构造函数,构造函数将其解析为对象数据。
如果稍后您能够编译为 64 位,则只需更改(或扩展)访问器类以从内存中读取即可。
至于限制进程使用的 RAM 量……这主要是确保 A)没有内存泄漏(尤其是淫秽的内存泄漏)和 B)销毁当前不需要的对象。即使您稍后需要它,但数据不会改变......只需销毁该对象即可。然后在您确实需要时重新创建它,从而允许它重新从文件中读取数据。