別のツール(overlapFeatures)をラップするperlスクリプトを作成して、ファイル形式をその場で正しく変換できるようにしました。私が扱っているファイルはすべて、通常200万行程度のタブ区切りのテーブルです。それ自体では、overlapFeaturesはこれらを問題なく処理できます。
しかし、一度にたくさんのラインを配管することで、パイプがロックしてしまうのではないかと思います。子プロセスの読み取りと書き込みを同時に行えるように、これをなんとかしてスレッド化する必要があることはわかっています。しかし、私はperl(またはその他のプログラム)でスレッドを適切に使用する方法を本当に理解していません。私はそれを理解しているので、問題を解決するために使用することthreads
もできます。IPC::run
デッドロックが発生する元のスクリプトは、次のようになります。
use strict;
use warnings;
use IPC::Open2;
my $infile = shift;
my $featurefile = shift;
my $command = 'overlapFeatures';
my @args = (qw (-a stdin -b), $featurefile);
my ($input, $output);
my $pid = open2($output, $input, $command, @args)
or die "Failed with error $!\n";
open (my $infh, '<', $infile) or die "Can't open $infile\n";
while (<$infh>){
# Do some format conversion...
chomp
my @cols = split /\t/;
# print a modified line to the tool
print $input join ("\t", @cols[0,2,3,1,5,4]),"\n";
}
close ($input);
while (<$output>){
# format conversion for ouput
chomp;
my @cols = split /\t/;
print join (",",@cols[0,1,2,5,3,8]),"\n";
}
close ($output);
IPC :: Open2で大量のデータをフィルタリングする方法に従って、スレッドを利用するようにスクリプトを書き直そうとしました。そのようです:
use strict;
use warnings;
use IPC::Open2;
use threads;
my $infile = shift;
my $featurefile = shift;
my $command = 'overlapFeatures';
my @args = (qw (-a stdin -b), $featurefile);
my ($input, $output);
my $pid = open2($output, $input, $command, @args)
or die "Failed with error $!\n";
my $thread = async {
print join(",", qw(seqid start end strand read feature name)),"\n";
for(;;) {
my $line = <$output>; # should block here and wait for output?
last if !defined $line; # end of stream reached?
print STDERR "Got line $line\n";
# Do some format conversion...
chomp $line;
my @cols = split /\t/, $line;
# print a modified line to the tool
print join(",",@cols[0,1,2,5,3,8]),"\n";
}
close($output)
};
{
open (my $infh, '<', $infile) or die "Can't open $infile\n";
while (<$infh>){
# format conversion for ouput
chomp;
my @cols = split /\t/;
print $input join ("\t", @cols[0,2,3,1,5,4]),"\n";
}
close ($input);
}
$thread->join();
waitpid ($pid, 0);
ただし、スクリプトは同じようにスタックし、私もスタックします。この場合の使い方もわかりませんIPC::run
。
私は何が間違っているのですか?糸脱毛を誤解しましたか?
編集:スクリプトのデバッグ(およびamonの支援)により多くの時間を費やして、から行を取得できることがわかりました$output
。ただし、スクリプトは終了せず、すべての出力が受信された後、ハングしているように見えます。これが私の唯一の問題だと思います。