首页 > 解决方案 > 如何在 R 中编写并行代码以同时索引对象?

问题描述

所以我有两个大的字符串列表,我想检查列表中的每个字符串是否有五个不同的序列。

我目前有连续执行此操作的代码。它在列表中的每个条目中搜索一个序列,然后在列表中搜索下一个序列,然后是下一个,依此类推。

作为我将如何构建代码的示例,我正在考虑如下内容:

library(Biostrings)
library(parallel)

#The data
sequences <- c("ATGGTA","CGAACT","AAATGC","CTTTGA","ACCAGT")
biglist <- list("AAAAAAAAAAAAAAAAAAAATGGTACCCCCCCCCCCCCCCCCCCCCCC",
                "AAAAAAAAAAAAAAAAAAAAAATGCTTTTTTTTTTTTTTTTTTTTTTT",
                "AAAAAAAAAAAAAAAAAAACGAACTGGGGGGGGGGGGGGGGGGGGGGG",
                "TTTTTTTTTTTTTTTTTTTCTTTGACCCCCCCCCCCCCCCCCCCCCCC",
                "GGGGGGGGGGGGGGGGGGGACCAGTAAAAAAAAAAAAAAAAAAAAAAA")

#Making clusters for parallel workload
cl1 <- makeCluster(detectCores()/2)
cl2 <- makeCluster(detectCores()/2)
clusterExport(cl1, c("sequences","biglist","length","nchar","matchPattern"))
clusterExport(cl2, c("sequences","biglist","length","nchar","matchPattern"))

#Converting biglist to nucleotide sequence for matchPattern to read
biglistDNA <- parLapply(cl1,
                        1:length(biglist),
                        function(i) DNAString(biglist[[i]],
                                              start = 1,
                                              nchar = nchar(biglist[[i]])
                                             )
                       )

#Exporting the new list
clusterExport(cl1, "biglistDNA")
clusterExport(cl2, "biglistDNA")

#The problem child
Matched <- parLapply(c(cl1,cl2),
                     1:length(sequences),
                     function (i) {parLapply(
                                             cl1,
                                             1:length(biglistDNA),
                                             function(j){length(
                                                         nchar(
                                                         matchPattern(
                                                         sequences[i],
                                                         biglistDNA[[j]],
                                                         0,
                                                         0
                                                         )
                                                         )
                                                         )
                                                        }
                                            )
                                  }
                    )

我期望(并且想要)的是一个列表,其中第一个元素是一个列表,说明在序列的第一个元素和 biglistDNA 的每个元素之间找到了多少匹配,第二个元素是一个列表,说明在之间找到了多少匹配序列的第二个元素和 biglistDNA 的每个元素,以此类推。我知道 matchPattern 的 nchar 的长度为我提供了查询序列和主题序列之间的匹配数量,以从串行运行我的代码。

像这样的东西

Matched
[[1]]
[1] 1 0 0 0 0
[[2]]
[1] 0 0 1 0 0
[[3]]
[1] 0 1 0 0 0
[[4]]
[1] 0 0 0 1 0
[[5]]
[1] 0 0 0 0 1

当我运行代码时,我得到 Error in checkCluster(cl) : not a valid cluster.

我猜这意味着我不能按照我打算用于 parLapply 的方式使用多个集群。如果我尝试clusterExport与集群对象向量一起使用,我会遇到同样的错误。有没有办法单独增加这些指数?我要生成的列表的元素不相互依赖,因此应该有一种方法可以并行执行它们。

标签: rparallel-processing

解决方案


您的数据

sequences <- c("ATGGTA","CGAACT","AAATGC","CTTTGA","ACCAGT")
biglist <- list("AAAAAAAAAAAAAAAAAAAATGGTACCCCCCCCCCCCCCCCCCCCCCC",
            "AAAAAAAAAAAAAAAAAAAAAATGCTTTTTTTTTTTTTTTTTTTTTTT",
            "AAAAAAAAAAAAAAAAAAACGAACTGGGGGGGGGGGGGGGGGGGGGGG",
            "TTTTTTTTTTTTTTTTTTTCTTTGACCCCCCCCCCCCCCCCCCCCCCC",
            "GGGGGGGGGGGGGGGGGGGACCAGTAAAAAAAAAAAAAAAAAAAAAAA")

正如@r2evans 在评论中指出的那样,声明 2 个集群是没有意义的。无论您声明 1 个还是 N 个集群,您都将使用所有可用的内核。

library(parallel)
cl <- makeCluster(detectCores()-1)

从技术上讲,您只需要导出biglist到集群,因为 的元素sequences将通过parLapply

clusterExport(cl, c("biglist"))

下面的parLapply语句将遍历sequences,将每个元素传递给一个新的核心。在核心内,它将执行function(x) { ... }. 在这种情况下,您可以使用矢量化 (注意:快速) 获得您想要的结果grepl(pattern, list)grepl将在字符串列表中搜索模式的存在。

parLapply(cl, sequences, function(x) { grepl(x, biglist) + 0 })

输出

[[1]]
[1] 1 0 0 0 0

[[2]]
[1] 0 0 1 0 0

[[3]]
[1] 0 1 0 0 0

[[4]]
[1] 0 0 0 1 0

[[5]]
[1] 0 0 0 0 1

推荐阅读