foreach 失败的并行网状调用

Parallelized reticulate call with foreach failing

您好,我正在尝试使用 foreach 以并行方式调用带有网状结构的 python 函数,如下所示:

library(reticulate)
library(doParallel)
library(foreach)
library(parallel)

py_install("wandb")
wandb <- import("wandb")


cl <- makeCluster(detectCores(), type = 'PSOCK')
registerDoParallel(cl)
foreach(i = 1:5) %dopar% {
    wandb$init(project = "test")
}

给出:

Error in {: task 1 failed - "attempt to apply non-function"
Traceback:

1. foreach(i = 1:5) %dopar% {
 .     wandb$init(project = "test")
 . }
2. e$fun(obj, substitute(ex), parent.frame(), e$data)

foreach 包是否不能与 reticulate 一起使用?

您不能将 reticulate python.builtin.module 对象从一个 R 进程导出到另一个。它们被设计为仅在它们创建的同一 R 进程中工作。如果尝试,您将收到报告的错误。

如果您使用 future 框架进行并行化,那么您可以让它检查这一点并立即给出信息性错误消息,例如

library(reticulate)
library(foreach)
library(doFuture)
registerDoFuture()
cl <- parallelly::makeClusterPSOCK(2L)
plan(cluster, workers = cl)

## Detect non-exportable objects and give an error asap
options(future.globals.onReference = "error")

# py_install("wandb")
wandb <- import("wandb")

res <- foreach(i = 1:5) %dopar% {
  wandb$init(project = "test")
  sqrt(i)
}

foreach() 的调用将导致:

Error: Detected a non-exportable reference ('externalptr') in one of
the globals ('wandb' of class 'python.builtin.module') used in the
future expression

您可以在 https://future.futureverse.org/articles/future-4-non-exportable-objects.html#package-reticulate 中阅读更多相关信息。

解决方法是在每次迭代中创建 wandb 对象,该对象在工作端运行。类似于:

res <- foreach(i = 1:5) %dopar% {
  wandb <- import("wandb")
  wandb$init(project = "test", mode = "offline")
  sqrt(i)
}

免责声明:我对 'wandb' Python 模块一无所知。可能以上说的不对。