r - 如何在 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
与集群对象向量一起使用,我会遇到同样的错误。有没有办法单独增加这些指数?我要生成的列表的元素不相互依赖,因此应该有一种方法可以并行执行它们。
解决方案
您的数据
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