【问题标题】:transform a multiple normal loop into a parallel loop with foreach使用 foreach 将多个正常循环转换为并行循环
【发布时间】:2013-03-07 02:57:39
【问题描述】:

如何通过 foreach 包将普通循环转换为并行循环?

我尝试从 vrtest 包中转换此代码

CvMexpb <- matrix(0,nrow=B,ncol=2)

           for(k in 1:B)
           {
            eb <- e * Mammen2(n)
            eb <- eb - mean(eb)
            tem <- 0

           for( j in 1:(n-1) ) 
           { 
           aux2 <- 1/((j*pi)*(j*pi))
           aux2 <- aux2/(n-j+1)
           tem <- tem+aux2* t(eb[(1+j):n]) %*% weiexp[1:(n-j),1:(n-j)] %*% eb[(1+j):n]
           }

           CvMexpb[k,] <- cbind(tem/v > CvMexp,tem/v)
           }    

        pboot <- mean(CvMexpb[,1])
        Critboot <- quantile(CvMexpb[,2],c(0.9,0.95,0.99))
        return(pboot)

进入

CvMexpb <- foreach(k = 1:B, .combine='cbind') %:%
           {
            eb <- e * Mammen2(n)
            eb <- eb - mean(eb)
            tem <- 0

           foreach(j = 1:(n-1), .combine='c') %dopar%
           { 
           aux2 <- 1/((j*pi)*(j*pi))
           aux2 <- aux2/(n-j+1)
           tem <- tem+aux2* t(eb[(1+j):n]) %*% weiexp[1:(n-j),1:(n-j)] %*% eb[(1+j):n]
           }

           CvMexpb[k,] <- cbind(tem/v > CvMexp,tem/v)
           }    

        pboot <- mean(CvMexpb[,1])
        Critboot <- quantile(CvMexpb[,2],c(0.9,0.95,0.99))
        return(pboot)

但返回错误

foreach 中的错误(k = 1:B, .combine = "cbind") %:% { : "%:%" 传递了一个非法的右操作数

原始完整代码是

compweexp <- 
function(inf) 
{
n <- length(inf)
weiexp <- matrix(1,nrow=n,ncol=n)
for(i in 1:n)
{
    for(j in (i+1):n)
    {
    if(j > n) break
    aux1 <- (inf[i]-inf[j]) %*% t(inf[i]-inf[j])
    weiexp[i,j] <- exp(-0.5*aux1)
    weiexp[j,i] <- weiexp[i,j]
    }
}
return(weiexp)
}

Mammen <-
function(n)
{
p <- (sqrt(5)+1)/(2*sqrt(5))
zmat <- rep(1,n)*(-(sqrt(5)-1)/2);
u <- runif(n,0,1)
zmat[u > p] <- (sqrt(5)+1)/2
return(zmat)
}


Gen.Spec <- 
function(y,B=300)
{
set.seed(12345)
n<- length(y)
e <- y - mean(y)
v <- var(e)
y1 <- y[1:(n-1)]
weiexp <- compweexp(y1)
CvMexp <- 0

for(j in 1:(n-1)) {
   aux2 <- 1/((j*pi)^2)
   aux2 <- aux2/(n-j+1)
   CvMexp <- CvMexp+ aux2* t(e[(1+j):n]) %*% weiexp[1:(n-j),1:(n-j)] %*% e[(1+j):n]
}
CvMexp <- CvMexp/v

CvMexpb <- matrix(0,nrow=B,ncol=2)
for(k in 1:B)
{
    eb <- e * Mammen(n)
    eb <- eb - mean(eb)
    tem <- 0
    for( j in 1:(n-1) ){
    aux2 <- 1/((j*pi)^2)
    aux2 <- aux2/(n-j+1)
    tem <- tem+aux2* t(eb[(1+j):n]) %*% weiexp[1:(n-j),1:(n-j)] %*% eb[(1+j):n]
    }
    CvMexpb[k,] <- cbind(tem/v > CvMexp,tem/v)

}    

pboot <- mean(CvMexpb[,1])
Critboot <- quantile(CvMexpb[,2],c(0.9,0.95,0.99))
return(pboot)
}

【问题讨论】:

  • 我不确定是什么导致了错误,但我建议将 CvMexpb[k,] CvMexp,tem/v) 更改为 cbind(tem/v > CvMexp ,tem/v);该路径要么是多余的,要么会主动破坏您的代码

标签: r foreach parallel-processing


【解决方案1】:

您收到一条错误消息,因为 '%:%' 运算符的正确参数必须是另一个 foreach 表达式。没有标准的方法来包含内部 foreach 循环的初始化代码。 doMPI 包确实提供了这种机制。

但另一个问题是您的内部 for 循环不能以这种方式并行化,因为您正在根据循环的上一次迭代中计算的值设置“tem”变量。你可以通过只对外部循环使用 foreach 来解决这两个问题:

CvMexpb <- foreach(k=1:B, .combine='rbind', .export='Mammen2') %dopar% {
  eb <- e * Mammen2(n)
  eb <- eb - mean(eb)
  tem <- 0
  for( j in 1:(n-1) )
  {
    aux2 <- 1/((j*pi)*(j*pi))
    aux2 <- aux2/(n-j+1)
    tem <- tem+aux2* t(eb[(1+j):n]) %*% weiexp[1:(n-j),1:(n-j)] %*% eb[(1+j):n]
  }
  cbind(tem/v > CvMexp,tem/v)
}

这将减少需要更长计算时间的任务,这可能不是一件好事。

【讨论】:

  • 谢谢史蒂夫韦斯顿和@RyanGrannell,我会试试这个!
  • 我对代码进行了建议的更改,但没有发生错误。然而,最终的结果是错误的!我添加了有问题的完整代码以方便理解。
  • 这可能是因为我在应该使用“rbind”时错误地使用了.combine="cbind"。对此感到抱歉。
猜你喜欢
  • 2016-01-26
  • 2021-03-12
  • 2014-12-11
  • 2012-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多