foreach 执行:无法分配内存,而 RAM 仍然可用

foreach execution: cannot allocate memory, while RAM still available

在我几周前的最后一次 R 更新之前(我现在使用的是 4.1.0 (2021-05-18)),我 运行 在我的 19 个内核上并行执行以下代码(我有一台 Windows 机器,共有 24 个虚拟内核和 128 GB RAM 的共享内存)

nport.total.all <- c(seq(10,100,10),seq(200,1000,100))

n.portfolios <- length(nport.total.all) 

nsim <- 100000 

ncores <- length(nport.total.all)
nruns <- 20 
data.VaR.L <- matrix(data = 0,nrow = nruns, ncol = ncores)
data.VaR.E.L.Y <- matrix(data = 0,nrow = nruns, ncol = ncores)
data.VaR.Analytical <- matrix(data = 0,nrow = nruns, ncol = ncores)


library(doParallel)
library(foreach)
library(iterators)

cl <- makePSOCKcluster(names = ncores)
registerDoParallel(cl)
getDoParWorkers()

start_time <- Sys.time()

paralleltest <- foreach(core = 1:ncores) %dopar% {
  
  nport.total <- nport.total.all[core] 
  
  alpha.LGD <- 2 
  beta.LGD <- 3 
  E.LGD  <- (alpha.LGD / (alpha.LGD + beta.LGD)) 
  Var.LGD <- (alpha.LGD * beta.LGD) / ( (alpha.LGD+beta.LGD)^2 *(alpha.LGD + beta.LGD + 1) ) 
  EAD <- rep(x = 1000, times = nport.total) 
  w.i <- EAD/sum(EAD) 
  min.PD <- 0.0005
  max.PD <- 0.018
  mean.PD <- (min.PD + max.PD) / 2 
  PD <- rep(x = mean.PD, times = nport.total)
  c  <- qnorm(PD) 
  Rho.PD <- 0.12 * ( (1-exp(-50*PD)) / (1-exp(-50)) ) + 0.24 * ( 1 - ( (1-exp(-50*PD)) / (1-exp(-50)) ) )
  alpha <- 0.999 
  
  for (run in 1:nruns) { 
    
    # /!\ EMPIRICAL PART /!\ DISTRIBUTION OF L
    
    Y              <- matrix(data = rnorm(nsim), nrow = nport.total, ncol = nsim, byrow = TRUE)  
    Z.Default      <- matrix(data = rnorm(nsim * nport.total), nrow = nport.total, ncol = nsim, byrow = FALSE) 
    LGD.Basel      <- matrix(data = rbeta(n = (nsim * nport.total), shape1 = alpha.LGD, shape2 = beta.LGD, ncp = 0), nrow = nport.total, ncol = nsim) 
    
    X.Default <- sqrt(Rho.PD) * Y + sqrt(1 - (Rho.PD)) * Z.Default 
    
    rm(Z.Default)
    gc()
    
    Default <- 1 * (X.Default < c) 
    
    
    Basel.Rel.Loss <- w.i * LGD.Basel * Default 
    Basel.Port.Rel.Loss <- apply(Basel.Rel.Loss, 2, sum) 
    
    Ecdf.Basel.Port.Rel.Loss <- ecdf(Basel.Port.Rel.Loss)
    VaR.Rel.Port.Basel <- as.numeric(quantile(x = Ecdf.Basel.Port.Rel.Loss, prob = alpha))
    
    rm(Default,Basel.Rel.Loss,LGD.Basel)
    gc()
    
    ##########################################################################################################################################################################
    
    # /!\ EMPIRICAL PART /!\ DISTRIBUTION OF E[L|Y]
    
    PD.Conditional <- pnorm( (qnorm(PD) - sqrt(Rho.PD) * Y) / sqrt(1-Rho.PD) ) 
    
    
    Basel.E.cond.portfolio.loss.i <- w.i * E.LGD * PD.Conditional 
    Basel.E.cond.portfolio.loss <- apply(Basel.E.cond.portfolio.loss.i, 2, sum) 
    
    Ecdf.Basel.E.cond.portfolio.loss <- ecdf(Basel.E.cond.portfolio.loss)
    VaR.Basel.E.cond.portfolio.loss <- as.numeric(quantile(x = Ecdf.Basel.E.cond.portfolio.loss, prob = alpha))
    
    rm(PD.Conditional,Basel.E.cond.portfolio.loss.i)
    gc()
    
    ##########################################################################################################################################################################
    
    # /!\ ANALYTICAL FORMULAS /!\
    
    VaR.Ana.Quantile.Basel_i <- w.i * E.LGD * pnorm((qnorm(PD)-sqrt(Rho.PD)*qnorm(1-alpha)) / sqrt(1-Rho.PD)) 
    VaR.Ana.Quantile.Basel <- sum(VaR.Ana.Quantile.Basel_i) 
    
    ##########################################################################################################################################################################
    
    # SAVE THE GENERATED VAR
    
    data.VaR.L[run,core] <- VaR.Rel.Port.Basel
    data.VaR.E.L.Y[run,core] <- VaR.Basel.E.cond.portfolio.loss
    data.VaR.Analytical[run,core] <- VaR.Ana.Quantile.Basel
    
    rm(Y)
    gc()
    
  }
  
  return(list(data.VaR.L,data.VaR.E.L.Y,data.VaR.Analytical)) 
  
}

end_time <- Sys.time() 
time.sim <- end_time - start_time

stopCluster(cl) 

并行化策略如下:

尽管如此,根据设计,某些内核将不得不使用比其他内核更大的矩阵(由于影响每个内核的 nport.total 的不同值)。后者在早期的模拟中从来没有真正成为问题,它只是意味着要“完成自身”整个过程将不得不等待“最后一个核心”。

在我上次 R 更新之前,我能够增加/减少 nsim 值,这要归功于我的 RAM 可用性。但是,我目前无法增加 nsim 而不会出现以下错误消息之一(取决于我介绍的 nsim):

Error in { : task 17 failed - "cannot allocate vector of size 610.4 Mb"

我正在努力了解正在发生的事情/在 R 的引擎盖下可能发生了什么变化...当我使用任务管理器检查我的计算机资源使用情况时,我仍然有很多可用的 RAM:

直觉上,要么是

  1. R 不再允许/无法访问总 RAM。
  2. 我并行化的每个 CPU 都不允许访问整个 RAM(因此存在 CPU 无法共享整个 RAM 的问题)。

有人遇到过类似的问题吗?

验证您运行 的 R 版本是 64 位。如果不是,如果我没记错的话,RAM 分配限制为 4Gb。在 64 位 R 中,分配受可用内存限制。

在 RStudio 中: 工具 > 全局选项 > 常规 > R 版本

过去我的机器(24 核,128 Gb RAM,64 位)在看似随机的时间出于未知原因默认为 32 位 R 时遇到过问题。在全局选项中,我必须手动将 R 版本更改为 64 位以确保它不再发生。