在Perl上使用线程进行DNA序列分析

时间:2018-10-28 01:24:42

标签: multithreading perl bioinformatics dna-sequence

我有一个示例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模块Para​​llel :: 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数组中,因为我稍后在程序中再次使用它。

再次感谢您的帮助。

1 个答案:

答案 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;