【问题标题】:mclapply vs for loops for plotting: speed and scalability focus用于绘图的 mclapply 与 for 循环:速度和可扩展性焦点
【发布时间】:2012-09-29 05:19:38
【问题描述】:

我正在 R 中运行一个函数,该函数可能需要很长时间才能运行,因为它执行多个命令来转换和子集一些数据,然后将其推送到 ggplot 进行绘图。我需要多次运行此函数来调整参数值。我将提供的示例很简单……但想知道如何加快速度?如果按比例放大,即获得每个组合的最快方法是什么...是否有将for 循环转换为mclapply 的通用方法,假设它们更快...请随时提供替代模拟示例来演示对特定方法的偏好

模拟示例:

基本功能:

ff <- function(n, mu, stdev){
     x1 <- c(1:n)
     y1 <- rnorm(n,mu,stdev)
     z1 <- data.frame(cbind(x1,y1))
     ggplot(z1, aes(x=x1,y=y1))+
       geom_point()+
       labs(title=paste("n=",n,"mu=",mu, "stdev=",stdev))
}

所以通过参数的方法是执行以下操作......

for(i in 1:10){
    for(j in 1:2){
       for(k in seq(100,500,by=100)){
         ff(k,i,j)
       }
    }
}

加快速度的最快方法是什么?我假设它可能需要expand.grid(x=c(1:10),y=c(1:2),z=seq(100,500,by=100)) 和使用mclapply 之类的东西来遍历每一行......以某种并行方式? (我有 4 个内核可用于此)。请根据可以最大程度提高速度的方法,随意从基本功能中提取一些内容或将内容放入基本功能中。如果您增加每个参数的范围,该过程显然会花费更长的时间,但是对此没有什么可以做的......或者如果分成更多的核心或其他东西,也可以以某种方式改变......?

对于奖励积分...是否有任何东西可以保存输出图像并创建像 manipulate 包中一样的滑块以交互方式遍历所有参数...其中所做的就是拉取出相关图像,而不是每次都重新计算。

注意请随意使用/建议您认为可能对您的解决方案有用的任何其他软件包(如 foreach

【问题讨论】:

    标签: r for-loop foreach ggplot2 mclapply


    【解决方案1】:

    保存输出图像非常容易。只需在 ff() 函数中调用 ggsave()

    ff <- function(n, mu, stdev){
      x1 <- c(1:n)
      y1 <- rnorm(n,mu,stdev)
      z1 <- data.frame(cbind(x1,y1))
      ggplot(z1, aes(x=x1,y=y1))+
        geom_point()+
        labs(title=paste("n=",n,"mu=",mu, "stdev=",stdev))
      ggsave(paste0(n,"_", mu, "_", stdev, ".jpeg"))
    }
    

    您对使用expand.grid() 的建议表示赞同。这是我要做的:

    x <- expand.grid(i = 1:10, j = 1:2, k = seq(100,500,100))
    

    然后调用它,如果您在 Linux 上并且有多个可用内核,我会使用 lapply()mclapply()

    lapply(seq(nrow(x)), function(i) ff(x[i,2], x[i,1], x[i,3]))
    

    这将创建 100 个具有“n_mu_stdev.jpeg”命名约定的 jpeg。至于访问这些并在屏幕上呈现它们的有效方法,我会研究一个 Web 浏览器和一些简单的 CSS 和 jQuery 来使其变得简单。尽管恕我直言,这确实是一个单独的问题。

    【讨论】:

    • 感谢您的快速响应...所以...我在使用 mclapply 位时遇到了困难...但也只是使用 lapply 并没有真正提供太多的速度改进.. .这是我的基准测试案例system.time(for(i in 1:10){for(j in 1:2){for(k in seq(100,500,by=100)){print(ff(k,i,j))}}}) 耗时21.4 秒,使用lapply 我做了以下system.time(lapply(seq(nrow(x)), function(i) print(ff(x[i,3], x[i,1], x[i,2])))) 耗时21.7 秒...将lapply 替换为mclapply 与mc.cores=4 创建了此错误: ATSFontGetFileReference failed: error -3182.
    • @h.l.m - 我不希望 lapply 比你的 for 循环快得多。我还敢打赌,您的大部分时间都花在了ggplot2 位上,而多核无法加速。尝试修改一些基本图形以使其不那么难看,您几乎可以肯定地将计算时间缩短很多倍。我以前从未见过这个错误,所以很遗憾在那里没有太多帮助。你能从?mclapply 那里得到一个简单的例子来工作吗?
    • 使用 mclapply 帮助页面上的代码,以下代码可以正常工作mclapply(1:30, rnorm, mc.cores=4)
    • @Chase 你是对的,ggplot 本身不会跨内核拆分,但每个作业都会,因此根据传输和计算时间之间的权衡,它可能会更快,因为每个内核处理 1 /该列表的第 4 位(因为他有 4 个核心)。
    • 但是对于这个简单的例子,llply 足以在单核上运行。
    【解决方案2】:

    如果使用mclapply,请将参数组合成一个列表并将其传递给函数,而不是使用 for 循环。

    例如

    df <- expand.grid(i = 1:10, j = 1:2 , k = seq(100, 500, 100))
    params <- mapply(list, n = df[, 3], mu = df[, 1], stdev = df[,2], SIMPLIFY = F)
    
    ff <- function(tlist) {
        n <- tlist$n 
        mu <- tlist$mu 
        stdev <- tlist$stdev
         x1 <- c(1:n)
         y1 <- rnorm(n,mu,stdev)
         z1 <- data.frame(cbind(x1,y1))
         ggplot(z1, aes(x=x1,y=y1))+
           geom_point()+
           labs(title=paste("n=",n,"mu=",mu, "stdev=",stdev))
    }
    
    results <- llply(params, ff, .progress='text')
    

    如果使用mclapply

    results <- mclapply(params, ff, mc.cores = 4, mc.preschedule = TRUE)
    

    【讨论】:

    • 感谢您的回复,但我似乎不断收到错误提示 "Error in 1:n : NA/NaN argument\n" 并且无法解决如何解决它...
    • 要排除mclapply 的问题,首先使用llply(删除mc.coresmc.preschedule),看看是否出现相同的错误。如果是这样,则该函数未正确读取每个列表项。请参阅params[1] 以确保所有 3 个都在其中。
    • 这是我的参数 [1] 的样子&gt; params[1] [[1]] [[1]]$i [1] 1 [[1]]$j [1] 1 [[1]]$k [1] 100 所以我不太确定要调整什么,因为我将最后一行更改为 llply(params, ff) 并得到相同的错误...跨度>
    • 所以解决方案现在似乎可以工作......但只有在两种情况下都输入results,这似乎需要大致相同的时间,是预处理的区别事先的数据?此外,如果尝试将其放入 system.time() 函数中以检查哪个更快,结果不打印,因此使用 h llply 中的.parallel 参数吗?
    • 你为什么要输入results?它只会将所有 300 个打印到屏幕上。相反,在results 对象上运行llply 并将其推送到ggsave,这样您就可以得到一个图像文件夹,然后您可以通过幻灯片放映。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 1970-01-01
    • 1970-01-01
    • 2014-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多