【问题标题】:Why is mclappy slower than apply in this case?为什么在这种情况下 mclappy 比 apply 慢?
【发布时间】:2013-08-08 10:01:55
【问题描述】:

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

我正在通过函数 quantsm 调用的 rq.fit.fnb:quantreg 对 log2ratio 数据进行平滑处理,并且我将数据包装到矩阵/列表中以供 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 的数据向量,我得到:

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

           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

为什么 apply 比 mclapply 高效得多?也许我只是在犯一些常见的初学者错误。

感谢您的反应。

【问题讨论】:

  • 您的apply 呼叫不应该使用MARGIN = 2,而不是1吗?
  • 当然!谢谢你们(@flodel 和@SteveWeston)。我真的忽略了这一点。

标签: r parallel-processing apply smoothing mclapply


【解决方案1】:

看起来mclapplylapply 相比相当不错,但lapplyapply 相比并不好。原因可能是您使用apply 迭代q 的行,并且使用lapplymclapply 迭代q 的列。这可能是造成性能差异的原因。

如果您确实想要遍历 q 的行,您可以使用以下命令创建 ql

ql <- lapply(seq_len(nrow(x)), function(i) x[i,])

如果要遍历q 的列,则应按照@flodel 的建议在apply 中设置MARGIN=2

lapplymclapply 都将遍历数据框的列,因此您可以使用以下命令创建 ql

ql <- as.data.frame(q)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多