Vector push_back仅当有足够的内存可用时

Vector push_back only if enough memory is available

本文关键字:内存 push back Vector      更新时间:2023-10-16

我目前正在构建一个使用vector类动态处理大量内存的代码。

代码正在用push_back构建向量,其中重要的是要注意向量是二维的,表示数据矩阵。根据具体情况,这个矩阵可以很小,也可以变得特别大。

例如,数据矩阵可以有很少的行,每一行有1000列,或者它可以得到1000行,具有相同数量的列,充满双数据类型。显然,这很容易成为一个问题,因为1000x1000x8 = 8 000 000字节,因此在内存中表示8 MB。但是如果是10倍的列和10倍的行呢?(这在我的代码中很容易发生)。

我通过将数据矩阵写入HDD来解决这个问题,但是这种方法相当慢,因为我没有充分使用RAM。

我的问题:如何使用push_back构建由vector< vector<double> >表示的矩阵,但前提是可以分配足够的内存。

如果内存量不够,我将继续将数据导出到HDD到一个文件中,释放分配的内存并重新开始循环。我不知道的是如何检查每个push_back执行时内存是否可用。

编辑:

我应该注意到我使用的是运行Ubuntu的64位机器。我不太确定操作系统分页是如何运行的,以及是否在运行,但是我实际上在做的是电场和磁场下粒子的数值计算。可能有1亿个粒子以超过1000个时间步移动,这是很多GB的数据。然而,有时我只运行数十万个粒子进行测试,这些测试可以毫无问题地装入RAM,从而加快了计算过程。我正在尝试创建某种通用的解决方案,以检查是否有足够的RAM用于另一个计算,如果没有,则将它们移动到文件中。这些粒子可以加入系统,也可以从系统中流出,所以基本上我不知道在任何给定的时间矩阵有多大。这就是为什么我需要"ok, That 's enough, move those data out from here,这样我们就可以重新开始了"方法

几乎所有替代"我将把数据推送到我的代码中的磁盘"都比这更好。

这是因为操作系统本身(如果我们谈论的是相当现代的操作系统,如Windows NT家族和Unix的大多数变体,包括Linux和MacOS X)有能力处理虚拟内存和交换磁盘,而且它会以一种比你可能想到的更聪明的方式来做到这一点。

进一步(按托尼D的评论),使用内存映射文件是一个更好的方法比手动读/写文件——这不会立即std::vector或其他标准的集合,但可能是一个更好的选择比手动处理读/写文件在您的应用程序,你简单地说"这是一个文件,请给我一个指针指向一块内存代表文件",你使用这个指针如果文件被加载到内存中。操作系统将负责管理文件的哪些部分在任何给定时间实际存在于内存中,类似于如果您分配的内存比系统中现有的内存多,则交换入和取出。

然而,这当然有限制(适用于"为应用程序分配超过可用RAM和内存映射文件解决方案")。如果你使用的是32位机器(或32位操作系统或32位应用程序),你的进程可用的最大内存将在2GB到4GB之间——确切的限制取决于操作系统(64位操作系统和32位应用程序可能会给你将近4GB, 32位Windows的常规设置会给你大约2GB)。因此,如果你的数组变得足够大,地址中就没有"足够的位"来跟踪它。此时,您需要以某种方式拆分工作。或者转到64位操作系统和应用程序(这里自然需要64位处理器),在这种情况下,内存大小的限制为128或256TB(如果我的脑力运动有效- 65536 * 4GB) -这可能比几乎每个人的磁盘空间都多,更不用说RAM了。

编辑:

根据你给出的数据做一些数学计算:每个粒子都有X, Y, Z位置,速度和"其他两个属性",double将占用6 * 8 = 48个字节,float将占用6 * 4 = 24个字节。

乘以100M,我们得到4.8GB的一组数据。乘以1000个时间步长,产生4.8TB的数据。这是一个巨大的量,即使你有非常大的内存。使用内存映射文件实际上并不能一次将所有这些数据保存在内存中。如果您的机器有相当多的内存(16GB左右),那么一次保留两组内存可能是可行的。但是您仍然会产生大量需要在某个时刻存储的数据,这很可能会占用大部分时间。对于一个相当现代的(单个)硬盘,大约50-100MB/s是一个合理的期望。它可以通过某些RAID配置来改进,但即使这样,它也是每秒数百兆字节,而不是每秒多少千兆字节。因此,以100MB/s的速度存储1tb (1000GB)将花费10000s,或者大约三个小时。4.8TB需要15小时。这只是为了存储数据,没有计算(尽管这可能是最小的部分)。即使我们把数据集除以10,我们有一个多小时,除以50,我们在分钟范围内。

不管你用什么方法,存储和检索这样大的数据集至少是很耗时的。内存映射文件在许多方面都是"最不坏的",因为它在进程中复制的数据要少一些。但是"磁盘速度"仍然是决定计算速度的主要因素。