现在有很大的内存,我想知道是否可能分配一个大于4GB的单一内存块?还是需要分配多个较小的内存块并处理它们之间的切换?
为什么呢? 我正在处理一些openstreetmap xml数据,这些文件非常大。由于无法一次性加载所有数据,所以我目前正在使用流式传输方式,但我对malloc或new的上限产生了好奇。
现在有很大的内存,我想知道是否可能分配一个大于4GB的单一内存块?还是需要分配多个较小的内存块并处理它们之间的切换?
为什么呢? 我正在处理一些openstreetmap xml数据,这些文件非常大。由于无法一次性加载所有数据,所以我目前正在使用流式传输方式,但我对malloc或new的上限产生了好奇。
简短回答:不太可能。
为了实现这个目标,你绝对需要使用64位处理器。此外,还要考虑操作系统是否支持将超过4G的内存分配给单个进程。
理论上来说,这是可能的,但你必须阅读内存分配器的文档。此外,你还会更容易受到内存碎片问题的影响。
关于Windows内存管理有很好的信息。
物理和虚拟内存布局概述
你需要一个64位的CPU和操作系统构建,几乎肯定需要足够的内存来避免工作集抖动。一些背景知识:
32位机器(大多数情况下)具有可以存储2^32(4,294,967,296)个唯一值中的一个的寄存器。这意味着32位指针可以寻址2^32个唯一的内存位置,这就是魔法的4GB限制的来源。
一些32位系统(例如SPARCV8或Xeon)具有MMU(内存管理单元),可以通过一种技巧允许使用更多物理内存。这允许多个进程占用总共超过4GB的内存,但每个进程都限于其自己的32位虚拟地址空间。对于查看虚拟地址空间的单个进程,只能使用32位指针映射2^32个不同的物理位置。
我不会详细解释,但本演示文稿(警告:powerpoint)描述了这是如何工作的。一些操作系统具有设施(例如上面提到的此处 - 感谢FP),可以在用户级别控制下操作MMU并将不同的物理位置换入虚拟地址空间。
操作系统和内存映射I/O将占用一些虚拟地址空间,因此并非所有4GB都可供进程使用。例如,Windows默认占用2GB,但可以在引导时调用/3G开关将其设置为仅占用1GB。这意味着,在这种32位架构上,单个进程只能在内存中构建少于4GB的连续数据结构。内存映射文件的优点在于您可以打开比4Gb大得多的文件(在NTFS上几乎无限制!),并且在其中有多个小于4Gb的内存窗口。
它比将文件打开并读入内存更加高效,在大多数操作系统上,它使用内置的分页支持。
如果使用64位操作系统(以及内存足够的机器),这将不会是一个问题。
如果malloc无法处理,则操作系统肯定会提供API,允许您直接分配内存。在Windows下,您可以使用VirtualAlloc API。
您是否考虑过使用内存映射文件?由于您正在加载非常大的文件,因此这似乎是最好的选择。
如果您的系统上的size_t大于32位,那么您已经成功地跨过了第一道障碍。但是,C和C++标准并不负责确定任何特定的new或malloc调用是否成功(除了malloc大小为0的情况)。这完全取决于操作系统和堆的当前状态。