R语言ensembleBMA包ensemblegamma0()函数并行化改造问题咨询
错误问题排查
你修改后的代码存在以下核心问题:
- 入参逻辑错误:
future_lapply直接遍历juliandates向量,此时函数内的i是日期数值而非原串行循环中1~nDates的索引值,用该值索引dates、trainTable等数组必然出现下标越界错误。 - 变量作用域问题:并行子进程的内存空间独立,你在子进程内修改
prob0coefs、biasCoefs、l等主进程预先定义的变量不会同步到主进程,运行结束后主进程的数组仍为空值。另外原串行逻辑中l是按顺序迭代的缓存变量,并行场景下任务无固定执行顺序,该缓存逻辑直接失效。 - 语法错误:
next是R for循环的专属关键字,不能在lapply类的匿名函数中使用,会直接触发语法报错。 - 代码结构错误:你将最终返回
structure的逻辑错误嵌套进了future_lapply的语法范围内,括号匹配错误,且并行返回的结果列表也不能直接作为函数返回值。
改造方案
按以下逻辑修改即可正常运行:
- 把单日拟合逻辑拆成独立函数,输入为日期索引
i,输出为单日的所有拟合结果,不要在函数内修改外部变量 - 遍历索引序列而非日期值,去掉依赖执行顺序的
l缓存逻辑 - 所有
next替换为return()返回错误标识 - 主进程收集所有并行结果后,统一填充到结果数组中,再生成最终返回对象
简化的改造示例:
library(future.apply) plan(multisession) # 跨平台兼容的并行方案 # 原函数前半部分预处理逻辑保持不变,直到循环部分替换为以下代码 # ---------------------- 并行逻辑替换 ---------------------- # 定义单日拟合函数 fit_single_date <- function(i) { res <- list(error = FALSE, i = i) I <- (juliandates[i]-lag*incr) >= julianDATES if (!any(I)) { warning("insufficient training data for date ", dates[i]) res$error <- TRUE return(res) } j <- which(I)[sum(I)] # 去掉l缓存逻辑,每个日期单独处理 D <- as.logical(match(Dates, DATES[j:1], nomatch=0)) nonz <- sum(obs[D] != 0) if (is.null(control$prior) && nonz < control$rainobs) { cat("insufficient nonzero training obs for date", dates[i], "...\n") res$error <- TRUE return(res) } twin <- (j+1) - (1:trainingDays) if (is.null(control$prior)) { while (TRUE) { D <- as.logical(match(Dates, DATES[twin], nomatch=0)) if (!any(D)) { res$error <- TRUE return(res) } nonz <- sum(obs[D] != 0) if (nonz >= control$rainobs) break if (min(twin) == 1) { if(nonz < control$rainobs) { cat("insufficient nonzero training obs for date", dates[i], "...\n") res$error <- TRUE return(res) } break } twin <- max(twin):(min(twin)-1) } } cat("modeling for date", dates[i], "...\n") kNA <- apply(ensembleForecasts(ensembleData[D,]), 2, function(x) all(is.na(x))) if (any(kNA)) { x <- exchangeable if (!is.null(x)) x <- exchangeable[-K[kNA]] fit <- fitBMAgamma0(ensembleData[D,-K[kNA]], control = control, exchangeable = x) } else { fit <- fitBMAgamma0(ensembleData[D,], control = control, exchangeable = exchangeable) } # 把单日结果打包返回 res$kNA <- kNA res$fit <- fit res$trainTable <- length(unique(Dates[D])) res$nIter <- fit$nIter res$loglikelihood <- fit$loglikelihood return(res) } # 并行执行所有日期 all_res <- future_lapply(seq_along(juliandates), fit_single_date) # 主进程填充结果数组 for (res in all_res) { if (res$error) next i <- res$i kNA <- res$kNA fit <- res$fit prob0coefs[,K[!kNA],i] <- fit$prob0coefs biasCoefs[,K[!kNA],i] <- fit$biasCoefs varCoefs[,i] <- fit$varCoefs weights[K[!kNA],i] <- fit$weights trainTable[i] <- res$trainTable nIter[i] <- res$nIter loglikelihood[i] <- res$loglikelihood } # ---------------------- 并行逻辑结束 ---------------------- # 原函数末尾的structure返回逻辑保持不变 power <- if(length(all_res) > 0) all_res[[which(!sapply(all_res, \(x) x$error))[1]]]$fit$power else NULL structure(list(training = list(days=trainingDays,lag=lag,table=trainTable), prob0coefs = prob0coefs, biasCoefs = biasCoefs, varCoefs = varCoefs, weights = weights, nIter = nIter, exchangeable = exchangeable, power = power, call = match.call()), forecastHour = forecastHour, initializationTime = ensembleItime(ensembleData), class = c("ensembleBMAgamma0","ensembleBMA"))
内容的提问来源于stack exchange,提问作者ABHIJITH
相关产品推荐
相关产品推荐

