如何提高处理大型光栅堆栈的 R 处理速度?
How to increase R processing speed dealing with large raster stacks?
我正在处理大型光栅堆栈,我需要重新采样并裁剪它们。
我阅读了 Tiff 文件列表并创建了堆栈:
files <- list.files(path=".", pattern="tif", all.files=FALSE, full.names=TRUE)
s <- stack(files)
r <- raster("raster.tif")
s_re <- resample(s, r,method='bilinear')
e <- extent(-180, 180, -60, 90)
s_crop <- crop(s_re, e)
这个过程需要几天才能完成!但是,使用 ArcPy 和 python 速度要快得多。我的问题是:为什么在 R 中这个过程这么慢,是否有办法加快这个过程? (我使用 snow 包进行并行处理,但这也没有帮助)。
这些是 r
和 s
层:
> r
class : RasterLayer
dimensions : 3000, 7200, 21600000 (nrow, ncol, ncell)
resolution : 0.05, 0.05 (x, y)
extent : -180, 180, -59.99999, 90.00001 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
> s
class : RasterStack
dimensions : 2160, 4320, 9331200, 365 (nrow, ncol, ncell, nlayers)
resolution : 0.08333333, 0.08333333 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
我支持@JoshO'Brien 的直接使用 GDAL 的建议,gdalUtils
使这变得简单明了。
下面是一个使用与您尺寸相同的双精度网格的示例。对于 10 个文件,在我的系统上大约需要 55 秒。它是线性扩展的,因此 365 个文件大约需要 33 分钟。
library(gdalUtils)
library(raster)
# Create 10 rasters with random values, and write to temp files
ff <- replicate(10, tempfile(fileext='.tif'))
writeRaster(stack(replicate(10, {
raster(matrix(runif(2160*4320), 2160),
xmn=-180, xmx=180, ymn=-90, ymx=90)
})), ff, bylayer=TRUE)
# Define clipping extent and res
e <- bbox(extent(-180, 180, -60, 90))
tr <- c(0.05, 0.05)
# Use gdalwarp to resample and clip
# Here, ff is my vector of tempfiles, but you'll use your `files` vector
# The clipped files are written to the same file names as your `files`
# vector, but with the suffix "_clipped". Change as desired.
system.time(sapply(ff, function(f) {
gdalwarp(f, sub('\.tif', '_clipped.tif', f), tr=tr, r='bilinear',
te=c(e), multi=TRUE)
}))
## user system elapsed
## 0.34 0.64 54.45
您可以进一步并行化,例如 parLapply
:
library(parallel)
cl <- makeCluster(4)
clusterEvalQ(cl, library(gdalUtils))
clusterExport(cl, c('tr', 'e'))
system.time(parLapply(cl, ff, function(f) {
gdalwarp(f, sub('\.tif', '_clipped.tif', f), tr=tr,
r='bilinear', te=c(e), multi=TRUE)
}))
## user system elapsed
## 0.05 0.00 31.92
stopCluster(cl)
10 个网格的 32 秒(使用 4 个同步进程),您正在查看 365 个文件的大约 20 分钟。实际上,它应该比这更快,因为两个线程可能最后什么都不做(10 不是 4 的倍数)。
为了比较,这是我得到的:
library(raster)
r <- raster(nrow=3000, ncol=7200, ymn=-60, ymx=90)
s <- raster(nrow=2160, ncol=4320)
values(s) <- 1:ncell(s)
s <- writeRaster(s, 'test.tif')
x <- system.time(resample(s, r, method='bilinear'))
# user system elapsed
# 15.26 2.56 17.83
10 个文件需要 150 秒。所以我预计 365 个文件需要 1.5 小时 --- 但我没有尝试过。
我正在处理大型光栅堆栈,我需要重新采样并裁剪它们。 我阅读了 Tiff 文件列表并创建了堆栈:
files <- list.files(path=".", pattern="tif", all.files=FALSE, full.names=TRUE)
s <- stack(files)
r <- raster("raster.tif")
s_re <- resample(s, r,method='bilinear')
e <- extent(-180, 180, -60, 90)
s_crop <- crop(s_re, e)
这个过程需要几天才能完成!但是,使用 ArcPy 和 python 速度要快得多。我的问题是:为什么在 R 中这个过程这么慢,是否有办法加快这个过程? (我使用 snow 包进行并行处理,但这也没有帮助)。
这些是 r
和 s
层:
> r
class : RasterLayer
dimensions : 3000, 7200, 21600000 (nrow, ncol, ncell)
resolution : 0.05, 0.05 (x, y)
extent : -180, 180, -59.99999, 90.00001 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
> s
class : RasterStack
dimensions : 2160, 4320, 9331200, 365 (nrow, ncol, ncell, nlayers)
resolution : 0.08333333, 0.08333333 (x, y)
extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
我支持@JoshO'Brien 的直接使用 GDAL 的建议,gdalUtils
使这变得简单明了。
下面是一个使用与您尺寸相同的双精度网格的示例。对于 10 个文件,在我的系统上大约需要 55 秒。它是线性扩展的,因此 365 个文件大约需要 33 分钟。
library(gdalUtils)
library(raster)
# Create 10 rasters with random values, and write to temp files
ff <- replicate(10, tempfile(fileext='.tif'))
writeRaster(stack(replicate(10, {
raster(matrix(runif(2160*4320), 2160),
xmn=-180, xmx=180, ymn=-90, ymx=90)
})), ff, bylayer=TRUE)
# Define clipping extent and res
e <- bbox(extent(-180, 180, -60, 90))
tr <- c(0.05, 0.05)
# Use gdalwarp to resample and clip
# Here, ff is my vector of tempfiles, but you'll use your `files` vector
# The clipped files are written to the same file names as your `files`
# vector, but with the suffix "_clipped". Change as desired.
system.time(sapply(ff, function(f) {
gdalwarp(f, sub('\.tif', '_clipped.tif', f), tr=tr, r='bilinear',
te=c(e), multi=TRUE)
}))
## user system elapsed
## 0.34 0.64 54.45
您可以进一步并行化,例如 parLapply
:
library(parallel)
cl <- makeCluster(4)
clusterEvalQ(cl, library(gdalUtils))
clusterExport(cl, c('tr', 'e'))
system.time(parLapply(cl, ff, function(f) {
gdalwarp(f, sub('\.tif', '_clipped.tif', f), tr=tr,
r='bilinear', te=c(e), multi=TRUE)
}))
## user system elapsed
## 0.05 0.00 31.92
stopCluster(cl)
10 个网格的 32 秒(使用 4 个同步进程),您正在查看 365 个文件的大约 20 分钟。实际上,它应该比这更快,因为两个线程可能最后什么都不做(10 不是 4 的倍数)。
为了比较,这是我得到的:
library(raster)
r <- raster(nrow=3000, ncol=7200, ymn=-60, ymx=90)
s <- raster(nrow=2160, ncol=4320)
values(s) <- 1:ncell(s)
s <- writeRaster(s, 'test.tif')
x <- system.time(resample(s, r, method='bilinear'))
# user system elapsed
# 15.26 2.56 17.83
10 个文件需要 150 秒。所以我预计 365 个文件需要 1.5 小时 --- 但我没有尝试过。