关于程序员:R语言多线程提高计算速度如何使用foreach包加速并行计算

3次阅读

共计 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 多平台公布

正文完
 0