系统分配的内存 vs DLMalloc在大型分配时的表现

4
我有一个奇怪的问题。我想一次性malloc 8GB内存,并计划稍后使用TLSF来管理这个堆。也就是说,我想避免在整个应用程序中使用malloc,只需在开始时获取一个大内存块,在结束时释放它。然而,这里有一个特殊之处。我以前一直在我的程序中使用dlmalloc。链接它和一切都很顺利。然而,现在当我尝试一次性malloc 8GB并链接dlmalloc使用它时,我在OSX上运行时会得到segmentation fault 11,没有dlmalloc时一切都很好。无论我使用gcc还是clang都无济于事。虽然系统没有8GB的RAM,但它有4GB。有趣的是,在具有32GB RAM的Windows机器和16GB RAM的Ubuntu机器上也发生了同样的情况。使用系统malloc时,所有操作都正常进行,分配通过,并且在所有三个系统上对分配的内存进行简单迭代也能按预期工作。但是,当我链接dlmalloc时,它会失败。我已经尝试过使用malloc和dlmalloc函数调用。 分配本身并不是什么特别的,只是普通的c99。
[...]
size_t bytes = 1024LL*1024LL*1024LL*8LL;
unsigned long *m = (unsigned long*)malloc(bytes);
[...]

我对这里的几件事感到困惑。为什么系统malloc即使没有4GB RAM也会给我8GB malloc,这些是虚拟页面吗?为什么dlmalloc不这样做?我知道可能没有一个连续的8GB RAM块可以分配,但为什么会出现段错误而不是null ptr?

如果我不确定系统是否有那么多RAM,是否有一种可靠的(希望是平台中立的)解决方案可以从malloc中一次获得那么多RAM?

编辑:程序和我运行的操作系统都是64位的。

编辑2: 所以我又试了一下。结果发现如果我将分配分解成1GB块,也就是8个单独的malloc,那么使用dlmalloc就可以工作了。因此,这似乎是一个关于连续范围分配的问题,其中dlmalloc可能只在存在连续块时尝试分配。这使我的问题更难以表述。是否有一种跨平台的相对可靠的方法来获取那么大的内存块,无论是否使用dlmalloc,并且如果没有物理内存剩余,它不会失败(可以在交换区中,只要它不失败)。同时,是否有可能以跨平台的方式告诉malloc是在RAM还是在swap中。


你使用的系统交换分区有多大? - Jiminion
100GB在OSX上,其他两个系统(Windows和另一台Linux机器)专门为此目的分配了600GB。 - Keyframe
2
不确定DLmalloc和malloc之间的区别,但你能够malloc 8 GB的原因正是你所说的,它们是虚拟页面。当机器没有足够的物理RAM来支持所需的RAM时,它将使用硬盘空间。从功能上讲,它可以工作,但读/写速度显着较慢。 - sedavidw
1个回答

2
我将为您提供一些观点,尽管不是完全的答案。当我看到您试图分配8GB连续RAM时,我感到担忧。是的,在64位计算和其他方面,这可能是“合法”的,但在普通机器上,您可能会遇到很多边缘情况,32位旧代码无法处理64位大小,以及获取足够大的内存块以使其工作的普遍可用性问题。如果您想尝试这种事情,请尝试malloc单个块,然后如果失败,请使用较小的块。这在某种程度上破坏了1个块系统的目的。也许操作系统中有一些“页面大小”,可以将您的malloc大小链接到该大小,以帮助性能和获得所需内存量。
在游戏机上,这种内存管理方法有些常见-在启动时从操作系统分配1个尽可能大的缓冲区,然后放置自己的内存管理器以避免操作系统开销和可能的劣质分配代码。它还允许更好地控制这些系统上虚拟内存不存在的内存碎片。但在这些系统上,您也会提前知道有多少RAM可用。
有没有一种以平台无关的方式查看内存是物理的还是虚拟的?我认为没有,但也许其他人可以给出一个好的答案,我将编辑掉这部分。
所以这不是100%的答案,但一些随机想法可以帮助您,并且我内心想知道您在做什么,需要8GB RAM的单个块时,多个块似乎可以正常工作。 :)

首先回答你的问题。我尝试了一种懒惰的方法,获取了一大块内存,以便可以将大量的exr图像加载到其中,以便更快地访问和移动它们。我认为这不是一个太疯狂的想法。 :) 这是我的主要动机。其他方面,你已经描述了它。在未来,我想制作一个游戏,并且我想按照控制台上的方式进行,但显然不会像那样工作。看起来我需要有两个单独的内存管理。一个用于控制台,一个由多个部分组成。是否存在现有的解决方案? - Keyframe
并不完全是这样。跨平台开发的游戏通常具有共同的高级内存接口,但在底层,每个游戏都有本地代码,可以利用该系统的特殊功能。8GB的容量真的很大!你要做什么和计划将其移植到哪里,需要那种容量?也许Xbox One或PS4可以胜任 - 这两者都有8GB,但我猜操作系统和开销会占用相当多的空间。如果我没记错的话,Wii U可用的内存大约为1GB,下一代当前的游戏机和任何旧的游戏机都会小得多。 - Michael Dorgan
顺便说一句,如果这只是为了优化,那么这么大的文件可能会跨越多个虚拟页面,我猜这可能会消耗你使用单个缓冲区所获得的任何性能。只需分配所需的大小并释放它即可。这就是控制台所做的-尽管分配和释放的顺序要仔细观察以防止碎片化。 - Michael Dorgan
我已经对较小的RAM数量进行了测试。无论访问模式如何,只要将所有内容保留在RAM中,就可以获得显着的性能提升,因为文件很大,这是一个IO受限瓶颈问题。您能否更详细地阐述控制台方式的事情,它是否也适用于桌面?也许您可以指向一些资源?谢谢! - Keyframe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接