当使用malloc分配内存时,通常可以更快地执行多个较小数据块的malloc或更少的大块数据malloc吗?例如,假设您正在处理具有黑色像素和白色像素的图像文件。您正在迭代像素,并希望将每个黑色像素的x和y位置保存在一个新结构中,该结构还具有指向下一个和前一个像素x和y值的指针。迭代通过为指针分配每个黑色像素的x和y值的新结构的像素通常会更快,或者通过迭代一次获得黑色像素数的计数会更快,然后分配一个大的使用仅包含x和y值但没有指针的结构的内存块,然后再次迭代,将x和y值保存到该数组中?我假设某些平台可能与其他平台不同,哪个更快,但每个人认为通常会更快?
答案 0 :(得分:20)
取决于:
如果我关心,我会测量它!如果我真的非常关心,并且无法猜测,那么我可以实现两者,并在目标机器上的运行时进行测量,并相应地进行调整。
一般来说,我认为越少越好:但是有大小和运行时库实现,这样(足够)大的分配将被委托给(相对慢的)O / S.而(一个(足够)小的分配将从(相对快速的)已经分配的堆中提供。
答案 1 :(得分:14)
分配大块更有效;此外,由于您使用较大的连续块,因此您具有更大的引用位置,并且在生成内存结构后遍历您的内存结构也应该更高效!此外,分配大块应该有助于减少内存碎片。
答案 2 :(得分:5)
一般来说,分配更大的内存块的次数会更快。每次调用malloc()时都会产生开销。
答案 3 :(得分:4)
除速度问题外,还有memory fragmentation problem。
答案 4 :(得分:3)
分配内存是有效的。分配内存块时完成的工作量通常与块的大小无关。你从这里开始工作。
答案 5 :(得分:3)
最好不要在性能敏感的代码中进行分配。事先为一次分配您需要的内存,然后根据需要使用和重复使用。
内存分配通常是一个相对较慢的操作,所以不要经常这样做。
答案 6 :(得分:2)
一般来说,malloc很贵。它必须找到一个适当的内存块,从中分配内存并跟踪非连续的内存块。在几个库中,您会发现小内存分配器,它们通过分配大块和管理分配器中的内存来尽量减少影响。
Alexandrescu在“现代C ++设计”和Loki库中处理这个问题,如果你想看一个这样的库。
答案 7 :(得分:2)
这个问题是一种实用主义,我害怕;也就是说,这取决于。
如果你有很多像素,只有少数是黑色的,那么计算它们可能是最高的成本。
如果你正在使用C ++,你的标签就是这样,我强烈建议你使用STL,比如std :: vector。
如果我没记错的话,vector的实现使用实用的方法进行分配。分配策略有一些启发式方法,信息量如下:
class SampleVector {
int N,used,*data;
public:
SampleVector() {N=1;used=0;data=malloc(N);}
void push_back(int i)
{
if (used>=N)
{
// handle reallocation
N*=2;
data=realloc(data,N);
}
data[used++]=i;
}
};
在这种情况下,每次重新分配时都会分配多少内存。 这意味着重新分配的频率逐渐减半。
您的STL实施将进行良好调整,因此如果您可以使用它,请执行!
答案 8 :(得分:2)
要考虑的另一点是它如何与线程交互。在线程并发应用程序中多次使用malloc是性能的主要阻力。在那种环境中,您最好使用可扩展的分配器,例如英特尔Thread Building Blocks或Hoard中使用的分配器。 malloc的主要限制是所有线程都争用一个全局锁。添加另一个线程会大大减慢您的应用程序,这可能会非常糟糕。
答案 9 :(得分:1)
正如已经提到的那样,malloc成本很高,因此可能会更快。 此外,在大多数平台上使用像素将减少缓存未命中率并且速度更快。 但是,并不能保证每个平台
答案 10 :(得分:1)
在分配开销本身旁边,分配多个小块可能会导致大量缓存未命中,而如果您可以迭代连续块,则可能更好。
您描述的场景要求预先分配大块,imho。
答案 11 :(得分:1)
虽然分配大块的分配内存的每个字节的速度更快,但如果你人为增加分配大小只是为了自己砍掉它,它可能不会更快。你只是在重复内存管理。
答案 12 :(得分:1)
对像素进行迭代以计算要存储的数量。 然后为确切的项目数分配一个数组。这是最有效的解决方案。
您可以使用std :: vector来更轻松地进行内存管理(请参阅std :: vector :: reserve过程)。注意:预留可能会分配一些(可能多达2倍)内存,然后必要。
答案 13 :(得分:0)
“我可以分配全部”(真的,我可以!)
我们可以对一些特殊的实现进行哲学思考,大大加快小分配......是的!但总的来说这有:
malloc必须是通用的。它必须实现所有不同类型的分配。这就是它相当缓慢的原因!可能是,你使用了一个特殊的kinky-super-duper库,它可以加快速度,但也不会创造奇迹,因为它们必须在其全部范围内实现malloc。
规则是,当你有更专业的分配编码时,你总是比广泛的“我可以分配全部”例程“malloc”更快。
因此,当您能够在编码中为更大的块分配内存时(并且不会花费太多成本),您可以大大加快速度。另外 - 正如其他人所提到的那样 - 你将获得更少的内存碎片,这也会加快速度并降低内存成本。你还必须看到,malloc需要为它返回给你的每一块内存需要额外的内存(是的,特殊的例程可以减少这个......但是你不知道!除非你自己实现它或者买了一些奇迹-library)。