我正在尝试研究d维范围搜索算法的实用性,该算法在渐近情况下被证明是好的,但是具有与之相关的大常数。这意味着我需要能够将d维空间中的点数改变为一些非常大的值。使用1<<20
(2到20的幂)点开始导致我的malloc
s返回空指针。我尽可能频繁地free
记忆,而且我正在尽可能少地节省一些钱,但我希望能够更接近价值观。 1<<28
。有没有一种处理这种大小的内存块的传统方法?
答案 0 :(得分:3)
如果您在32位处理器和/或操作系统上运行,或者正在编译32位而不是64位,那么您就不能,即使您在64位处理器上运行并为其编译,您也需要有很多物理内存 - malloc尝试连续块,所以交换文件对你没有好处。 SIZE_MAX会告诉您可以尝试分配的最大数量,但失败取决于物理限制。
答案 1 :(得分:0)
你说分配这样的大块启动以返回空指针。对我来说,这意味着它可以工作一段时间,你随着时间的推移分配和释放其中的一些,并且在做了很多次之后,你开始得到空值。
如果是这种情况,您会看到一个典型的内存碎片案例。 (如果我的假设不正确,请原谅以下小说。)过去,我通过编写自己的内存管理器来处理这些问题,这些内存管理器允许我在内存中重新定位对象,以便为新块的分配腾出空间。如果您的代码必须能够将指针保存到已分配的块中,那么您的内存管理器将不得不涉及一个指针实现,这将使移动透明。如果您依赖第三方软件,这就变得难以实现。
您可能会考虑预先分配您将使用的每个块大小的池。这样可以确保您永远不会以一种大块只有大块不可用的方式分割内存,而不是拥有足够的可用内存,而只是使用小块。检查名为Slab Allocation的方法。
我的可重定位内存的实现是这样的:在程序执行开始时,我分配了可用的最大单个内存块。 (mmap是你的朋友。)如果我找不到一个可以满足分配请求的空闲片段,我会在它之前和之后找到一块带有一大块可用空间的块,然后将它移动到前一个空闲空间的位置。我计划这个移动,以便产生的空闲块足够大,可以用于新请求的分配。
这不是一个好的通用解决方案。它可能非常慢,我不会在需要实时性能的系统中使用它。 (想想如果你为了一次分配而必须洗掉几十个块会发生什么。最坏的情况是,为了满足一个请求,你必须复制每个分配的字节。)它还要求你能够容忍改组引用此内存的每个指针。但如果绝对必要,它确实提供了比slab分配器更有效的内存使用。
答案 2 :(得分:0)
2 ^ 28 = 256MB。
如果您有足够的物理内存,那么在32位或64位系统上肯定是可行的。要检查您是否这样做,请获取cat /proc/meminfo
的输出并查找MemFree
行。
我建议的API是mmap()
(匿名映射),而不是malloc()
http://man7.org/linux/man-pages/man2/mmap.2.html
mmap
是一个系统调用,直接向OS请求内存。这是malloc()
在下面使用的内容。
答案 3 :(得分:0)
如果malloc()
开始失败,那么你可能会受到(略微随意)限制。你应该能够放松一些(参见ulimit
中的bash
);但请记住,这些限制旨在帮助保持系统在通用用途中的稳定性和可预测性。另外,请注意过度使用,操作系统可能会让您要求的内存超出其可能提供的内存,如果您尝试使用它,则会导致您死亡。
如果您真的用完了地址空间并且正在构建32位应用程序,那么请切换到64位。
如果您在64位应用程序中耗尽地址空间,那么我建议您不要充分利用您的分配。这需要填写很多数据,我希望你在用完地址空间之前用完时间。在这种情况下,您可能应该重新考虑使用该空间的方式。
如果确实需要比系统上可用的地址空间更大的地址空间,则可以根据需要创建文件(或多个文件)和mmap()
个文件。这允许操作系统尽可能地缓存文件,如果它确实耗尽了物理内存和交换(这些项目总是存在风险),那么它可以将数据分页到没有陷入恐慌并杀死你的申请。
不幸的是,以这种方式使用mmap()
确实需要您在该文件中管理自己的分配。