最近,我在工作区中创建了一个对象factor=1,却不知道factor包中有一个函数base

我打算做的是在并行循环中使用factor变量,例如,

library(plyr)
library(foreach)
library(doParallel)

workers <- makeCluster(2)
registerDoParallel(workers,cores=2)

factor=1

llply(
  as.list(1:2),
  function(x) factor*x,
  .parallel = TRUE,
  .paropts=list(.export=c("factor"))
     )

但是,这导致了一个错误,使我花了很多时间来理解。看起来,plyr在其环境factor中创建了对象exportEnv,但是使用了base::factor而不是用户提供的对象。请参阅以下示例
llply(
  as.list(1:2),
  function(x) {
    function_env=environment();
    global_env=parent.env(function_env);
    export_env=parent.env(global_env);
    list(
      function_env=function_env,
      global_env=global_env,
      export_env=export_env,
      objects_in_exportenv=unlist(ls(envir=export_env)),
      factor_found_in_envs=find("factor"),
      factor_in_exportenv=get("factor",envir=export_env)
      )
    },
  .parallel = TRUE,
  .paropts=list(.export=c("factor"))
  )

stopCluster(workers)

如果我们检查llply的输出,我们会看到factor_in_exportenv=get("factor",envir=export_env)行不返回1(对应于用户提供的对象),而是返回base::factor的函数定义。

问题1)我如何理解这种行为?我本来希望输出是1

问题2)如果我给另一个包中已定义的对象(例如R)分配了新值,是否有办法从factor得到警告?

最佳答案

llply函数在后台调用“foreach”。 Foreach使用“parant.frame()”来确定要评估的环境。在llply的情况下,parant.frame是什么?这是llply的功能环境,没有定义因素。

与其直接使用llply,为什么不直接使用foreach?

library(plyr)
library(foreach)
library(doParallel)

workers <- makeCluster(2)
registerDoParallel(workers,cores=2)

factor=1
foreach(x=1:2) %dopar% {factor*x}

请注意,您甚至不需要.export参数,因为在这种情况下它会自动这样做。

关于r - 并行plyr中的奇怪环境行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17840167/

10-12 17:39