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

并行计算提高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.rhkb.cn/news/131015.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Linkerd 2.0:下一代服务网格的探索》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

数据结构——排序算法——插入排序

交换法插入排序 void swap(vector<int> arr, int i, int j) {int temp arr[i];arr[i] arr[j];arr[j] temp;}void insertSort(vector<int> arr) {// 从第二个数开始&#xff0c;往前插入数字for (int i 1; i < arr.size(); i) {// j 记录当前数字下标int j …

WPS或EXCEL表格单元格下拉快捷选择项修改及设置方法

WPS或新版本EXCEL的设置下拉选项的方法是.点击一个单元格,菜单上选择数据,下拉列表即可设置,双击文字可编辑 EXCEL 旧的版本不同,可能有不同方法 方法一, 1.在空白区域里面&#xff0c;准备好需要填入下拉菜单里面的内容。 2.选中一个需要添加下拉菜单的单元格&#xff0c;然后…

Linux编辑器-vim使用

文章目录 前言一、vim编辑器1、vim的基本概念2、vim的基本操作2.1 命令模式切换至插入模式2.2 插入模式切换至命令模式2.3 命令模式切换至底行模式 3、vim命令模式命令集3.1 移动光标3.2 删除文字3.3 复制与粘贴3.4 替换3.5 撤销上一次操作3.6 更改3.7 跳至指定的行 4、vim末行…

论文浅尝 | 思维树:使用大语言模型反复思考解决问题

笔记整理&#xff1a;许泽众&#xff0c;浙江大学博士&#xff0c;研究方向为知识图谱上的神经符号推理 链接&#xff1a;https://arxiv.org/abs/2305.10601 1. 动机 语言模型是一种强大的工具&#xff0c;可以用于各种需要数学、符号、常识或知识推理的任务。然而&#xff0c;…

请体验一下falcon 180b 大语言模型的感觉

引言 由Technology Innovation Institute(T四训练的开源大模型Falcon 180B登陆Hugging Face!Falcon180B为开源大模型树立了全新的标杆。作为当前最大的开源大模型&#xff0c;有l80B参数并且是在在3.5万亿token的TII RefinedWeb数据集上进行训练&#xff0c;这也是目前…

列表和字典练习

定义四个学生信息 在Python环境下&#xff0c;用列表定义&#xff1a; >>> stu1[xiaoming,True,21,79.9] >>> stu1[lihong,False,22,69.9] >>> stu1[zhangqiang,True,20,89.9] >>> stu1[EMT,True,23,99.9]如图&#xff0c;定义了四个列表…

Redis高效、安全的不停机数据迁移方案

Redis是目前最流行的键值对存储数据库&#xff0c;凭借高性能和丰富的数据类型的特性&#xff0c;不仅可以作为缓存&#xff0c;还可以作为一个可持久化的数据库存储。随着业务的发展和版本的迭代&#xff0c;必然会遇到内存不足、集群节点不够和BUG等一系列问题。为了防止这些…

深入理解JVM虚拟机第三篇:JVM的指令集架构模型和JVM的生命周期

文章目录 一&#xff1a;JVM的指令集架构模型 1&#xff1a;基于栈式架构的特点 (1)&#xff1a;什么叫零地址指令、一地址指令、二地址指令、三地址指令&#xff1f; (2)&#xff1a;为什么说不需要硬件支持&#xff0c;可移植性好&#xff1f; 2&#xff1a;基于寄存…

基于Elasticsearch的多文档检索 比如 商品(goods)、案例(cases)

概述 Elasticsearch多文档聚合检索 详细 记得把这几点描述好咯&#xff1a;需求&#xff08;要做什么&#xff09; 代码实现过程 项目文件结构截图 演示效果 应用场景 我们需要在五种不同的文档中检索数据。 比如 商品&#xff08;goods&#xff09;、案例&#xff08;ca…

1014. 最佳观光组合

1014. 最佳观光组合 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 1014. 最佳观光组合 https://editor.csdn.net/md/?not_checkout1&spm1000.2115.3001.5352 完成情况&#xff1a; 解题思路&#xff1a; …

【DevOps核心理念基础】3. 敏捷开发最佳实践

一、敏捷开发最佳实践 1.1 项目管理 1.2 需求管理 1.3 技术架构 1.4 技术开发 1.5 测试 二、敏捷开发最佳实践 2.1 敏捷开发的执行细节 三、全面的DevOps工具链 四、版本控制和协作开发工具 4.1 集中式版本控制工具 4.2 分布式版本控制工具 一、敏捷开发最佳实践 …

房地产小程序 | 小程序赋能,房地产业务数字化升级

随着科技的不断发展&#xff0c;房地产行业正逐渐向数字化转型。在这个过程中&#xff0c;房地产小程序成为了一种重要的工具&#xff0c;可以帮助房地产企业提供更好的购房体验、增加销售额&#xff0c;并实现管理的便捷化。 优点 便捷购房体验&#xff1a;房地产小程序为用户…

使用mybatis批量插入数据

最近在做项目的时候&#xff0c;有些明细数据&#xff0c;一条一条的插入太费资源和时间&#xff0c;所以得需要批量插入&#xff0c;今晚闲来无事写个小demo。 新建工程 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis…

如何实现微服务

一、问题拆解 1.1、客户端如何访问这些服务 原来的Monolithic方式开发&#xff0c;所有的服务都是本地的&#xff0c;UI可以直接调用&#xff1b;现在按功能拆分成独立的服务&#xff0c;跑在独立的虚拟机上的Java进程了。客户端UI如何访问他的&#xff1f; 后台有N个服务&a…

计算机毕业设计 高校课程评价系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

redis安装部署

文章目录 准备工作下载安装包修改配置文件命令常用配置信息 准备工作 检查linux系统是否安装了相关的编译工具 要检查 Linux 系统上是否已经安装了编译工具&#xff0c;可以执行以下命令&#xff1a; 检查 GCC 是否安装&#xff1a;在终端窗口中运行 gcc --version 命令&#…

CTFhub_SSRF靶场教程

CTFhub SSRF 题目 1. Bypass 1.1 URL Bypass 请求的URL中必须包含http://notfound.ctfhub.com&#xff0c;来尝试利用URL的一些特殊地方绕过这个限制吧 1.利用?绕过限制urlhttps://www.baidu.com?www.xxxx.me 2.利用绕过限制urlhttps://www.baidu.comwww.xxxx.me 3.利用斜…

ARM Linux DIY(八)USB 调试

前言 V3s 带有一个 USB 接口&#xff0c;将其设置为 HOST 或 OTG 模式&#xff0c;这样可以用来接入键盘、鼠标等 USB 外设。 USB 简介 USB 有两种设备&#xff1a;HOST 和 USB 功能设备。 在 USB2.0 中又引入了一个新的概念 OTG&#xff0c;即设备角色可以动态切换。 切换方…

技术架构图是什么?和业务架构图的区别是什么?

技术架构图是什么&#xff1f; ​技术架构图是一种图形化工具&#xff0c;用于呈现软件、系统或应用程序的技术层面设计和结构。它展示了系统的各种技术组件、模块、服务以及它们之间的关系和交互方式。技术架构图关注系统内部的技术实现细节&#xff0c;以及各个技术组件之…