R语言并行计算提高速度丨parallel包和foreach包

news2024/12/24 9:10:40

并行计算提高R语言速度

今天与大家分享的是R语言中的并行计算的内容,将探讨如何使用parallel和foreach包在R中进行并行计算,以及在不同情况下提高计算效率的方法。

alt

目标:让计算等待时间缩短!


1. 什么是并行计算?

并行计算是计算机科学中的一个概念,它涉及到同时执行多个计算任务以加速整体的处理速度,这是通过在多个处理器或多个计算节点上同时执行代码来实现的。

alt

2. 为什么需要并行计算?

随着数据规模的增长,我们需要更快地处理数据。单线程的程序只能在一个CPU核心上运行,而并行计算可以同时利用多个核心,从而大大提高计算速度。

alt

3. CPU多线程基础

多线程是一种允许单个程序或应用执行多个任务(线程)的技术。每个线程都运行在其自己的CPU核心上,这使得多线程程序可以更高效地使用多核CPU。

4. R语言中的并行计算

R语言提供了多种并行计算的方法,其中最常用的是parallel和foreach包。

alt

4.1 parallel包

使用parallel包的mclapply函数,可以轻松地实现并行计算。

library(parallel)

定义一个简单的函数来模拟计算任务

f <- function(x) {
  Sys.sleep(1)  # 模拟耗时1秒的任务
  return(x^2)
}
使用mclapply函数并行处理数据
result <- mclapply(1:4, f, mc.cores = 2)
print(result)

4.2 foreach包

alt

foreach包提供了一个更加灵活的并行框架。与传统的for循环相比,它的语法更加简洁。

library(foreach)
library(doParallel)
注册并行后端
cl <- makeCluster(2)
registerDoParallel(cl)
使用foreach函数并行处理数据
result <- foreach(i=1:4) %dopar% {
  Sys.sleep(1)  # 模拟耗时1秒的任务
  return(i^2)
}
print(result)
停止并行后端
stopCluster(cl)

5. 性能比较

为了对比普通for循环、mclapply和foreach的性能,我们将使用上面定义的函数f模拟计算任务。

  • 普通for循环
start.time <- Sys.time()
result <- vector("list", 4)
for(i in 1:4) {
  result[[i]] <- f(i)
}
end.time <- Sys.time()
cat("For loop time:", end.time - start.time, "\n")
alt
  • 使用mclapply
start.time <- Sys.time()
result <- mclapply(1:4, f, mc.cores = 2)
end.time <- Sys.time()
cat("mclapply time:", end.time - start.time, "\n")
alt
  • 使用foreach
cl <- makeCluster(2)
registerDoParallel(cl)
start.time <- Sys.time()
result <- foreach(i=1:4) %dopar% f(i)
end.time <- Sys.time()
cat("foreach time:", end.time - start.time, "\n")
stopCluster(cl)
alt

从上述代码的输出中,我们可以看到mclapply和foreach的执行时间都明显短于传统的for循环。(此处演示设置的线程数是2,实际上一般生信计算服务器可以达到一百多个线程,计算速度还可以明显提高)

如何使用并行计算模式?

在R中尽量避免使用for循环,在R中使用for循环速度很慢,在写代码的时候,应该尽可能的避免使用for循环。

查看电脑的可用线程数量

detectCores(logical = F)#查看电脑的物理核数
install.packages("future")
library(future)
availableCores()#查看电脑可用的线程数

foreach初级用法

使用foreach()+%do%代替for循环,计算速度和for循环差不多。但函数foreach返回了一个列表(list)。使用foreach的优势在于%do%后的花括号{}之间可以像for循环那样写多条语句。

x1 <- list()
foreach(i = 1:30000) %do% {
  x1[[i]] <- mean(rnorm(1e5))
}
# 上述代码等同于以下for结构
for (i in 1:30000){
  x1[i] <- mean(rnorm(1e5))
}

foreach高级用法

使用foreach进行并行计算,需要将上面的%do%替换为%dopar%来启动并行计算,在使用并行计算之前,首先需要加载doParallel包,创建一个集群并注册。

library(foreach)
library(doParallel)
# 创建一个集群并注册
cl <- makeCluster(128) # 128是设置的线程数
registerDoParallel(cl)
 
# 启动并行计算
x2 <- foreach(i = 1:3e4, .combine = c) %dopar% {
  mean(rnorm(1e5))
}

# 在计算结束后别忘记关闭集群
stopImplicitCluster()
stopCluster(cl)

特别注意:foreach默认的返回值数据类型为list,可以使用".combine"参数来指定输出数据的类型为向量。

foreach函数中也可以使用rbind或者cbind等函数以矩阵形式输出结果。

下面是一个原始的for循环代码,对一个矩阵进行循环计算,运行耗时大约6分钟。

x <- matrix(0,nrow=3e4,ncol=6)
for (i in 1:30000) {
  x[i,] <- summary(rnorm(1e5))
}

对其进行重构优化,采用dopar的方式并行计算,将返回的结果按行合并(rbind),计算实际耗时1分钟。

# 创建一个集群并注册
cl <- makeCluster(36)
registerDoParallel(cl)
# 启动并行计算
x <- foreach(i = 1:3e4, .combine = rbind) %dopar% {
  summary(rnorm(1e5))
}
# 结束任务
stopImplicitCluster()
stopCluster(cl)

foreach函数使用技巧

cl <- makeCluster(20)
registerDoParallel(cl)
out <- foreach(i = 1:100,
               .combine = rbind,
               .packages = "tidyverse",
               .errorhandling = "pass") %dopar% {
                 a <- i
                 b <- mean(rnorm(10000))
                 c <- str_c(a,"-",b)
                 d <- c(a,b,c)
                 if (i == 2){
                   stop("no")
                 }
                 return(d)
               }
stopCluster(cl)

.package

写在%dopar%后的代码经常会用到第三方R包,这些包必须在.package中指定,也就是说一旦函数主体内出现了引用其他包的函数,就要在此指定。比如上面的tidyverse包中“str_c”函数。

.errorhandling

处理循环中出现错误时的应对方法,默认为stop,即出现错误就停止,但是这样会导致已经计算的内容全部失效,还得重新算。另外还有两种方式,remove选项可以在遇到错误时自动移除错误项,pass可以在出现错误时跳过该项,后者的区别是会记录出现错误的位置。

alt

变量作用域

函数内部的局部变量具有自身的作用域,在离开运行环境时将会失效,因此在并行计算过程中也要考虑到该问题。

一个R语言函数有自己的运行环境,通常顶层环境就是全局变量,在任意位置都可以调用,而函数内部变量无法在顶层环境使用。

如果在dopar结构在函数中,则不会主动加载全局环境中的变量。

x1 <- 1
x2 <- 2
f <- function(x1) {
  foreach(i = 1:100, .combine = c)  %dopar% {
    x1 + x2 + i
  }
}

比如,上面这个会报错x2无法找到,因为foreach只识别了f函数环境的变量,而不会识别全局环境的变量。修改方法是将x2作为f函数的参数,或者.export参数。

# 方法一
f <- function(x1, x2) {
  foreach(i = 1:3, .combine = c)  %dopar% {
    x1 + x2 + i
  }
}
# 方法二
f <- function(x1) {
  foreach(i = 1:3, .combine = c, .export = 'x2')  %dopar% {
    x1 + x2 + i
  }
}

如何提前下班?

数据分析除了写代码,还离不开复杂的计算过程,有时候一个步骤的执行耗时好久,不得不加班!那么如何才能加速计算时间,每天早点下班呢?

CPU和内存的权衡

R语言并行计算的内存消耗量很大,因为R语言计算时都需要将数据全部加载到内存中进行操作。

alt

适当的选择核心数量和内存大小,防治任务意外卡死。主要的解决方法是提高配置(钞能力)或者将一个大任务切分成若干小任务。

超线程不要太压榨

现在的处理器基本都实现了超线程的功能,在运行并行任务时不要一次性设置全部线程,不然速度不增反降。

alt

对于支持超线程的CPU,并行计算时建议选择物理核心数量的1.5倍为上限,可以用detectCores(logical = F)命令查看自己电脑的物理核心数量

结论

并行计算为我们提供了一种有效地利用多核CPU的方法,从而加速数据处理速度。在R中,我们可以使用parallel和foreach包轻松实现并行计算,当处理大量数据时,建议尝试并行计算以提高效率。

最后,希望这篇文章能帮助大家更好地理解R语言中的并行计算技术。如果有任何建议,请后台留言或私信,感谢大家的阅读,欢迎分享和点赞!

参考资料

https://blog.csdn.net/u011375991/article/details/131272023
alt

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1004621.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

认识网线上的各种参数标号

最近工作需要&#xff0c;接触了很多不同类型的网线&#xff0c;为了能够区分不同型号的网线&#xff0c;特意做一篇笔记用来学习&#xff0c;如有记录有误之处&#xff0c;欢迎大家指正~初步认识网线 常用的网络电缆有三种&#xff1a;双绞线、同轴电缆和光纤电缆&#xff08…

Vue3、Vite使用 html2canvas 把Html生成canvas转成图片并保存,以及填坑记录

这两天接到新需求就是生成海报分享&#xff0c;生成的格式虽然是一样的但是自己一点点画显然是不符合我摸鱼人的性格&#xff0c;就找到了html2canvas插件&#xff0c;开始动工。 安装 npm install html2canvas --save文档 options 的参数都在里面按照自己需求使用 https://a…

Python3.10 IDLE更换主题

前言 自定义主题网上有很多&#xff0c;3.10IDLE的UI有一些新的东西&#xff0c;直接扣过来会有些地方覆盖不到&#xff0c;需要自己测试着添几行配置&#xff0c;以下做个记录。 配置文件路径 Python安装目录下的Lib\idlelib\config-highlight.def。如果是默认安装&#xf…

2023年7月京东平板电脑行业品牌销售排行榜(京东销售数据分析)

鲸参谋监测的京东平台7月份平板电脑市场销售数据已出炉&#xff01; 根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;今年7月份&#xff0c;京东平台上平板电脑的销量为68万&#xff0c;同比增长超过37%&#xff1b;销售额为22亿&#xff0c;同比增长约54%。从价格上看…

win11本地连接没了怎么办

很多用户在使用win11系统时发现自己的网络连接没有了&#xff0c;遇到这种情况的话&#xff0c;我们应该怎么处理呢&#xff1f;我们可以尝试打开网络图标&#xff0c;下面就是小编整理出的教程&#xff0c;大家一起看看吧。 win11本地连接没了怎么办 方法一&#xff1a; 1、…

Python基于Flask的招聘信息爬取,招聘岗位分析、招聘可视化系统

Python基于Flask招聘信息可视化系统 一、介绍 今天为大家带来的是Python基于Flask的招聘信息爬取&#xff0c;招聘岗位分析、招聘可视化系统。视频演示地址&#xff1a;https://www.bilibili.com/video/BV1Tp4y1A7nW/ Python基于flask的招聘数据可视化&#xff0c;招聘岗位分…

Cpp/Qtday050912cpp基础

目录 实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#x…

YoloV8改进策略:Diverse Branch Block改进YoloV8,继续在重参数结构上恐龙抗狼

摘要 DBB(Diverse Branch Block)是一种类似Inception的多分支结构,用于网络结构重参数化。它通过多分支结构类型更丰富(多尺度卷积、平均池化等),感受野更多样性,各操作具有不同的计算复杂度,因此更具有通用性,可以用来替换单个卷积进行训练。在训练阶段,对模型中的…

软件自动化测试有哪些步骤?自动化测试需要找第三方检测机构吗?

您是否曾经因为软件出现问题而影响了工作进程或者个人生活的正常运转?那么&#xff0c;您是否了解软件自动化测试这一神奇的技术?在这篇文章中&#xff0c;我们将为您介绍软件自动化测试的定义和测试步骤&#xff0c;帮助您更好地了解自动化测试。 一、什么是软件自动化测试…

Qt自定义QSlider(支持水平垂直)

实现背景&#xff1a; Qt本身有自己的QSlider&#xff0c;为什么我们还要自定义实现呢&#xff0c;因为Qt自带的QSlider存在一个问题&#xff0c;当首尾为圆角时&#xff0c;滑动滚动条到首尾时会出现圆角变成矩形的问题。当然如果QSS之间的margin和滑动条的圆角控制的好的话是…

ModStartBlog v8.2.0 独立友情链接页面,博客列表样式优化

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议。 功能特性 丰富的模块市场&#xff0c;后台一键快速安装 …

【系统设计系列】异步和网络通信

系统设计系列初衷 System Design Primer&#xff1a; 英文文档 GitHub - donnemartin/system-design-primer: Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards. 中文版&#xff1a; https://github.com/donnemarti…

【DevOps核心理念基础】2. 敏捷开发与DevOps关系

一、什么是敏捷开发 ? 1.1 敏捷开发的核心模型 二、敏捷开发的要点 2.1 敏捷开发 > 执行细节 2.2 敏捷开发 > 思路的转变 客户需求&#xff1a;提升出行速度 三、敏捷开发 与 DevOps 四、DevOps 实践的度量标准 4.1 怎样判断DevOps实践好与坏? 一、什么是敏捷…

欧科云链研究院:锚定金融市场,香港从STO再出发

作者&#xff5c;Hedy Bi 昨日&#xff0c;据大公报报道&#xff0c;太极资本宣布推出香港首个面向「专业投资者」的房地产基金证券型代币发行&#xff08;STO&#xff09;。集资目标为1亿元。“牌照&#xff0c;醉翁之意不在酒。BTC、ETH等加密资产只是第一步&#xff0c;而背…

Ubuntu搭配POE交换机激活海康威视网络摄像头

前言 一般使用网络摄像头基本有两种方案&#xff1a; 用电源线和网线连接路由器&#xff08;交换机&#xff09;与网络摄像头用两根网线连接路由器交换机网络摄像头&#xff08;前提&#xff1a;交换机和网络摄像头都支持POE协议通电&#xff09; 踩坑日志 由于第一次使用网…

MySQL与ES数据同步之同步调用

这是第一种方法&#xff0c;也是最简单的方法&#xff0c;在对mysql进行增删改查时&#xff0c;操作后直接调用ES方法实现增删改查。 可以看出这种方式业务逻辑简单&#xff0c;实时性高&#xff0c;但是会有业务强耦合&#xff0c;存在双写失败丢数据风险&#xff0c;性能也比…

趣解设计模式之《为什么租房子要找中介?》

〇、小故事 小王大学毕业了&#xff0c;打算来北京闯荡一下&#xff0c;于是就先寄宿到了他的表姐家&#xff0c;白天的时候&#xff0c;自己在外面小区转一转&#xff0c;看看能不能找到可以租到的房子&#xff0c;他找了好几天都没有找到合适的&#xff0c;要么就是小区里一…

每天40min,我们一起用70天稳扎稳打学完《JavaEE初阶》——33/70 第三十三天【JavaScript(webapi)】

JavaScript WebAPI WebAPI 背景知识DOM 基本概念获取元素事件初识操作元素输入密码的 显示 和隐藏点击计数器勾选复选框获取/修改 样式 属性开关灯WebAPI 背景知识 DOM 基本概念 获取元素 事件初识

JUC简介与环境搭建

1.新建一个Maven项目 2.导入依赖 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.26</version></dependency> 3.检查Java版本 4.什么是JUC JUC&#xff08;java.util.co…

vue-tabel 中使用 el-autocomplete 出现的问题

必须加 :popper-append-to-body"false" :popper-class"vxetableignoreclear" 我自己用的话缺一不可 说一下我自己项目中遇到的问题吧&#xff0c;我写的是表格中套表格&#xff0c;会出现就是当下拉选的时候用selete是可以用的&#xff0c;但是用blur也…