如何在R中编写并行代码来同时索引对象?
我有两个大的字符串列表,我想检查列表中的每个字符串是否有五个不同的序列 我目前有连续执行此操作的代码。它在列表中的每个条目中搜索一个序列,然后在列表中搜索下一个序列,然后搜索下一个序列,依此类推 作为我如何构建代码的示例,我的想法如下:如何在R中编写并行代码来同时索引对象?,r,parallel-processing,R,Parallel Processing,我有两个大的字符串列表,我想检查列表中的每个字符串是否有五个不同的序列 我目前有连续执行此操作的代码。它在列表中的每个条目中搜索一个序列,然后在列表中搜索下一个序列,然后搜索下一个序列,依此类推 作为我如何构建代码的示例,我的想法如下: library(Biostrings) library(parallel) #The data sequences <- c("ATGGTA","CGAACT","AAATGC","CTTTGA","ACCAGT") biglist <- list
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
)
)
)
}
)
}
)
当我运行代码时,我得到
检查群集(cl)中的错误:不是有效群集
我猜这意味着我不能像我为Parlappy打算的那样使用多个集群。如果我尝试将clusterExport
与群集对象向量一起使用,则会出现相同的错误。有没有办法单独增加这些指数?我要生成的列表中的元素互不依赖,因此应该有一种并行执行它们的方法。您的数据
sequences <- c("ATGGTA","CGAACT","AAATGC","CTTTGA","ACCAGT")
biglist <- list("AAAAAAAAAAAAAAAAAAAATGGTACCCCCCCCCCCCCCCCCCCCCCC",
"AAAAAAAAAAAAAAAAAAAAAATGCTTTTTTTTTTTTTTTTTTTTTTT",
"AAAAAAAAAAAAAAAAAAACGAACTGGGGGGGGGGGGGGGGGGGGGGG",
"TTTTTTTTTTTTTTTTTTTCTTTGACCCCCCCCCCCCCCCCCCCCCCC",
"GGGGGGGGGGGGGGGGGGGACCAGTAAAAAAAAAAAAAAAAAAAAAAA")
下面的parlappy
语句将遍历序列
,将每个元素传递给一个新的核心。在内核中,它将执行函数(x){…}
。在这种情况下,您可以使用矢量化(注意:fast)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
(1) 我认为
cl
不是可以传递给集群内节点的变量(我可能错了)。(2) 对我来说,使用嵌套的parlappy
似乎不合适(我并不是说它不合适,但我不会这么做)。我建议(a)在内部循环中接受简单的lappy
,或者(b)使用expand.grid
在主循环中生成biglist
和sequences
的所有(必要)组合,然后与此扩展帧的每一行并行。使用此代码的几个“BTW”:(1)biglist
是一个list
,那么它不应该是biglist[[i]]
?(2) 与1:length(…)
相反,我建议seq_沿着(…)
或seq_len(length(…)
,它可以防止在0长度向量/列表上建立不正确的索引。(3) 是否有理由针对1:length(…)
而不是数据本身,如parLapply(cl、biglist、function(x)…)
?如果您不需要索引号,为什么不直接传递值本身呢?您在(1)上是对的。这不是我实际代码的复制和粘贴。那只是一个打字错误。(2) 我知道我处理的数据不会给我0长度的向量/列表。在我使用的情况下,唯一的方法是如果我没有从测序中读取DNA。至于(3)这就是我被教导如何使用lappy/parlappy的方法。我见过其他人使用lapply,他们按照您的建议提供数据,但我始终无法获得正确的语法。称之为坏习惯。如果我可以问的话,+0是否可以将TRUE转换为1的数值?如果是这样的话,这样做会丢失查询和主题之间实际存在多少匹配的信息。另外,很抱歉,我对格雷普不熟悉。如果我想在我列出的序列中允许突变,我是否必须将每个可能的可接受突变输入到对象序列中
?我使用matchPatterns的另一个原因是,它允许我指定查询和主题(或者在本例中是列表中的模式和字符串)之间允许的最大不匹配量。是的,+0
是将逻辑转换为数字。是的,如果你想坚持使用grepl
,你必须将每个突变添加到序列中。如果你想接受突变,我建议你坚持使用matchPatterns
。不要嵌套parlappy
。您必须决定要并行化的lappy
语句。在这种情况下,我将并行化外部lappy
(跨序列)并保持内部lappy
(跨1:biglist的长度)为正常的lappy
。如果我在序列上有lappy
,在1:length(biglist)
上有parlappy
,这会不会像有一系列的parlappy
s,其中每个parlappy
接受向量序列的元素?我在RStudio中的代码目前就是这个系列,我试图将其并行化,因为它对于包含100mil+序列的biglist文件来说仍然太慢,而且还因为parlappy
的每个输出都是独立的。如果我在序列上使用parlappy
,在biglist
上使用lappy
,那真的会更快吗(看看biglist
有数百万个序列,sequences
只有5个)?没错,你想并行化1:length(biglist)
。我唯一担心的是,在内核之间传递数据常常会导致速度减慢。如果并行化biglist
,则将传递100mil数据对象并重新收集100mil结果。这就是为什么我建议为您的问题找到一个矢量化的解决方案,而不是简单的并行化解决方案
clusterExport(cl, c("biglist"))
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