#python #r #foreach #parallel-processing #reticulate
Вопрос:
Привет, я пытаюсь вызвать функцию python с помощью reticulate параллельным образом, используя foreach
примерно так:
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?
Комментарии:
1. Что это за объект
wandb
? Я думаюwandb$init(project = "test")
, что это не работает, поскольку это каким-то образом смешивает оператор на основе данных$
с функцией( ... )
. Возможно, вы хотели что-то вродеwandb$init[project == "test"]
(что, скорее всего, тоже не сработает… возможноwandb$init[wandb$project == "test"]
).2. wandb — это библиотека python, импортированная через reticulate.
3. Использует ли он этот специальный синтаксис? Потому
R
что я ожидал бы некоторых незначительных синтаксических изменений.4. Это никак не сработает,
reticulate
не поддерживает многопоточность, потому что весь сеанс python встроен в родительский сеанс R. Если вы хотите сделать это параллельно, импортируйте функцию из каждого дочернего процесса R.
Ответ №1:
Вы не можете экспортировать сетчатые python.builtin.module
объекты из одного процесса R в другой. Они предназначены для работы только в рамках того же процесса R, который они создали. Если вы попытаетесь, то получите сообщение об ошибке, о котором сообщаете.
Если вы используете future framework для своего распараллеливания, вы можете проверить это и немедленно выдать информативное сообщение об ошибке, например
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)
}
Отказ от ответственности: Я ничего не знаю о модуле Python ‘wandb’. Возможно, вышесказанное не имеет смысла.
Комментарии:
1. спасибо @HenrikB за объяснение и обходной путь.