免责声明:我对这个问题的冗长表示歉意(尽pipe我认为这是一个有趣的问题!),但我无法弄清楚如何更简洁地说出来。
我已经花了几个小时的研究,以解决在64位Windows 7的32位进程中访问多GB文件的问题,从/LARGEADDRESSAWARE
到VirtualAllocEx
AWE,显然有很多种方法。 在Windows中编写一个多视图内存映射系统(CreateFileMapping,MapViewOfFile等等)时,我感到有点舒服,但是却不能完全避免这样的问题。 另外,我非常了解Boost的进程和iostream模板,虽然它们看起来相当轻巧,但是只需要使用Windows API调用来编写一个系统就可以做出类似的努力(更不用说我已经有了一个内存 – 使用Windows API调用半实现的映射架构)。
我正在尝试处理大型数据集。 该程序依赖于预编译的32位库,这就是为什么目前程序本身也在32位进程中运行,即使系统是64位,也有64位的操作系统。 我知道有一些方法可以在这个方面添加包装库,但是,由于它是一个更大的代码库的一部分,这确实是一件小事。 我将二进制头文件设置为允许/LARGEADDRESSAWARE
(以减less我的内核空间为代价),这样每个进程就可以获得大约2-3 GB的可寻址内存,可以给出或取用(取决于堆碎片等)。 )。
这里的问题是:数据集是4 + GB,并且在它们上面运行DSPalgorithm,基本上要求整个文件随机访问。 在C#中处理从文件生成的对象的指针,但是文件本身在C ++(它是P / Invoked)中被加载到内存中(使用这个部分内存映射系统)。 因此,我相信这个解决scheme不是简单地调整窗口来访问我需要访问的文件部分,因为我基本上还想把整个文件抽象成一个指针,从中我可以调用方法几乎可以在文件的任何位置访问数据。
显然,大多数内存映射体系结构都依赖于将单个进程拆分为多个进程。因此,例如,我将访问一个具有3个进程的6 GB文件,每个文件都拥有一个2 GB的窗口。 然后,我需要添加大量的逻辑来从这些不同的窗口/进程中提取和重新组合数据。 VirtualAllocEx
显然提供了一种增加虚拟地址空间的方法,但我仍然不完全确定这是否是最好的方法。
但是,让我们说,我希望这个程序在64位系统上的function与“64位”单一程序一样“容易”。 假设我不在乎抖动,我只想在系统上操作一个大文件,即使只有500 MB被加载到物理RAM中。 有没有办法获得这个function,而不必手动编写一个有点荒谬的手动内存系统? 或者,还有什么比通过如此的梳理SO和互联网find更好的方法吗?
这本身就是一个第二个问题:是否有限制这个进程使用多less物理RAM的方法? 例如,如果我想限制只有500 MB加载到物理RAM在任何时间(同时保持多GB文件在磁盘上)?
对于这个长期的问题,我感到抱歉,但是我觉得这是对我在SO和networking上发现的很多问题(只有部分答案)的恰当总结。 我希望这可以是一个可以明确回答(或者至less是一些优点/缺点)的领域,我们都可以在这个过程中学到一些有价值的东西!
你可以写一个访问器类,你给它一个基地址和一个长度。 它返回数据或抛出异常(或者你想告诉错误条件),如果出现错误条件(超出界限等)。
然后,无论SetFilePointerEx()
您需要从文件中读取,访问器对象都可以在调用ReadFile()
之前使用SetFilePointerEx()
ReadFile()
。 然后,您可以将访问器类传递给您在读取文件时创建的任何对象的构造函数。 然后对象使用访问器类从文件中读取数据。 然后它将数据返回给对象的构造函数,将其解析为对象数据。
如果稍后可以编译为64位,则只需更改(或扩展)访问器类即可从内存中读取。
至于限制进程使用的内存量。这主要是确保A)你没有内存泄漏(特别是淫秽的)和B)摧毁对象,你不需要在这个时刻。 即使你稍后需要它,但数据不会改变…只要摧毁对象。 然后在需要的时候重新创建它,允许它重新读取文件中的数据。