gpt4 book ai didi

c++ - 分配约10GB的 vector -如何加快速度?

转载 作者:搜寻专家 更新时间:2023-10-31 01:37:49 25 4
gpt4 key购买 nike

我正在加载约1000个文件,每个文件代表约300万个浮点数组。我需要将它们全部存储在内存中,因为我需要进行一些涉及它们全部的计算。

在下面的代码中,我详细介绍了内存分配和文件读取,因此可以分别观察它们的速度。我感到惊讶的是,发现内存分配花费的时间比文件读取要长得多。

  std::vector<std::vector<float> * > v(matrix_count);   
for(int i=0; i < matrix_count; i++) {
v[i] = new std::vector<float>(array_size);
}

for(int i=0; i < matrix_count; i++) {
std::ifstream is(files[i]);
is.read((char*) &((*v[i])[0]), size);
is.close();
}

通过计算时间,分配循环花费了6.8s,而文件加载花费了2.5s。与从磁盘分配空间相比,从磁盘读取速度快将近3倍,这似乎是违反直觉的。

我可以做些什么来加快内存分配吗?我尝试分配一个大的 vector ,但是由于bad_malloc失败了-我猜一个10GB的 vector 不合适。

最佳答案

Is there something I could do to speed up the memory allocation? I tried allocating one large vector instead, but that failed with bad_malloc -- I guess a 10GB vector isn't ok.
我主要想通过解决这一部分来做出回应:bad_alloc异常易于被误解。它们不是“内存不足”的结果-它们是系统无法找到连续的未使用页面块的结果。如果您习惯于尝试分配大量的连续内存块,那么您可能拥有足够多的可用内存,并且仍然会得到一个bad_alloc,这仅仅是因为系统找不到一组空闲的连续页面。您不一定通过“确保有足够的可用内存”来避免bad_alloc,因为您可能已经看到,尝试分配仅10 GB的块时,超过100 GB的RAM仍然会使您容易受到攻击。避免它们的方法是在较小的块中分配内存,而不是分配一个史诗数组。在足够大的规模上,展开列表之类的结构可以开始在巨大的数组上提供良好的性能,并且获得bad_alloc异常的可能性要低得多(呈指数形式),除非您确实确实耗尽了所有可用内存。实际上存在一个峰值,在该峰值处连续性和它提供的引用局部不再变得有用,并且实际上可能以足够大的大小(主要是由于分页而不是缓存)阻碍了内存性能。

对于您要处理的史诗规模输入,鉴于它的页面友好特性,您实际上可能会从std::deque中获得更好的性能(这是双端队列真正可以发光的少数情况之一,不需要push_frontvector)。如果您不需要完美的连续性,可以尝试一下。

自然,最好是使用实际的探查器进行测量。它可以帮助我们深入研究实际问题,尽管鉴于您拥有“大量块”的种类,您可能在这里受到内存而不是磁盘IO的瓶颈可能并不完全令人震惊(令人惊讶,但也许并不令人震惊)。正在分配(磁盘IO速度很慢,但是如果您确实给系统施加压力,则内存堆分配有时可能会很昂贵)。这在很大程度上取决于系统的分配策略,但是如果您分配并存储这样的史诗级内存块,那么即使是平板分配器或伙伴分配器也可能会退回到一个慢得多的代码分支,并且分配甚至可能开始需要类似于搜索或更多访问的东西在那些极端情况下迁移到二级存储(在这里,我不确定分配这么多大块时到底是怎么回事,但是我已经“感觉到”并测量了这些瓶颈,但是在某种程度上我从来没有弄清楚过OS到底在做什么-上面的这段纯粹是推测。

这有点违反直觉,但分配大量较小的块通常可以提高性能。通常情况会使情况变得更糟,但是如果我们要谈论的是每个内存块300万个浮点数和类似的1000个内存块,则可能有助于开始分配页面友好的4k块。通常,预先在大块中预先分配内存并进行池化比较便宜,但是这种情况下的“大”更像是4 KB块,而不是10 GB块。
std::deque通常会为您执行此类操作,因此尝试查看是否有帮助可能是最快的方法。使用std::deque,您应该能够为所有10 GB的内容制作一个,而不必将其拆分成较小的内容以避免bad_alloc。它也没有某些引用的全部内容的零初始化开销,即使在最坏的情况下,它的push_backs也都是固定时间的(不像std::vector那样摊销固定时间),所以我会尝试使用实际上是std::deque,而不是预先调整大小并使用push_back。您可以一次读取一小块文件的内容(例如:使用4k字节缓冲区),而只需推回浮点数即可。无论如何都可以尝试。

无论如何,这些都是未经培训的猜测,没有代码和性能分析结果,但是这些是在测量后可以尝试的一些方法。

MMF也可能是此方案的理想解决方案。让操作系统处理访问文件内容所需的所有棘手细节。

关于c++ - 分配约10GB的 vector -如何加快速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33658908/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com