R语言多线程减速

通常状况下,R语言只能应用一个线程来进行计算,因而计算的速度及其感人!

最近刚好有一个需要:我有一个参考数据表,外面寄存了30万条基因的名称和地位信息,当初我想从外面找到指定的6000个基因的地位信息。

最简略的办法是用两层for循环进行迭代,一分钟写出以下代码:

for (i in 1:nrow(df)){    pos <- 0    for (m in 1:nrow(ref)){        if (ref$geneID[m] == gene$ID[i]){            pos <- ref$pos[m]        }    }    df$pos[i] <- pos}

这段代码是一个双重循环构造,其中外层循环遍历数据框df中的每一行,内层循环遍历参考数据框ref中的每一行。那么也就是说一共要计算290000*6000次。如果是一个线程跑到花儿都谢了。。。。

R语言中如何实现多线程,使计算速度更快?明天分享一个提高效率的神技能。

前言

在R语言中,for循环是一个十分常见的循环构造,它能够用来遍历数据集、进行计算等。

然而,当数据量较大时,应用for循环进行计算会十分耗时,这时咱们能够思考应用多线程来减速计算。

单线程计算

咱们首先来看一下单线程的计算速度,上面是一个简略的for循环示例:

# 生成一个长度为100000000的随机向量x <- rnorm(100000000)# 计算向量中所有元素的平方start_time <- Sys.time()for (i in 1:length(x)) {  x[i] <- x[i] ^ 2}end_time <- Sys.time()# 输入计算工夫cat("单线程计算工夫:", end_time - start_time, "\n")

运行以上代码,咱们能够失去一个长度为100000000的随机向量,并对其中的每个元素进行平方计算。运行后果如下:

能够看到,单线程计算1000000个元素的平方须要0.024秒左右。

多线程计算

接下来,应用foreach包来实现多线程计算。foreach包是一个十分罕用的并行计算包,它能够在多个处理器上并行运行迭代过程。上面是应用foreach包进行多线程计算的示例代码:

# 加载foreach包library(foreach)# 生成一个长度为100000的随机向量x <- rnorm(100000000)# 应用foreach包进行多线程计算start_time <- Sys.time()foreach(i = 1:length(x), .combine = c) %dopar% {  x[i] <- x[i] ^ 2}end_time <- Sys.time()# 输入计算工夫cat("多线程计算工夫:", end_time - start_time, "\n")

运行以上代码,咱们能够失去与单线程雷同的后果。然而,因为应用了多线程计算,计算工夫会更短。运行后果如下:

多线程计算工夫: 0.00099906 

能够看到,应用foreach包进行多线程计算100000000个元素的平方只须要0.0009秒左右,比单线程计算快了很多。

多线程计算的原理

在下面的示例中,咱们应用了foreach包来实现多线程计算。foreach包的原理是将迭代过程分成多个局部,每个局部在不同的处理器上并行运行。

具体来说,foreach包将迭代过程分成若干个工作,并将这些任务分配给不同的处理器进行计算。每个处理器计算实现后,foreach包会将计算结果合并起来,并返回最终后果。

在下面的示例中,咱们应用了%dopar%关键字来示意并行运行。这个关键字通知foreach包在多个处理器上并行运行迭代过程。另外,咱们还应用了.combine = c参数来通知foreach包如何将计算结果合并起来。这里咱们应用了c函数来将计算结果合并成一个向量。

总结

在本文中,介绍了如何在R语言中实现多线程计算,并比照了单线程与多线程的计算速度。能够看到,应用多线程能够大大放慢计算速度,特地是在数据量较大时。在理论利用中,咱们能够依据本人的需要抉择不同的多线程计算包来实现并行计算。

彩蛋

最初,分享本文开始时提出问题的答案,通过以下代码替换原来的双层嵌套for循环,能大幅提高计算速度,从集体应用上来看,原来24小时跑完的工作,当初1小时就能出后果(次要还是CPU外围数限度,不然可能还能再快一点儿)

# 设置并行计算的外围数num_cores <- detectCores()cl <- makeCluster(num_cores - 1)# 注册并行计算集群registerDoParallel(cl)# 定义并行计算工作gene_pos <- foreach(i = 1:nrow(gene), .combine = rbind) %dopar% {    pos <- 0    for (m in 1:nrow(ref)){        if (ref$gene[m] == gene$V1[i]){            pos <- ref$pos[m]        }    }    pos}# 完结并行计算stopCluster(cl)

本文由mdnice多平台公布