R语言常用两种并行方法之parallel详解

目录
  • 并行计算
  • 在模拟时什么地方可以用到并行?
  • 怎么在R中看我们可以使用并行?
  • parallel(简单)

由于最近在进行一些论文的模拟,所以尝试了两种并行的方法:parallelsnowfall,这两种方法各有优缺,但还是推荐snowfall,整体较为稳定,不容易因为内存不足或者并行线程过多等原因而报错。

并行计算

并行计算: 简单来讲,就是同时使用多个计算资源来解决一个计算问题,是提高计算机系统计算速度和处理能力的一种有效手段。(参考:并行计算简介)

  • 一个问题被分解成为一系列可以并发执行的离散部分;
  • 每个部分可以进一步被分解成为一系列离散指令;
  • 来自每个部分的指令可以在不同的处理器上被同时执行;
  • 需要一个总体的控制/协作机制来负责对不同部分的执行情况进行调度。

而在我们平时的模拟中,在一台电脑或者服务器上,就是将我们的计算任务分散到多个不同的小的核中同时进行处理。

在模拟时什么地方可以用到并行?

并行操作一般适用于重复的操作,比如重复随机按照相同分布生成数据,然后分别同时进行模拟。这里就可以用并行。亦或者我们要做permutation计算p-value等信息,也可以进行并行,因为这种操作是简单的重复即可完成。

但诸如迭代,递归等算法就很难用并行实现,这种都叫串行。因为后一个的对象需要前一个对象的信息,只能先算完前一个,再计算后一个内容。

在进行实际的模拟比较多种方法的优劣时,通常需要重复实验成百上千次,一般可对这里进行并行操作,写在这里的操作是最简单的。但会有个缺点:可能会出现挂服务器跑了半天还没出现结果,但是自己又并不知道运行到哪了的现象。虽然有一些方法可以进行查看(例如snowfall中的sfCat()函数,但是输出的结果是相对来说比较凌乱的,而且有时还会输出不了,具体用法后面会进行介绍),但是还是可能等很久才出一些结果,如果并行某一个地方维度或者代码有些小瑕疵,整段结果都没法进行输出。

所以建议,如果能将并行写到每个算法中间的话,就尽量写到每个具体算法之中(如需要permutation的写到permutation中;如要多次for循环计算统计量以及其它信息的,直接替代for循环),这样后面实际操作时也比较方便。(这样做的缺点是可能导致内存占用过多,从而使并行出错)

怎么在R中看我们可以使用并行?

只需使用如下命令,就可以查看我们电脑能够使用的线程数:

detectCores()

理论上这个值 ≥2,我们电脑就可以进行并行操作(现在的电脑基本都是4往上的)。当然通常我们不会使用所有的线程来进行并行,不然。。。电脑很可能会崩。

言归正传,下面介绍两种R中常用的并行操作(默认会apply族相关操作)。

parallel(简单)

一个是parallel包,此包最大的优势就是非常的便捷,只需将我们原本的apply()修改为parApply()lapply()修改为parLapply()sapply()修改为我们常用的parSapply()等等,然后再在开头和结尾添加上相应的开始并行与结束并行的语句即可。

下面举个栗子(参考:How-to go parallel in R – basics + tips

首先我们使用lapply()进行下述操作向量化操作:

lapply(1:3, function(x) c(x, x ^ 2, x ^ 3))

输出结果为:

[[1]]
[1] 1 1 1

[[2]]
[1] 2 4 8

[[3]]
[1]  3  9 27

我们将其修改为并行方法,首先是初始化我们的并行:

library(parallel) # 载入parallel包

# 计算可用线程数,并设置并行使用线程数
no_cores <- detectCores() - 1

# 初始化
cl <- makeCluster(no_cores)

然后修改原本我们lapply()的命令:

parLapply(cl, 1:3, function(x) c(x, x ^ 2, x ^ 3))

注意:这里与一般的lapply()相比,要加上cl。

输出结果为:

[[1]]
[1] 1 1 1

[[2]]
[1] 2 4 8

[[3]]
[1]  3  9 27

到这里我们还没完,前面初始化我们的并行,这里需要结束我们的并行,释放我们用到的线程与内存,返还给系统。具体使用如下语句:

stopCluster(cl)

至此,一个简单的并行就完成了。

但事情远远没这么简单,在我们需要处理非常复杂的并行任务,反复使用parallel库中的并行方法时,我们没办法将我们的线程数开到最大,有时候甚至连一半都不行,它会出现下面所示的报错:

Error in unserialize(node$con) : error reading from connection

这种情况出现的原因就很复杂了,这是因为“调用核心数–计算机内存”的不匹配造成的。如果你的数据集很大,调用了很多核心,那么你的计算机内存如果不够匹配,就会出现连接不上的不错,甚至还出现卡机等现象。简言之就是爆内存了。

解决方法(不能说完全解决,只能说能有效缓解):

使用更少的线程进行并行;

如果你的电脑内存非常小,有一个简单的方法确定你的最大使用线程:

max cores = memory.limit() / memory.size();

将大量的并行分小部分进行;在代码中多使用rm()删除没用的变量,使用gc()回收内存空间;

不过后面我们介绍另一种并行方式snowfall相对而言就更加稳定了(虽然代码写起来会相对复杂一些),这个我们留待下一篇博客:R中两种常用并行方法snowfall 中进行详细介绍。

以上就是R语言常用两种并行方法之parallel详解的详细内容,更多关于R语言并行方法parallel的资料请关注我们其它相关文章!

(0)

相关推荐

  • R语言常用两种并行方法之snowfall详解

    上一篇博客(R中两种常用并行方法之parallel)中已经介绍了R中常见的一种并行包:parallel,其有着简单便捷等优势,其实缺点也是非常明显,就是很不稳定.很多时候我们将大量的计算任务挂到服务器上进行运行时,更看重的是其稳定性. 这时就要介绍R中的另一个并行利器--snowfall,这也是在平时做模拟时用的最多的一种方法. 针对上篇中的简单例子 首先是一个最简单的并行的例子,这个例子不需要载入任何依赖库.函数.对象等.相对也比较简单: library(snowfall) # 载入snowf

  • R语言中for循环的并行处理方式

    前言 本文用于记录笔者在将R语言中的for语句并行化处理中的一些问题. 实验 这里使用foreach和doParallel包提供的函数实现for语句的并行处理. for语句脚本 func <- function(x, y, z) { return(x^y/z) } # >>> main <<< x <- 2 y <- 3 z <- 1:100000 start <- (proc.time())[3][[1]] a <- 0 for (

  • R语言通过parallel包实现多线程运行方式

    总的来说,R的运算速度不算快,不过类似并行运算之类的改进可以提高运算的性能.下面非常简要地介绍如何利用R语言进行并行运算 library(parallel) cl.cores <- detectCores() cl <- makeCluster(cl.cores) detectCores( )检查当前电脑可用核数. makeCluster(cl.cores)使用刚才检测的核并行运算.R-Doc里这样描述makeCluster函数:Creates a set of copies of R run

  • R语言常用两种并行方法之parallel详解

    目录 并行计算 在模拟时什么地方可以用到并行? 怎么在R中看我们可以使用并行? parallel(简单) 由于最近在进行一些论文的模拟,所以尝试了两种并行的方法:parallel与snowfall,这两种方法各有优缺,但还是推荐snowfall,整体较为稳定,不容易因为内存不足或者并行线程过多等原因而报错. 并行计算 并行计算: 简单来讲,就是同时使用多个计算资源来解决一个计算问题,是提高计算机系统计算速度和处理能力的一种有效手段.(参考:并行计算简介) 一个问题被分解成为一系列可以并发执行的离

  • R语言刷题检验数据缺失类型过程详解

    目录 题目 解答 下面考虑三种情况: 1. a = 0, b = 0 2. a = 2, b = 0 3. a = 0, b = 2 题目 解答 由于题目要求需要重复三次类似的操作,故首先载入所需要的包,构造生成数据的函数以及绘图的函数: library(tidyr) # 绘图所需 library(ggplot2) # 绘图所需 # 生成数据 GenerateData <- function(a = 0, b = 0, seed = 2018) { set.seed(seed) z1 <- r

  • C语言常用库函数的使用及模拟实现详解例举

    目录 1.strlen 1.计数法 2.递归法 3.指针减指针 2.strcpy 3.strcmp 4.strcat 5.strstr 6.strtok 7.字符分类函数 8.memcpy&memmove 9.memcmp 经历了C语言基础篇的学习,让我们来简单了解几个C语言的库函数! 1.strlen 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' ). 函数的模拟实现 1.计数法 int my_strlen(dest)

  • R语言使用cgdsr包获取TCGA数据示例详解

    目录 TCGA数据源 TCGA数据库探索工具 查看任意数据集的样本列表方式 选定数据形式及样本列表后获取感兴趣基因的信息,下载mRNA数据 选定样本列表获取临床信息 综合性获取 下载mRNA数据 获取病例列表的临床数据 从cBioPortal下载点突变信息 从cBioPortal下载拷贝数变异数据 把拷贝数及点突变信息结合画热图 TCGA数据源 众所周知,TCGA数据库是目前最综合全面的癌症病人相关组学数据库,包括的测序数据有: DNA Sequencing miRNA Sequencing P

  • Java 两种延时thread和timer详解及实例代码

    Java 两种延时thread和timer详解及实例代码 在Java中有时候需要使程序暂停一点时间,称为延时.普通延时用Thread.sleep(int)方法,这很简单.它将当前线程挂起指定的毫秒数.如 try { Thread.currentThread().sleep(1000);//毫秒 } catch(Exception e){} 在这里需要解释一下线程沉睡的时间.sleep()方法并不能够让程序"严格"的沉睡指定的时间.例如当使用5000作为sleep()方法的参数时,线 程

  • Android 两种启动模式的实例详解

    Android 两种启动模式的实例详解 Intent的FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_REORDER_TO_FRONT Activity的两种启动模式:FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_REORDER_TO_FRONT 1. 如果已经启动了四个Activity:A,B,C和D.在D Activity里,我们要跳到B Activity,同时希望C finish掉,可以在startActivity(intent)里

  • 对Python中创建进程的两种方式以及进程池详解

    在Python中创建进程有两种方式,第一种是: from multiprocessing import Process import time def test(): while True: print('---test---') time.sleep(1) if __name__ == '__main__': p=Process(target=test) p.start() while True: print('---main---') time.sleep(1) 上面这段代码是在window

  • Vue中Router路由两种模式hash与history详解

    hash 模式 (默认) 工作原理: 监听网页的hash值变化 -> onhashchange事件, 获取location.hash 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载. 会给用户好像跳转了网页一样的感觉, 但是实际上没有跳转 主要用在单页面应用(SPA) // 模拟原理 // 监听页面hash值变化 window.onhashchange = function(){ // 获取当前url的哈希值 const _hash = locat

  • Spring依赖注入的两种方式(根据实例详解)

    1,Set注入    2,构造注入 Set方法注入: 原理:通过类的setter方法完成依赖关系的设置 name属性的取值依setter方法名而定,要求这个类里面这个对应的属性必须有setter方法. Set方法注入时spring中配置文件: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans&qu

随机推荐