Multithreading 如何将多线程应用于Bio::SeqIO翻译代码(Bioperl)?

Multithreading 如何将多线程应用于Bio::SeqIO翻译代码(Bioperl)?,multithreading,perl,bioperl,Multithreading,Perl,Bioperl,我正在用这个代码将一个fasta核苷酸文件翻译成蛋白质序列 use Bio::SeqIO; use Getopt::Long; my ($format,$outfile) = 'fasta'; GetOptions( 'f|format:s' => \$format, 'o|out|outfile:s' => \$outfile, ); my $oformat = 'fasta'; $file=$ARGV[0]; chomp $file; # thi

我正在用这个代码将一个fasta核苷酸文件翻译成蛋白质序列

use Bio::SeqIO;
use Getopt::Long;

my ($format,$outfile) = 'fasta';

GetOptions(
    'f|format:s'  => \$format,
    'o|out|outfile:s' => \$outfile,
    );

my $oformat = 'fasta';
$file=$ARGV[0];
chomp $file;

# this implicity uses the <> file stream
my $seqin = Bio::SeqIO->new( -format => $format, -fh => \*ARGV);
my $seqout;
if( $outfile ) {
    $seqout = Bio::SeqIO->new( -format => $oformat, -file => ">$outfile" );
} else {
# defaults to writing to STDOUT
    $seqout = Bio::SeqIO->new( -format => $oformat );
}

    while( (my $seq = $seqin->next_seq()) ) {
            my $pseq = $seq->translate();
            $seqout->write_seq($pseq);
    }
#此WHILE应该是多线程的

    while( (my $seq = $seqin->next_seq()) ) {
            my $pseq = $seq->translate();
            $seqout->write_seq($pseq);
    }
        sleep 1 if 0.2 > rand;
    }
    print "Thread done.\n";
    return;
}
print "\n$time\n";
my $time = localtime;
print "$time\n";
#此WHILE应该是多线程的

    while( (my $seq = $seqin->next_seq()) ) {
            my $pseq = $seq->translate();
            $seqout->write_seq($pseq);
    }
        sleep 1 if 0.2 > rand;
    }
    print "Thread done.\n";
    return;
}
print "\n$time\n";
my $time = localtime;
print "$time\n";
正在创建线程,但不知何故它无法处理fasta文件。
第一个代码在没有多线程的情况下运行良好。

我恐怕不会为您重写代码,但我可以给您一些如何完成线程的建议

关于perl线程,您需要了解的是它不是一个轻量级线程。您应该生成相当于并行度的线程数量,将它们从
Thread::Queue
中运行,然后从那里开始

您还需要避免使用任何非线程安全的模块-如果小心,您可以使用它们,但这通常意味着在程序开始时使用
require
import
在线程中实例化它们,而不是
use

我还建议避免并行执行输出IO—返回线程结果并在“主”线程中合并它们(必要时进行排序)(或派生出单个编写器)

所以我会选择这样的东西

#!/usr/bin/env perl

use strict;
use warnings;

use threads;

use Thread::Queue;
use Storable qw ( freeze thaw );

my $NUM_THREADS = 16;    #approx number of cores.

my $translate_q         = Thread::Queue->new;
my $translate_results_q = Thread::Queue->new;


sub translate_thread {
   while ( my $item = translate_q->dequeue ) {
      my $seq  = thaw $item;
      my $pseq = $seq->translate();
      $translate_results_q->enqueue( freeze $pseq );

   }

}

threads->create( \&translate_thread ) for 1 .. $NUM_THREADS;

while ( my $seq => $seqin->next_seq ) {
   $translate_q->enqueue( freeze($seq) );
}
$translate_q->end;

$_->join for threads->list;
$translate_results_q->end;

while ( my $result = $translate_results_q->dequeue ) {
   my $pseg = thaw($result);
}
注意-这不会按原样工作,因为它缺少与ocde其余部分的合并。但希望它能说明队列和线程如何工作以获得并行性

您可以使用Storable中的
冻结
解冻
传递对象,并使用并行性将其解包

不要在线程数量上太过疯狂-对于主要的计算工作负载(例如没有IO),那么线程数量等于核心数量就差不多了。如果他们在IO上阻塞,你可以增加这个数字,但超过大约两倍不会有多大作用


你不可能真正有效地并行磁盘IO,它就是不能那样工作。所以在“主”线程中这样做

谢谢,这是一个很好的建议@Sobrique。我将尝试使它与剩余的代码一起工作。