为什么mclappy在这种情况下比应用慢?

时间:2013-08-08 10:01:55

标签: r parallel-processing apply smoothing mclapply

我很困惑。我想通过使用 mclapply:parallel 来加速我的算法,但是当我比较时间效率时,应用仍然会获胜。

我正在通过 rq.fit.fnb:quantreg 平滑log2ratio数据,这是由我的函数quantsm调用的,我将我的数据包装到矩阵/列表中 apply / lapply( mclapply)用法。

我赞成这样的数据:

q = matrix(data, ncol=N)        # wrapping into matrix (using N = 2, 4, 6 or 8)
ql = as.list(as.data.frame(q))  # making list

时间比较:

apply=system.time(apply(q, 1, FUN=quantsm, 0.50, 2))
lapply=system.time(lapply(ql, FUN=quantsm, 0.50, 2))
mc2lapply=system.time(mclapply(ql, FUN=quantsm, 0.50, 2, mc.cores=2))
mc4lapply=system.time(mclapply(ql, FUN=quantsm, 0.50, 2, mc.cores=4))
mc6lapply=system.time(mclapply(ql, FUN=quantsm, 0.50, 2, mc.cores=6))
mc8lapply=system.time(mclapply(ql, FUN=quantsm, 0.50, 2, mc.cores=8))
timing=rbind(apply,lapply,mc2lapply,mc4lapply,mc6lapply,mc8lapply)

功能 quantsm

quantsm <- function (y, p = 0.5, lambda) {
   # Quantile smoothing
   # Input: response y, quantile level p (0<p<1), smoothing parmeter lambda
   # Result: quantile curve

   # Augment the data for the difference penalty
   m <- length(y)
   E <- diag(m);
   Dmat <- diff(E);
   X <- rbind(E, lambda * Dmat)
   u <- c(y, rep(0, m - 1))

   # Call quantile regression
   q <- rq.fit.fnb(X, u, tau = p)
   q
}

功能 rq.fit.fnb (quantreg库):

rq.fit.fnb <- function (x, y, tau = 0.5, beta = 0.99995, eps = 1e-06) 
{
    n <- length(y)
    p <- ncol(x)
    if (n != nrow(x)) 
        stop("x and y don't match n")
    if (tau < eps || tau > 1 - eps) 
        stop("No parametric Frisch-Newton method.  Set tau in (0,1)")
    rhs <- (1 - tau) * apply(x, 2, sum)
    d <- rep(1, n)
    u <- rep(1, n)
    wn <- rep(0, 10 * n)
    wn[1:n] <- (1 - tau)
    z <- .Fortran("rqfnb", as.integer(n), as.integer(p), a = as.double(t(as.matrix(x))), 
        c = as.double(-y), rhs = as.double(rhs), d = as.double(d), 
        as.double(u), beta = as.double(beta), eps = as.double(eps), 
        wn = as.double(wn), wp = double((p + 3) * p), it.count = integer(3), 
        info = integer(1), PACKAGE = "quantreg")
    coefficients <- -z$wp[1:p]
    names(coefficients) <- dimnames(x)[[2]]
    residuals <- y - x %*% coefficients
    list(coefficients = coefficients, tau = tau, residuals = residuals)
}

对于长度为2000的数据向量,我得到:

(value =以秒为单位的经过时间;列=平滑矩阵/列表的不同列数)

           2cols 4cols 6cols 8cols
apply      0.178 0.096 0.069 0.056
lapply    16.555 4.299 1.785 0.972
mc2lapply 11.192 2.089 0.927 0.545
mc4lapply 10.649 1.326 0.694 0.396
mc6lapply 11.271 1.384 0.528 0.320
mc8lapply 10.133 1.390 0.560 0.260

对于长度为4000的数据,我得到:

            2cols  4cols  6cols 8cols
apply       0.351  0.187  0.137 0.110
lapply    189.339 32.654 14.544 8.674
mc2lapply 186.047 20.791  7.261 4.231
mc4lapply 185.382 30.286  5.767 2.397
mc6lapply 184.048 30.170  8.059 2.865
mc8lapply 182.611 37.617  7.408 2.842

为什么申请比mclapply更有效?也许我只是做了一些常见的初学者错误。

感谢您的反应。

1 个答案:

答案 0 :(得分:2)

看起来mclapplylapply的效果相当,但lapplyapply的效果不佳。原因可能是您使用qapply行进行了迭代,并且您使用q和{{1}对lapply列进行了迭代}。这可能是性能差异的原因。

如果您确实希望迭代mclapply行,可以使用以下方式创建q

ql

如果您要迭代ql <- lapply(seq_len(nrow(x)), function(i) x[i,]) 的列,则应按照@flodel的建议在q中设置MARGIN=2

applylapply都将遍历数据框的列,因此您可以使用以下内容创建mclapply

ql

这是有道理的,因为数据框实际上是一个列表。