光栅包占用了整个硬盘的空间问题

12

我正在处理一系列栅格数据的时间序列 (modis ndvi 图像),以计算该序列的平均值和标准偏差。每个年度序列由 23 张 ndvi.tif 图像组成,每张图像大小为 508Mb,总共需要处理的数据量达到 11Gb。下面是一个年度的脚本,我需要为多年重复这个过程。

library(raster)
library("rgeos")
filesndvi <- list.files(, pattern="NDVI.tif",full.names=TRUE) 
filesetndvi10 <- stack(filesndvi)
names(filesetndvi10)
avgndvi10<-mean(filesetndvi10)
desviondvi10 <- filesetndvi10 - avgndvi10
sumdesvioc <-sum(desviondvi10^2)
varndvi10  <- sumdesvioc/nlayers(filesetndvi10)
sdndvi10  <- sqrt(varndvi10)
cvndvi10  <- sdndvi10/avgndvi10

问题: 该进程会累加地写入硬盘,直到硬盘被填满。不知道进程在硬盘的哪里进行写入。唯一的清除硬盘的方法是重新启动。尝试过 rm 命令,但没有成功。尝试关闭 RStudio,也没有成功。我使用的是 R 3.0.2 和 RStudio 0.98.994,Ubuntu 14.04 操作系统,4GB RAM 的 Asus UX31 笔记本电脑,带有 256GB 硬盘。非常欢迎任何可以在每年计算后清除硬盘而无需重新启动的想法。谢谢。


2
最可能是 tempdir() - Dieter Menne
4个回答

14

有两件事需要考虑。首先,通过将calc或overlay函数中的步骤合并(这里的空间有限,但仍有一些),可以减少中间文件的数量。这也可以加速计算,因为读写磁盘的次数会减少。其次,控制删除特定的文件。在calc和overlay函数中,您可以提供文件名,以便删除不再需要的文件。但您也可以显式地删除临时文件。当然,最好先删除指向这些文件的对象。以下是基于您的示例的示例。

library(raster)
# example data
set.seed(0)
ndvi <- raster(nc=10, nr=10)
n1 <- setValues(ndvi, runif(100) * 2 - 1)
n2 <- setValues(ndvi, runif(100) * 2 - 1)
n3 <- setValues(ndvi, runif(100) * 2 - 1)
n4 <- setValues(ndvi, runif(100) * 2 - 1)
filesetndvi10 <- stack(n1, n2, n3, n4)

nl <- nlayers(filesetndvi10)
avgndvi10 <- mean(filesetndvi10)
desviondvi10_2 <- overlay(filesetndvi10, avgndvi10, fun=function(x, y) (x - y)^2 , filename='over_tmp.grd')
sdndvi10 <- calc(desviondvi10_2, fun=function(x) sqrt(sum(x) / nl), filename='calc_tmp.grd')
cvndvi10  <- overlay(xsdndvi10, avgndvi10, fun=function(x,y) x / y, filename='cvndvi10.grd', overwrite=TRUE)

f <- filename(avgndvi10)
rm(avgndvi10, desviondvi10_2, sdndvi10)
file.remove(c(f, extension(f, '.gri')))
file.remove(c('over_tmp.grd', 'over_tmp.gri', 'calc_tmp.grd', 'calc_tmp.gri'))

要查找临时文件写入的位置,请查看

rasterOptions()

或者要将路径作为变量获取,可以执行以下操作:

dirname(rasterTmpFile()) 

要设置路径,请使用

rasterOptions(tmpdir='a path')

6

我也遇到过同样的问题,但是有一些小技巧可以帮助解决这个问题。首先,增加内存。RAM和硬盘空间便宜并且对于处理大型R对象(例如光栅图像)会产生显著影响。其次,在光栅包中使用 removeTmpFiles()。你可以设置只删除比某一个小时数旧的临时文件,例如removeTmpFiles(0.5)将删除30分钟以前的临时文件。一定要确保只在不再需要调用这些文件时才进行设置。第三,使用类似下面的片段的 rasterOptions()。注意设置内存块大小;这些可能无法适用于您的系统,但是您可能会发现与默认值更优化的内容。最后,使用rm()gc()进行清理。希望这些技巧能够帮到你,如果你找到更好的解决方案,请告诉我。

tmpdir_name <- paste(c(drive, ":/RASTER_TEMP/"), collapse='')
if(file.exists(tmpdir_name) == FALSE){
    dir.create(tmpdir_name)
}

rasterOptions(datatype = "FLT4S", 
    progress = "text", 
    tmpdir = tmpdir_name, 
    tmptime = 4, 
    timer = TRUE,
    tolerance = 0.5,
    chunksize = 1e+08,
    maxmemory = 1e+09)

非常感谢您,ecos先生。我将删除临时文件。我发现它们位于/tmp/R_raster_myuser目录下。是的,我一定会购买更多的RAM,或者可能是一台并行计算机。干杯! - user2942623
关闭问题。我使用rasterOptions(tmpdir =“path”)解决了我的问题,将临时文件定向到3Tb的外部驱动器。这不是最优雅的解决方案,但它有效。 - user2942623
不确定您最后的评论:将临时文件写入外部磁盘可能会使计算速度变慢。只需使用上面的命令定期删除临时文件即可。 - Lucas Fortini
很高兴听到这个消息!如果您觉得这个答案有帮助,请点击勾选标志。谢谢! - Mr.ecos
要获取当前临时目录,请使用 dirname(rasterTmpFile())。要设置它,请使用 rasterOptions(tempdir='路径')。 - Robert Hijmans
显示剩余2条评论

5
我发现了另一种更适合我的方法来管理这个问题,借鉴于这个答案。在我的情况下,我正在使用并行循环,并且不想从临时目录中删除所有文件,因为它可能会删除其他进程的临时文件。

@RobertH的答案建议对每个单独的临时文件命名,但我不确定这是否手动强制栅格将即使是小文件也写入硬盘而不是使用RAM并减慢过程(栅格文档说只有当文件无法适应RAM时才会写入磁盘)。

所以,我所做的就是在循环或并行处理中创建一个临时目录,该目录与正在处理循环中的数据的唯一名称相关联,在我的情况下,这是single@data$OWNER的值:

#creates unique filepath for temp directory
dir.create (file.path("c:/",single@data$OWNER), showWarnings = FALSE)

#sets temp directory
rasterOptions(tmpdir=file.path("c:/",single@data$OWNER)) 

在此处插入您的处理代码,然后在循环结束时删除整个文件夹:

#removes entire temp directory without affecting other running processes
unlink(file.path("c:/",single@data$OWNER), recursive = TRUE)

0
也许这很显然,但我在实施本主题建议时发现的另一个提示是要注意处理指令的顺序。尽量避免批量执行相同的指令并“之后全部清除”。将代码原子化并清理小块。例如,而不是(来自上面):
[...]
nl <- nlayers(filesetndvi10)
avgndvi10 <- mean(filesetndvi10)

desviondvi10_2 <- overlay(filesetndvi10, avgndvi10, fun=function(x, y) (x - y)^2 , 
filename='over_tmp.grd')
sdndvi10 <- calc(desviondvi10_2, fun=function(x) sqrt(sum(x) / nl), filename='calc_tmp.grd')
cvndvi10  <- overlay(xsdndvi10, avgndvi10, fun=function(x,y) x / y, filename='cvndvi10.grd', overwrite=TRUE)

f <- filename(avgndvi10)
rm(avgndvi10, desviondvi10_2, sdndvi10)
file.remove(c(f, extension(f, '.gri')))
file.remove(c('over_tmp.grd', 'over_tmp.gri', 'calc_tmp.grd', 'calc_tmp.gri'))

这将需要更少的空间,无论是RAM还是驱动器方面:

[...]
nl <- nlayers(filesetndvi10)
avgndvi10 <- mean(filesetndvi10)

desviondvi10_2 <- overlay(filesetndvi10, avgndvi10, fun=function(x, y) (x - y)^2 , 
filename='over_tmp.grd')
rm(avgndvi10)
file.remove(c('over_tmp.grd', 'over_tmp.gri'))

sdndvi10 <- calc(desviondvi10_2, fun=function(x) sqrt(sum(x) / nl), filename='calc_tmp.grd')
rm(desviondvi10_2)
file.remove(c('calc_tmp.grd', 'calc_tmp.gri'))

cvndvi10  <- overlay(xsdndvi10, avgndvi10, fun=function(x,y) x / y, filename='cvndvi10.grd', overwrite=TRUE)
rm(sdndvi10)
file.remove(c('cvndvi10.grd', 'cvndvi10.gri'))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接