我正在通过此代码将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);
}
我实施 线程和 threads :: shared perl模块可以在其他情况下实现,但我想将以下代码应用于上一个任务
use threads;
use threads::shared;
use List::Util qw( sum );
use YAML;
use constant NUM_THREADS =>100;
my @output :shared;
my $chunk_size = @data / NUM_THREADS;
my @threads;
for my $chunk ( 1 .. NUM_THREADS ) {
my $start = ($chunk - 1) * $chunk_size;
push @threads, threads->create(
\&doOperation,
\@data,
$start,
($start + $chunk_size - 1),
\@output,
);
}
$_->join for @threads;
sub doOperation{
my ($data, $start, $end, $output) = @_;
my $id = threads->tid;
print "$id ";
for my $i ($start .. $end) {
print "Thread [$id] processing row $i\n";
#应该被多重理解
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文件。 fisrt代码可以在没有多线程的情况下正常工作。
答案 0 :(得分:2)
恐怕我不会为您重写代码,但是我可以为您提供一些有关如何完成线程化的指导。
关于perl线程,您需要了解的事情是不是轻量级线程。您应该产生与并行度相等的多个线程,将它们从Thread::Queue
处运行,然后从那里去。
您还需要避免使用任何非线程安全的模块-如果您对谨慎,可以使用它们,但这通常意味着使用require
和{{ 1}},而不是程序开始时的import
。
我还建议避免尝试并行执行输出IO-返回线程结果并在“主”线程中合并它们(如有必要,进行排序)(或分离一个编写器)。
所以我会选择类似的东西
use
注意-这无法按原样工作,因为它缺少与其余的ocde合并的功能。但是希望它能说明队列和线程如何工作以获取并行性?
您可以使用Storable中的#!/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);
}
和freeze
来传递对象,并使用并行性对其进行解压缩。
不要太着迷于线程数量-对于主要计算工作负载(例如,没有IO),那么等于内核数量的线程数量是正确的。如果他们将阻止IO,则可以增加这个数字,但是超过两倍几乎没有多大作用。
您不能真正有效地并行化磁盘IO-只是不能那样工作。在“主”线程中也是如此。