限制 foreach 和 doParallel 中的迭代

问题描述 投票:0回答:1

我正在尝试使用

foreach
doParallel
实现嵌套 for 循环,但我不想循环所有值的组合。基本上,我有一个方形数据集,我想对每对值运行一个函数,但我不需要重复 - 例如,我需要计算 [1,2] 的函数,而不是 [ 2,1],因为结果是相同的。这是一个非常基本的示例,但请注意,由于实际函数/计算的复杂性,我正在尝试使用 doParallel。

bvec <- seq(1,10,1)
avec <- seq(1,10,1)

x <- data.frame()
for (i in 1:10) {
  for (j in i:10) {
    x[i,j] <- sim(avec[i], bvec[j])
  }
}
x

原始数据集约为 1800 x 1800,如果我进行所有成对计算,将导致超过 320 万次计算,这是不必要的。这是我为

foreach
准备的:

cl <- parallel::makeCluster(detectCores()-4)
doParallel::registerDoParallel(cl)
clusterExport(cl, list("bvec","avec"))  
z <-
  foreach(i=1:10, .combine="cbind") %:%
    foreach(j=i:10) %dopar% {
      x[i,j] <- sim(avec[i], bvec[j])
    }
z
parallel::stopCluster(cl)

是否可以使用

foreach
来限制迭代?如果没有,还有其他方法可以优化这个过程吗?

我尝试将 foreach 语句更改为

foreach(i=1:10, .combine="cbind") %:%
    foreach(j=i:10) %dopar% {
      x[i,j] <- sim(avec[i], bvec[j])
    }

但这显然行不通。

r foreach doparallel
1个回答
0
投票

我在 1800x1800 数据上运行

microbenchmark
,并且您的嵌套
if()
三角形循环在
outer()
的计算次数上比
sum()
更快。

这是一种进行

foreach
嵌套的方法(从 https://cran.r-project.org/web/packages/foreach/vignettes/nested.html 的文档中提取)与
ifelse()
技巧相结合评估内循环并跳过半个三角形的重函数。

foreach(b=bvec, .combine='cbind') %:%
    foreach(a=avec, .combine='c') %dopar% {
      ifelse(a>=b, sum(a, b), NA)
    }

这个想法 (

j=i:10
) 适用于
%do%
,但不适用于
%dopar%
,这在此线程中进行了讨论 https://stackoverflow.com/a/45920140/10276092 并表示“[%dopar%] 确实不改变全局对象[x]”

x <- matrix(NA, nrow = 10, ncol = 10)
foreach(i=1:10, .combine="cbind") %:%
  foreach(j=i:10, .combine="c", .inorder=TRUE) %do% { # %do% works
    x[i,j] <- sum(avec[i], bvec[j])
  }
x

下面的方法可行,但是以一种奇怪的方式回收跳过的值。三角形形状不正确。来自 https://stackoverflow.com/a/48988950/10276092 的矩阵魔法使数据变得可呈现。

aa <- foreach(i=1:10, .combine="cbind") %:%
  foreach(j=i:10, .combine="c", .inorder=TRUE) %dopar% {
    sum(avec[i], bvec[j])
  }
aa[col(aa) + row(aa) > nrow(aa) + 1] <- 0 # drop the recycling
aa

       result.1 result.2 result.3 result.4 result.5 result.6 result.7 result.8 result.9 result.10
 [1,]        2        4        6        8       10       12       14       16       18        20
 [2,]        3        5        7        9       11       13       15       17       19         0
 [3,]        4        6        8       10       12       14       16       18        0         0
 [4,]        5        7        9       11       13       15       17        0        0         0
 [5,]        6        8       10       12       14       16        0        0        0         0
 [6,]        7        9       11       13       15        0        0        0        0         0
 [7,]        8       10       12       14        0        0        0        0        0         0
 [8,]        9       11       13        0        0        0        0        0        0         0
 [9,]       10       12        0        0        0        0        0        0        0         0
[10,]       11        0        0        0        0        0        0        0        0         0
© www.soinside.com 2019 - 2024. All rights reserved.