在不中断for循环的情况下重新启动R会话

时间:2018-01-17 15:59:49

标签: r

在我的for循环中,我需要删除RAM。所以我使用 rm() 命令删除了一些对象。然后,我做 gc() ,但RAM仍然相同

所以我使用 .rs.restartR() 而不是 gc() 并且它有效:在重新启动R后,我的RAM的足够部分被删除会话。

我的问题是在R重启后中断的for循环。您是否有意在 .rs.restartR() 命令后自动进行for循环?

5 个答案:

答案 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')
    }