【问题标题】:Using threads on DNA sequence analysis with Perl使用 Perl 进行 DNA 序列分析的线程
【发布时间】:2019-04-01 07:55:16
【问题描述】:

我有一个示例 DNA 序列,例如: S = ATGCGGGCGTGCTGCTGGGCTGCT.... 长度为 5MB。 另外,我有每个基因的基因坐标,例如:

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 {
     ......
}

如果有人能建议我如何并行化此类程序,我将不胜感激。我想要并行化的是每个基因的模型1和模型2之间的c值计算,这最终将加快这个过程。 我曾尝试使用 Threads::queue 但以一堆错误结束。我对 Perl 编程相当陌生,因此非常感谢任何帮助。

感谢大家的 cmets 和建议。我已经修改了代码,它似乎正在使用 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 数组中,因为我稍后会在程序中再次使用它。

再次感谢您帮助我。

【问题讨论】:

  • 试试AnyEvent::Forkmetacpan.org/pod/AnyEvent::Fork
  • 任何优化的第一步都是测量。然后,使用分析器来确定究竟在哪里花费了多少时间。然后,也只有到那时,考虑不同的优化方法。
  • 请展示更多你的代码,不是 perl 标签上的每个人都熟悉生物信息学,但如果提供更多细节,仍然可以帮助你进行并行化..
  • 一个错误可能是因为$c-value 不是有效的 Perl 标识符。如果你使用严格和警告(你应该)这将由于值bareword而导致错误。只有单词字符(字母、数字、下划线)在 Perl 标识符中有效。
  • 另外foreach my $gene($sequence){ 没有意义,它只会运行一次,因为您提供了一个标量值供它迭代。

标签: multithreading perl bioinformatics dna-sequence


【解决方案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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    • 2011-10-28
    • 1970-01-01
    • 2017-05-12
    • 2021-09-16
    相关资源
    最近更新 更多