共计 2003 个字符,预计需要花费 6 分钟才能阅读完成。
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 多平台公布