你可以分配一个非常大的内存单元(> 4GB)在C或C + +?
现在有了大量内存,我想知道,有可能分配一个大于4GB的内存块吗? 或者我需要分配一堆小块,并处理它们之间的切换?
为什么??? 我正在处理一些openstreetmap XML数据,这些文件是巨大的。 我目前正在将它们stream入,因为我无法将它们全部加载到一个块中,但我只是对malloc或new的上限感到好奇。
简短的回答:不太可能
为了这个工作,你绝对不得不使用一个64位的处理器。 其次,这要取决于操作系统支持为单个进程分配超过4G的RAM。
从理论上讲,这是可能的,但是你必须阅读内存分配器的文档。 你也会更容易受到内存碎片问题的影响。
Windows内存pipe理有很好的信息。
物理和虚拟内存布局的入门
你需要一个64位的CPU和O / S版本以及几乎可以肯定的内存,以避免冲击你的工作集。 一点背景:
32位机器(大体上)具有可以存储2 ^ 32(4,294,967,296)唯一值中的一个的寄存器。 这意味着一个32位的指针可以解决2 ^ 32个独特内存位置中的任何一个,这是4GB限制的来源。
一些32位系统(如SPARCV8或Xeon)有MMU的技巧来允许更多的物理内存。 这允许多个进程共占用大于4GB的内存,但是每个进程仅限于其自己的32位虚拟地址空间。 对于查看虚拟地址空间的单个进程,只有2 ^ 32个不同的物理位置可以由32位指针映射。
我不会进入细节,但这个演示文稿 (警告:powerpoint)描述了这是如何工作的。 一些操作系统具有操作MMU并且在用户级别控制下将不同的物理位置交换到虚拟地址空间的设施(诸如这里描述的那些 – 归功于上面的FP)。
操作系统和内存映射的I / O将占用一些虚拟地址空间,因此并不是所有的4GB都可用于该进程。 例如,Windows默认使用2GB,但如果在启动时调用/ 3G开关,则可以设置为1GB。 这意味着这种32位体系结构上的单个进程只能在内存中build立一个小于4GB的连续数据结构。
这意味着您将不得不明确使用Windows上的PAE工具或Linux上的Equivalent工具来手动交换叠加层。 这不一定很难,但需要一些时间才能工作。
或者你可以得到一个有很多内存的64位盒子,这些问题或多或less都会消失。 具有64位指针的64位体系结构至less在理论上可以build立多达2 ^ 64(18,446,744,073,709,551,616)唯一地址的连续数据结构。 这允许build立和pipe理更大的连续数据结构。
内存映射文件的优点是你可以打开比4Gb大得多的文件(在NTFS上几乎是无限的!),并有多个<4Gb的内存窗口。
它比打开文件并将其读入内存更有效率,在大多数使用内置寻呼支持的操作系统上。
这不应该是一个64位的操作系统(和一个有这么多内存的机器)的问题。
如果malloc不能应付,那么操作系统肯定会提供API来让你直接分配内存。 在Windows下,您可以使用VirtualAlloc API。
它取决于你正在使用哪个C编译器,以及在什么平台上(当然),但是没有根本的原因,为什么你不能分配连续可用内存的最大块 – 这可能比你需要的less。 当然,你可能不得不使用64位系统来解决更多的RAM问题。
看Malloc的历史和细节
调用alloc.h中的HeapMax来获得最大的可用块大小
你有没有考虑使用内存映射文件? 由于你正在加载真正的大文件,似乎这可能是最好的方式去。
这取决于操作系统是否会给你虚拟地址空间,允许寻址高于4GB的内存以及编译器是否支持使用new / malloc分配它。
对于32位Windows,由于指针大小为32位,因此您将无法获得大于4GB的单个块,因此将您的虚拟地址空间限制为4GB。 (您可以使用物理地址扩展来获得超过4GB的内存;但是,我相信您必须将该内存映射到4GB的虚拟内存空间中)
对于64位Windows,VC ++编译器支持64位指针,虚拟地址空间的理论极限为8TB。
我怀疑同样适用于Linux / gcc – 32位不允许你,而64位允许你。
正如Rob指出的那样,VirtualAlloc for Windows是一个很好的select,就像anonymouse文件映射一样。 但是,特别是对于你的问题,答案是“如果C或C ++”可以分配,答案是没有这个WIN7 RC 64不支持
在EXE文件的PE / COFF规范中,指定HEAP保留和HEAP提交的字段是32位的数量。 这与windows CRT中当前堆实现的物理尺寸限制是一致的,这只是短小的4GB。 因此,从C / C ++(技术上来说,CreateFileMapping和VirtualAlloc / VirtualAllocNuma等的操作系统支持工具不是C或C ++)是无法分配超过4GB的。
另外,BE AWARE还有一些底层的x86或amd64 ABI结构被称为页表。 这将实际上做你所认同的事情,为更大的请求分配更小的块,尽pipe这在内核内存中是有利的,但是对整个系统有影响,这些表是有限的。
如果你在这样macros大的意义上分配内存,你最好build议根据分配粒度(VirtualAlloc强制执行)进行分配,并且确定可选的标志或方法来启用更大的页面。
4kb页面是386的初始页面大小,最后是Pentium增加了4MB。 今天, AMD64 (AMD系列10h处理器软件优化指南)的最大页表条目大小为1GB。 这意味着你的情况在这里,假设你只是做了4GB,它只需要在内核的目录中有4个唯一的条目来定位\分配和许可你的进程的内存。
微软还发布了本手册 ,阐述了应用程序内存的一些优点,并且适用于Vista / 2008平台和更新版本。
内容
介绍。 4
关于内存pipe理器4
虚拟地址空间。 五
内核虚拟地址空间的dynamic分配。 五
x86体系结构的详细信息。 6
64位体系结构的详细信息。 7
在x86架构中跳转内核模式堆栈。 7
使用过量的池内存。 8
安全性:地址空间布局随机化。 9
ASLR对图像负载地址的影响。 9
ASLR的好处.. 11
如何创build基于dynamic的图像。 11
I / O带宽。 11
微软SuperFetch。 12
页面文件写入。 12
内存pipe理器和cachingpipe理器的协调13
预取式聚类。 14
大文件pipe理15
hibernate和待机。 16
高级video模型16
NUMA支持17
资源分配。 17
默认节点和亲和力。 18
中断亲和力。 19
NUMA感知系统function的应用程序。 19
驱动程序的NUMA感知系统function。 19
寻呼。 20
可扩展性。 20
效率和平行
页码帧号和PFN数据库。 20
大页面。 21
cachingalignment池分配。 21
虚拟机。 22
负载均衡。 22
其他优化。 23
系统完整性。 23
硬件错误的诊断。 23
代码完整性和驱动程序签名。 24
错误检查期间的数据保存。 24
你应该做什么。 24
对于硬件制造商。 24
对于驱动程序开发者。 24
对应用程序开发人员。 25
对于系统pipe理员。 25
资源。 25
如果你的系统中的size_t大于32位,你已经清除了第一个障碍。 但是C和C ++标准并不负责确定是否有任何特定的新的或malloc调用成功(除了malloc的大小为0)。 这完全取决于操作系统和堆的当前状态。
就像其他人所说的那样,获得一台64位的机器是一个很好的select。 但即使在32位机器的intel机器上,如果您的操作系统和CPU支持PAE ,也可以处理大于4GB的内存区域。 不幸的是,32位的WinXP不这样做(32位的Vista?)。 Linux允许你在默认情况下这样做,但是由于指针仍然是32位,所以即使使用mmap(),也只能限制在4GB的区域。
你应该做的是让操作系统为你pipe理内存pipe理。 进入一个可以处理大量内存的环境,然后将XML文件读入(a)数据结构中,让它为你分配空间。 然后对内存中的数据结构进行操作,而不是在XML文件本身上进行操作。
尽pipe如此,即使在64位系统中,对于程序的哪些部分实际位于RAM中,caching中,还是被分页到磁盘,至less在大多数情况下,由于OS和MMU处理这本身。