【问题标题】:Prevent simulation from being killed by OS防止模拟被操作系统杀死
【发布时间】:2012-07-09 08:58:36
【问题描述】:

这不是家庭作业,只是我的学习练习。我一直在 R 中运行一个非常简单的模拟(或数字曲柄)。它生成两个数字(A,B)并运行 1 个月。

A=NULL
B=NULL
x=NULL
x <- Sys.time()
duration <-  2592000 # 30 days
while(Sys.time() <= x + duration){
A <-append(A, sample(1:5, 1000, 1/5))
B <-append(B, sample(1:5, 1000, 1/5))
save.image()
}

我认为它进展顺利,但一周后(产生了数百万个数字),操作系统终止了该进程。 有没有更好的方法来编写或运行模拟来防止操作系统杀死它?

我宁愿重写模拟而不是适应操作系统(例如添加更多交换等)。我在低功率设备(Raspberry Pi)上运行模拟,并且在硬件方面我能做的事情有限。谢谢。

更新:
1) 一次生成 1000 个样本并不重要。这只是我的笨拙。
2) 模拟运行一段时间(即 1 周、1 个月或 1 年)很重要
3) 除非不可能,否则我想要原始数据。

【问题讨论】:

  • 我的猜测是它溢出了你的记忆。
  • 这对我来说很难重现。 :) 进程被杀死时是否有任何错误消息?您是否监控内存使用情况?写入单个 (txt) 文件不是也有意义吗?
  • 我的猜测是,通过附加越来越大的向量,您的系统不喜欢 something。我会通过生成一个大向量来解决这个问题,然后将其写入(附加 = TRUE)到单个文本文件或数据库中。
  • 我的建议是你在每个循环中总结你的数据,然后将总结保存到磁盘。这应该可以防止出现可寻址空间(内存或磁盘)不足的问题。
  • @plannapus 那是另一个部门的问题。 :) 分析大数据的一种方法是将其抽样成可管理的部分。如果你有一个有代表性的样本,那么 1000 个点就相当于 10 亿个。如果将其存储到数据库中,R 中有很多工具可以处理这类计算。

标签: r simulation


【解决方案1】:

如果您考虑将结果打印在纸上作为可接受的解决方案,那么 Roman Luštrik 的解决方案(在您的问题的 cmets 中)将您的数据附加到文本文件或数据库绝对是一个很好的解决方案。

这是附加到文本文件的样子:

x <- Sys.time()
duration <-  2592000
while(Sys.time() <= x + duration){
    write.table(sample(1:5, 1000, 1/5),file="A.txt",append=TRUE,row.names=FALSE,col.names=FALSE,sep="\t")
    write.table(sample(1:5, 1000, 1/5),file="B.txt",append=TRUE,row.names=FALSE,col.names=FALSE,sep="\t")
}

【讨论】:

  • 谢谢。您是否认为这将运行一个月,而不是问题中发布的版本没有?我很乐意对其进行测试。
  • 好吧,我不会尝试,但请随意尝试。文本文件将非常庞大,因此请确保您有足够的磁盘空间。否则,由于您实际上并没有保留一个不断增长的对象,我认为内存(或浮点)不会成为问题....
  • 效率太高了,他会用完磁盘(这次不是内存)空间。
  • 您可能需要它们:1 分钟后,两个文件都已经 27Mb 大了。
  • 显然他需要以可用的最高压缩率压缩他的数据,以避免覆盖他的硬盘驱动器上的内核 或者更好的是,只需存储他的五个可能输出值的直方图
【解决方案2】:

如果目标是创建两个大样本,请考虑以下事项:

N <- 2000000
A <- sample(1:5, N, 1/5)
B <- sample(1:5, N, 1/5)
save.image()

如果对于 A 和 B 一次形成 1000 个样本很重要,请考虑以下问题:

N <- 2000
n <- 1000
A.list <- vector("list", N)
B.list <- vector("list", N)
for (i in 1:N) {
   A.list[[i]] <- sample(1:5, n, 1/5) 
   B.list[[i]] <- sample(1:5, n, 1/5)
}
A <- unlist(A.list)
B <- unlist(B.list)
save.image()

这应该解决代码中的两个主要问题:

  • 每次在循环中使用append 时,R 都必须从头开始创建和填充几个新对象。随着对象变大,你的循环迭代变得越来越慢;我相信计算时间是二次增长的。您还冒着内存空间碎片化的风险,这很难解释,但您可以尝试研究它。通过使用列表,只需将每次迭代的新数据存储到内存中,并且每次循环的计算时间保持不变。
  • 我已将 save.image() 移出循环。同样的想法,随着对象变得越来越大而保存对象将花费越来越长的时间,即减慢您的迭代速度。由于您只关心最终向量,因此仅在完成后保存才有意义。

您可以使用N 的值来查看您的操作系统会让您走多远。优点是您不必等待一周或一个月来找出限制。

【讨论】:

  • 出于哲学原因,我希望运行模拟 1 个月。这是模拟的重要部分。这似乎是一个奇怪的请求,但它确实存在。感谢您提出一个想法。
  • 你可以在我的循环中间放一个Sys.sleep(2592000 / N)。给你。
  • 呃。这不是作弊吗?我想生成 A 和 B 一个月。不用一个月就可以生成一个大集数。细微的差别?
  • 好吧,可能是星期一凌晨,但“哲学”与现实有什么关系?你真正想做什么?测试sample在不同月相下的操作是否不同?您向我们展示的不是“模拟”,而是数字曲柄。有很多更简单的方法可以找到操作系统对 RAM、文件大小等的各种限制。也许如果您能解释您实际想要找出的内容,我们可以提供适当的方法。
  • 您正试图在内存中创建一个不断增长的数据集:当您到达 R 分配的内存时,您注定会失败。因此,如果您希望您的程序可以正常运行一个月,即没有达到该限制,您需要编写 less 高效的代码。我知道,这听起来很疯狂,但到目前为止你做得很好,所以继续努力吧。例如,您可以编写自己的 appendsample 函数,并尽可能降低它们的效率。你甚至可以向对编程一无所知的人寻求帮助。希望对您有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多