并行处理时未写入列表的栅格

Rasters not written to list when parallel procesing

我可能做错了,但这就是我想做的...... 我有两个需要更正的大栅格。由于 R 仅在一个内核上工作,因此我想使用并行处理。所以我将两个栅格拆分为更小的栅格,我想在这些栅格上执行我的任务。之后我会将较小的栅格合并为一个。

我的问题是,在 foreach 循环中,应该创建新对象 - 我将它们保存到列表中。但是列表仍然是空的。

library(raster)
library(rgdal)
library(SpaDES)
library(doParallel)


dmp <- raster("exampe1.tif"))
luc <- raster("example2.sdat"))

UseCores <- parallel::detectCores()-1  #Define how many cores you want to use
cl       <- makeCluster(UseCores)      #Register CoreCluster
registerDoParallel(cl)

dmp_s <- splitRaster(dmp, nx= 10, ny = 10)   #Split raster to smaller rasters
luc_s <- splitRaster(luc, nx= 10, ny = 10)   #Split raster to smaller rasters

dmp_s_copy <- dmp_s
luc_s_copy <- luc_s


dmp1 <- vector(mode = 'list', length = length(dmp_s))
m <- vector(mode = 'list', length = length(dmp_s))
dmp2 <- vector(mode = 'list', length = length(dmp_s))
dmp_list <- vector(mode = 'list', length = length(dmp_s))
dmp_stack <- vector(mode = 'list', length = length(dmp_s))
dmp_final1 <- vector(mode = 'list', length = length(dmp_s))

foreach(i=1:length(dmp_s)) %dopar% {
  dmp1[i] <- dmp_s[[i]] * luc_s[[i]]
  
  m[[i]] <- matrix(1, ncol=5, nrow=5)
  dmp2[[i]] <- raster::focal(dmp1[[i]], w=m[[i]], fun=max, na.rm=TRUE, pad=TRUE, NAonly=TRUE)
  
  dmp_list[[i]] <- list(dmp_s[[i]], dmp2[[i]])
  dmp_stack[[i]] <- stack(dmp_list[[i]])
  
  dmp_final1[[i]] <- min(dmp_stack[[i]])
  
}

dmp_final <- mergeRaster(dmp_final1)

如果我不使用并行处理,代码可以工作,但我需要它。我如何让它发挥作用?

我认为这可能是因为将几个列表位置启动到并行集群中。取决于您 OS 这可能会导致问题。在这种情况下,我使用“fork”类型(仅在 linux 中)来节省一些内存,但如果您使用 windows,只需将“FORK”替换为“PSOCK”。不管怎样,我实现了两个东西:

  1. 更快的光栅分割函数。
  2. 一个整洁的并行进程(避免可能导致内存问题的中间对象)。

代码如下:

library(raster)
library(rgdal)
library(SpaDES)
library(doParallel)
library(mapview)

# read data
dmp <- raster("./data/example1.tif")
luc <- raster("./data/example2.tif")

# split rasters (this is slow)
# dmp_s <- splitRaster(dmp, nx= 100, ny = 100)   #Split raster to smaller rasters
# luc_s <- splitRaster(luc, nx= 100, ny = 100)   #Split raster to smaller rasters

# Function to split rasters (adapted from 
SplitRas <- function(raster, split){
        h <- ceiling(ncol(raster)/split)
        v <- ceiling(nrow(raster)/split)
        agg <- aggregate(raster,fact=c(h,v))
        agg[] <- 1:ncell(agg)
        agg_poly <- rasterToPolygons(agg)
        names(agg_poly) <- "polis"
        r_list <- list()
        for(i in 1:ncell(agg)){
                e1 <- extent(agg_poly[agg_poly$polis==i,])
                r_list[[i]] <- crop(raster,e1)
        }
        return(r_list)
}

# Apply function to split rasters
dmp_s <- SplitRas(dmp, 10)
luc_s <- SplitRas(luc, 10)

# start cluster & process
UseCores <- parallel::detectCores()-1  #Define how many cores you want to use
cl       <- makeCluster(UseCores, type="FORK")      #Register CoreCluster
doParallel::registerDoParallel(cl)

dmp_final1 <- foreach(i=1:length(dmp_s)) %dopar% {
        x1 <- dmp_s[[i]] * luc_s[[i]]
        m <- matrix(1, ncol=5, nrow=5)
        x2 <- raster::focal(x1, w=m, fun=max, na.rm=TRUE, pad=TRUE, NAonly=TRUE)
        min(stack(list(x1, x2)))
}

# stop cluster
stopCluster(cl)

# merge products
dmp_final <- mergeRaster(dmp_final1)

# showmap
mapview(dmp_final)