在程序临时数组中使用内存映射文件?

时间:2013-09-09 12:07:35

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

我正在编写一个能够处理核心数据的程序。 所以我处理的文件大小从1MB到50GB(未来可能更大)。

我已经阅读了几个有关内存映射文件的教程,现在正在使用内存映射文件来管理数据IO,即从/向硬盘驱动器读取和写入数据。

现在我还处理数据并需要一些与数据大小相同的临时数组。我现在的问题是,如果我还应该使用内存映射文件,或者我应该以某种方式让操作系统管理它而不显式定义内存映射文件。 问题如下:

我正在使用多个平台,但始终使用64位系统。从理论上讲,64位虚拟地址空间绝对足以满足我的需求。但是,在Windows中,最大虚拟地址空间似乎受操作系统的限制,即,如果允许分页以及允许哪个最大虚拟内存大小,则用户可以设置。另外我在某处读到,Windows 64中的最大虚拟内存不是2 ^ 64,而是某处2 ^ 40或类似,这对我来说仍然足够,但似乎是一个非常奇怪的限制。 此外,Windows有一些奇怪的限制,例如最大大小为2 ^ 31个元素的数组,与数组类型无关。我不知道所有这些是如何在linux上处理的,但我认为它的处理方式类似。可能最大允许虚拟内存= OS-RAM +交换分区大小?因此,如果我想使用系统来处理超出ram大小的数据,那么有很多事情需要解决。 我甚至不知道我是否可以在c ++中使用整个64位虚拟地址空间。在我的简短测试中,我得到一个编译器错误,无法初始化mot而不是2 ^ 31个元素,但我认为,通过使用std :: vector等很容易超越它。

但是,另一方面,通过使用内存映射文件,它将始终是使用我的所有内存写入操作写入hdd的数据。特别是对于比我的物理RAM小的数据,这应该是一个相当大的瓶颈。或者它是否避免写入,直到它必须,因为RAM超过??? 内存映射文件的优点在于与共享内存或时间通信的进程间通信,这样我就可以启动应用程序,编写内容,退出应用程序,然后重新启动它,并有效地只读取那些我需要的RAM数据。 由于我需要处理整个数据,并且只需要在一个执行实例中使用一个进程,因此我的情况下不会出现这两个优点。

注意:作为我问题的替代解决方案的流媒体方法并不可行,因为我严重依赖于对数据的随机访问。

我理想的是,我可以通过一种方式处理所有模型,而不管其大小和操作限制设置限制,但处理RAM中可能的所有内容,并且只有在超出物理限制时,才使用内存映射文件或用于分页RAM超出数据的其他机制(如果有其他机制),理想情况下由操作系统管理。

总结一下,处理这个临时现有数据的最佳方法是什么?如果我可以在没有内存映射文件和平台独立的情况下执行此操作,您是否可以给我任何代码片段或类似内容并解释它如何工作以避免这些操作系统限制?

2 个答案:

答案 0 :(得分:1)

如果没有人回答,我会自己更新问题的状态。

今天幸运地接触了boost进程库后,我发现了managed_mapped_file,它甚至允许我在映射范围内分配向量,这使得它们几乎与没有映射文件的编程一样容易使用。

此外,我发现:

  

如果多个进程映射同一个文件,并且进程修改了一个   内存范围来自映射区域,该区域也由其他映射   过程中,这些变化在其他过程中是可见的。   但是,磁盘上的文件内容不会立即更新,因为   这会损害性能(写入磁盘要慢几倍   而不是写入记忆)。如果用户想要确保该文件的   内容已更新,它可以从视图中清除范围   磁盘。

http://www.boost.org/doc/libs/1_54_0/doc/html/interprocess/sharedmemorybetweenprocesses.html

所以希望它只在我超过系统物理RAM时开始写入。 我还没有做过任何速度测量,也不会做其中的一些。

我现在可以很好地使用这个解决方案了。 但是,我将把这个问题保留为未答复并打开。 在某些时候,有人可能会发现问题并且可以提供更多提示,例如如何防止数据刷新到实际需要的程度,或者有一些其他想法/提示如何处理核心数据。< / p>

答案 1 :(得分:0)

也许有点晚了,但这是一个有趣的问题。

  

但是,另一方面,通过使用内存映射文件,它将始终是使用我的所有内存写入操作写入hdd的数据。特别是对于比我的物理RAM小的数据,这应该是一个相当大的瓶颈。或者它是否会避免写入,因为RAM已被超过???

为避免在内存足够的情况下写入磁盘,您应该使用FILE_ATTRIBUTE_TEMPORARY将文件打开为“临时”(FILE_FLAG_DELETE_ON_CLOSE)。这将暗示操作系统尽可能延迟写入磁盘。

至于数组大小的限制:最好提供自己的数据结构并访问映射的视图。对于大型数据集,您可能希望使用多个不同(较小)的映射视图,您可以根据需要进行映射和取消映射。