我有一个示例DNA序列,例如:
长度为5MB的S = ATGCGGGCGTGCTGCTGGGCTGCT....
。
另外,我具有每个基因的基因坐标,例如:
Gene no. Start End
1 1 50
2 60 100
3 110 250
.....
4000 4640942 4641628
我的目标是对每个基因的起始位置进行一定的计算。我的代码运行正常。但是,它很慢。我遍历了很多帮助页面,以使使用线程的速度更快,但不幸的是找不到。
这是我的代码摘要:
foreach my $gene($sequence){
my @coordinates = split("\t",$gene);
$model1 = substr($sequence, $coordinates[1], 50);
$model2 = substr($sequence, $coordinates[1], 60);
$c-value = calculate($model1, $model2);
....
}
sub calculate {
......
}
如果有人可以建议我如何并行化此类程序,我将不胜感激。我要并行化的是对每个基因的model1和model2之间的c值的计算,最终将加快该过程。 我曾尝试使用Threads :: queue,但以一堆错误结束。我对Perl编程还很陌生,因此非常感谢您的帮助。
谢谢大家,您的意见和建议。我已经修改了代码,并且似乎使用Perl模块Parallel :: ForkManager可以正常工作。该代码已成功使用我计算机的所有4个内核。
这是修改后的代码:
use strict;
use warnings;
use Data::Dumper;
use Parallel::ForkManager;
my $threads = 4;
my $pm = new Parallel::ForkManager($threads);
my $i = 1; #gene number counter
$pm -> run_on_finish( sub { $i++; print STDERR "Checked $i genes" if ($i % $number_of_genes == 0); } );
my @store_c_value = ();
foreach my $gene($sequence){
my $pid = $pm->start and next;
my @coordinates = split("\t",$gene);
my $model1 = substr($sequence, $coordinates[1], 50);
my $model2 = substr($sequence, $coordinates[1], 60);
my $c-value = calculate($model1, $model2);
push(@store_c_value, $c-value);
$i++;
$pm->finish;
}
$pm->wait_all_children;
sub calculate {
......
return ($c-value);
}
print Dumper \@store_c_value;
当前问题是我没有得到@store_c_value
(即空数组)的任何输出。我发现您无法将数据从子进程存储到数组中,该数组在主程序中已声明。
我知道我可以将其打印到一个外部文件中,但是我希望此数据位于@store_c_value
数组中,因为我稍后在程序中再次使用它。
再次感谢您的帮助。
答案 0 :(得分:1)
一个选项是IO::Async::Function,它将根据您所使用的操作系统使用派生或线程(在Unixy系统上,派生效率更高),并维护一组工作进程/线程以在其中运行代码。平行。它返回Future个实例,这些实例可用于根据需要同步异步代码。有很多使用Future的方法,下面介绍了几种。
use strict;
use warnings;
use IO::Async::Loop;
use IO::Async::Function;
use Future;
my $loop = IO::Async::Loop->new;
# additional options can be passed to the IO::Async::Function constructor to control how the workers are managed
my $function = IO::Async::Function->new(code => \&calculate);
$loop->add($function);
my @futures;
foreach my $gene($sequence){
my @coordinates = split("\t",$gene);
my $model1 = substr($sequence, $coordinates[1], 50);
my $model2 = substr($sequence, $coordinates[1], 60);
push @futures, $function->call(args => [$model1, $model2])->on_done(sub {
my $c_value = shift;
# further code using $c_value must be here, to be run once the calculation is done
})->on_fail(sub {
warn "Error in calculation for $gene: $_[0]\n";
});
}
# wait for all calculations and on_done handlers before continuing
Future->wait_all(@futures)->await;
如果您希望程序在其中一项计算中出现异常时立即停止,则可以使用needs_all并删除单个on_fail处理程序,然后使用get
(它是await
的包装器)如果成功,则将按顺序返回所有c值;如果失败,则将引发异常。
my @c_values = Future->needs_all(@futures)->get;