如何解决如何在 R 中嵌套 foreach 循环的内循环和外循环之间添加代码
我了解到在 R 中执行嵌套 foreach 循环的正确方法是通过嵌套运算符 %:%
(例如 https://cran.r-project.org/web/packages/foreach/vignettes/nested.html)。
但是,使用这种方法时,不能在内循环和外循环之间添加代码——请参见下面的示例。
有没有办法创建嵌套的、并行的 foreach 循环,以便可以在内循环和外循环之间添加代码?
更一般地说,我想到的显而易见的方法有什么问题,即简单地使用 %dopar%
运算符而不是 %:%
运算符嵌套两个 foreach 循环?请参阅下面的简单示例。
library(foreach)
# Set up backend
cl = makeCluster(6)
registerDoParallel(cl)
on.exit(stopCluster(cl))
# Run nested loop with '%:%' operator. Breaks if adding code between the inner and outer loops
foreach(i=1:2) %:%
# a = 1 #trivial example of running code between outer and inner loop -- throws error
foreach(j = 1:3) %dopar% {
i * j
}
# Run nested loop using 2 '%dopar%' statements -- is there anything wrong with this?
foreach(i=1:2,.packages = 'foreach') %dopar% {
a = 1 #trivial example of running code between outer and inner loop
foreach(j = 1:3) %dopar% {
i * j
}
}
解决方法
provided 文档中的“将 open (F,$file) or die; ### open the file or end the analyze
while(my $one = <F>) {### readline => F
chomp $one;
my @cols = split(/\s+/,$one); ### split columns
next unless (scalar @cols) == 8; ### the line must have 8 columns to add to the array
my $val = $cols[5];
if ($val >= 0.5) {
my $position = $cols[3];
my $id_list = $cols[0];
$id_list =~ s/^\s*([^_]+)_([0-9]+)_([a-zA-Z0-9]+)/$1.$2|$3/;
if (exists($fastadata{$id_list})) {
my $new_seq = $fastadata{$id_list};
my $subresidues = substr($new_seq,$position -3,5);
print $subresidues,"\n";
}
}
}
与 %:%
一起使用”一章给出了有用的提示:
所有的任务都是完全独立的,所以它们都可以并行执行
%dopar%
运算符将多个 foreach 循环变成一个循环。 这就是上例中只有一个 %:%
运算符的原因。当我们通过将 %do%
更改为 %do%
来并行化嵌套的 foreach 循环时,我们正在创建可以并行执行的单个任务流。
当您组合两个 %dopar%
并测量执行时间时,您会看到只有外循环是并行执行的,这可能不是您要找的:
%dopar%
这段经过的时间反映了:
system.time(
foreach(i=1:2,.packages = 'foreach') %dopar% {
# Outer calculation
Sys.sleep(.5)
foreach(j = 1:3) %dopar% {
# Inner calculation
Sys.sleep(1)
}
})
# user system elapsed
# 0.00 0.00 3.52
如果外层计算不是太长,放入内循环实际上更快,因为使用了您示例的6个worker:
parallel[ outer(0.5s) + sequential [3 * inner(1s)] ] ~ 3.5s
如果外层计算太长,并且您的内循环比外循环多得多,您可以并行预先计算外循环。然后您可以在 system.time(res <- foreach(i=1:2,.packages = 'foreach') %:%
foreach(j = 1:3) %dopar% {
# Outer calculation
Sys.sleep(.5)
# Inner calculation
Sys.sleep(1)
})
# user system elapsed
# 0.02 0.02 1.52
中使用结果:
%:%
比 :
快system.time({
precalc <- foreach(i=1:2) %dopar% {
# Outer pre-calculation
Sys.sleep(2)
i
}
foreach(i=1:2,.packages = 'foreach') %:%
foreach(j = 1:12) %dopar% {
# Inner calculation
Sys.sleep(1)
precalc[[i]]*j
}
})
# user system elapsed
# 0.11 0.00 5.25
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。