我目前正在构建一个使用 vector 类动态处理大量内存的代码。
代码正在使用 push_back 构建 vector ,其中重要的是要注意 vector 是二维的,表示数据矩阵。根据情况,该矩阵可能很小,也可能变得异常大。
例如,数据矩阵可以有几行,每行1000列,也可以有1000行,列数相同,全是double数据类型。显然,这很容易成为一个问题,因为 1000x1000x8 = 8 000 000 字节,因此在内存中代表 8 MB。但是多 10 倍的列和多 10 倍的行呢? (这很容易在我的代码中发生)。
我通过将数据矩阵写入硬盘来解决这个问题,但是这种方法相当慢,因为我没有充分利用 RAM。
我的问题:
如何构建由 vector< vector<double> > 表示的矩阵使用 push_back , 但前提是有足够的内存可以分配。
如果内存量不够,我会继续将数据导出到 HDD 到文件中,释放分配的内存并重新开始循环。我不知道的是如何检查每个 push_back 的内存是否可用。执行。
编辑: 我应该注意到我正在使用运行 Ubuntu 的 64 位机器。我不太确定操作系统分页如何以及是否正在运行,但我实际上正在做的是在存在电场和磁场的情况下对粒子进行数值计算。可能有 1 亿个粒子在超过 1000 个时间步长内移动,这是大量 GB 的数据。然而,有时我只运行几十万个粒子进行测试,这些粒子可以毫无问题地装入 RAM,从而加快了计算过程。我正在尝试创建某种通用的解决方案,该解决方案将检查是否有足够的 RAM 用于另一次计算,如果没有,则将它们移动到一个文件中。这些粒子可以添加到系统中或从中流出,所以基本上我不知道矩阵在任何给定时间会有多大。这就是为什么我需要“好吧,够了,将这些数据移出此处,以便我们可以重新开始”的方法。
最佳答案
几乎所有“我将在我的代码中将数据推送到磁盘”的替代方案都比这更好。
这是因为操作系统本身(如果我们谈论的是合理的现代操作系统,例如 Windows NT 系列和大多数 Unix 变体,包括 Linux 和 MacOS X)具有处理虚拟内存和交换到磁盘的能力,并且它将以比您可能想出的更聪明的方式来做到这一点。
此外(根据 Tony D 的评论),使用“内存映射文件”是比手动读取/写入文件更好的方法 - 这不会立即与 std::vector 一起使用或其他标准集合,但可能比在您的应用程序中手动处理读/写文件更好的选择 - 您只需说“这是一个文件,请给我一个指向代表该文件的一 block 内存的指针”,然后您使用该指针就好像文件已加载到内存中一样。操作系统将负责管理文件的哪些部分在任何给定时间实际物理存在于内存中,类似于如果您分配的内存多于系统中存在的内存,则换入和换出。
但是,这当然有限制(适用于“为您的应用程序分配超过可用 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">,以及 6 * 4 = 24 个字节作为 float。
乘以 100M,我们得到一组数据 4.8GB。乘以 1000 个时间步,产生 4.8TB 的数据。这是一个巨大的数量,即使你有非常大的内存。使用内存映射文件并不能真正将所有这些数据一次保存在内存中。如果你的机器有相当大的内存(16GB 左右),一次在内存中保存两套可能会奏效。但是您仍然会产生大量需要在某个时候存储的数据,这很可能会花费大部分时间。对于相当现代的(单个)硬盘,50-100MB/s 左右的速度是一个合理的期望值。它可以通过某些 RAID 配置进行改进,但即使是它们,它也是每秒数百兆字节,而不是每秒千兆字节。因此,以 100MB/s 的速度存储 1TB (1000GB) 需要 10000 秒,或大约三个小时。 4.8TB 需要 15 小时。那只是存储数据,没有计算 [尽管这可能是最小的部分]。即使我们将数据集除以 10,我们也有一个多小时,除以 50,我们在分钟范围内。
无论您使用什么方法,存储和检索如此大的数据集至少可以说是非常耗时的。内存映射文件在很多方面都是“最不坏的”,因为它在这个过程中复制的数据少了一点。但是“磁盘速度”仍然是您计算速度的主导因素。
关于c++ - 仅当有足够内存可用时 vector push_back,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24547294/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e
有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=
出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t