在我的for循环中,我需要删除RAM。所以我使用 rm()
命令删除了一些对象。然后,我做 gc()
,但RAM仍然相同
所以我使用 .rs.restartR()
而不是 gc()
并且它有效:在重新启动R后,我的RAM的足够部分被删除会话。
我的问题是在R重启后中断的for循环。您是否有意在 .rs.restartR()
命令后自动进行for循环?
答案 0 :(得分:4)
我只是偶然发现了这篇文章,因为我有一个类似的问题,rm()没有按预期清除内存。像你一样,如果我杀死脚本,使用rm(list = ls(all.names = TRUE))删除所有内容并重新启动,脚本需要比最初更长的时间。但是,使用.rs.restartR()重新启动会话,然后再次采购按预期工作。正如你所说,没有办法刷新'在循环中的会话。
我的解决方案是编写一个简单的bash脚本来调用我的.r文件。
假设您在R中有一个从1到3运行的循环,并且您希望在每次迭代后重新启动会话。我的bash脚本' runR.sh'可以理解如下:
#!/bin/bash
for i in {1..3}
do
echo "Rscript myRcode.r $i" #check call to r script is as expected
Rscript myRcode.r $i
done
然后在myRcode.r'
的顶部args <- commandArgs()
print(args) #list the command line arguments.
myvar <- as.numeric(args[6])
并删除您的for (myvar in...){}
,只保留循环的内容。
您将从print(args)
看到您的shell脚本输入是数组的第6个元素,因此在分配变量时,以下行中为args[6]
。如果你传入一个字符串,例如一个文件名,当然你不需要as.numeric。
然后运行./runR.sh
将调用您的脚本并希望解决您的内存问题。唯一的小问题是你每次都必须重新加载你的包,这与使用.rs.restartR()不同,并且可能必须重复通常只运行一次的其他位。
它适用于我的情况,我很想听听其他经验丰富的R / bash用户是否对此解决方案有任何问题......
答案 1 :(得分:2)
你有想法在.rs.restartR()命令之后自动进行for循环吗?
这是不可能的。
好的,您可以将R系统配置为执行此类操作,但这听起来不错。我不确定你是想从头开始重新启动for
循环还是从停止的地方拿起它。 (我也很困惑,你似乎能够在执行for
循环时在R控制台中输入命令。我认为不仅仅是你没有告诉我们。 )
您可以使用rprofile.site
文件在R启动时自动运行命令。您可以将其设置为在R启动时自动运行for循环代码。但这似乎是一个坏主意。我认为你应该为你的问题找到一种不同的解决方案。
您可以采取一些措施来帮助解决问题:将每次迭代的for
循环写入输出写入磁盘,并将某种日志写入磁盘,以便知道中断的位置。也许围绕你的for循环编写一个函数,该函数接受从哪里开始的参数,这样你就可以随时“跳入”。
使用这种方法,而不是“重新启动R并自动拾取循环”,更好的选择是使用Rscript(或类似)并使用R或命令行来顺序运行每次迭代(或一批迭代)在自己的R会议中。
最好的解决方法是在不重新启动的情况下解决内存问题。有关内存管理的SO有几个问题 - 尝试解决问题,如果它们不起作用,请制作一个可重现的示例并提出一个新问题。
答案 2 :(得分:2)
通过将迭代保存为外部文件,并编写一个调用自身的rscript,可以在rstudio中的for循环内重新启动会话。此示例需要执行以下步骤。
#Save an the iteration as a separate .RData file in the working directory.
iter <- 1
save(iter, file="iter.RData")
创建一个脚本,该脚本将自身进行一定数量的迭代。将以下脚本另存为“ test_script.R”
###load iteration
library(rstudioapi)
load("iter.RData")
###insert function here.
time_now <- Sys.time()
###save output of function to a file.
save(time_now, file=paste0("time_", iter, ".Rdata"))
###update iteration
iter <- iter+1
save(iter, file="iter.RData")
###restart session calling the script again
if(iter < 5){
restartSession(command='source("test_script.R")')
}
答案 3 :(得分:0)
重新启动会话后,您可以通过自行采购来使脚本递归。
确保脚本将考虑循环的初始状态。因此,在重新启动会话之前,您可能必须将循环的当前状态保存在.rds文件中。重新启动会话后,然后从循环内部调用.rds文件。这将帮助您在重新启动r会话之前启动循环。
我刚刚发现有关此命令'restartSession'的信息。我之所以使用它,是因为我还遇到了内存消耗问题,因为垃圾收集器不会将RAM返还给OS(Linux)。
library(rstudioapi)
restartSession(command = "print('x')")
答案 4 :(得分:0)
一种独立于Rstudio的方法:
如果要在Rstudio中运行此程序,请不要使用R控制台,而应使用终端机,否则请像其他答案一样使用rstudioapi::restartSession()
-不推荐(崩溃)-。
创建迭代器并加载脚本(在系统终端中为:)
R -e 'saveRDS(1,"i.rds"); source("Script.R")'
Script.R文件:
# read files and iterator
i<-readRDS("i.rds")
print(i)
# open process id of previous loop to kill it
tryCatch(pid <- readRDS(file="pid.rds"), error=function(e){NA} )
if (exists("pid")){
library(tools)
tools::pskill(pid, SIGKILL)
}
# update objects and iterator
i <- i+1
# process
pid <- Sys.getpid()
# save files and iterator
saveRDS(i, file="i.rds")
# process ID to close it in next loop
saveRDS(pid, file="pid.rds")
### restart session calling the script again
if(i <= 20 ) {
print(paste("Processing of", i-1,"ended, restarting") )
assign('.Last', function() {system('Rscript Script.R')} )
q(save = 'no')
}