1

同じコードの @solved C# は 2 倍高速です

perl で phred33 fastq ファイルを解析していますが、かなりの時間がかかります (15 分程度)。fastq ファイルは約 3 GB です。これを高速化する合理的な方法はありますか?

$file=shift;
open(FILE,$file);
open(FILEFA,">".$file.".fa");
open(FILEQA,">".$file.".qual");
while($line=<FILE>)
{
    chomp($line);
    if($line=~m/^@/)
    {


    $header=$line;
    $header =~ s/@/>/g;
    $seq=<FILE>;
    chomp($seq);
    $nothing=<FILE>;
    $nothing="";
    $fastq=<FILE>;

    print FILEFA $header."\n";
    print FILEFA $seq."\n";
    $seq="";
    print FILEQA $header."\n";

        @elm=split("",$fastq);
        $i=0;
        while(defined($elm[$i]))
        {
            $Q = ord($elm[$i]) - 33;
            if($Q!="-23")
            {
            print FILEQA $Q." ";
            }
            $i=$i+1;
        }
        print FILEQA "\n";
    }
}
print $file.".fa\n";
print $file.".qual\n";
4

1 に答える 1

1

ここで使用されている CPU はほとんどありません。これは IO バウンドであるため、ほとんどの場合、3 GB を読み取る必要があります。実行できるマイクロ最適化 (およびその他のクリーンアップ) があります。

まず、常に使用しますuse strict; use warnings;

メインコードは

my @elm = split(//, $fastq);
my $i=0;
while(defined($elm[$i])) {
    my $Q = ord($elm[$i]) - 33;
    if($Q!="-23") {
        print FILEQA $Q." ";
    }
    $i=$i+1;
}

の目的はif($Q!="-23")、文字が改行かどうかを確認することですchomp($fastq);。(周りの引用符は何-23ですか?!)

chomp($fastq);
my @elm = split(//, $fastq);
my $i=0;
while(defined($elm[$i])) {
    my $Q = ord($elm[$i]) - 33;
    print FILEQA $Q." ";
    $i=$i+1;
}
print FILEQA "\n";

ループを使用すると、while物事が複雑になります。反復回数がわかっている場合は、for ループを使用します。

chomp($fastq);
for (split(//, $fastq)) {
    print FILEQA (ord($_)-33)." ";
}
print FILEQA "\n";

それを裏返しにすることは少し役立つかもしれません。

chomp($fastq);
print FILEQA join(' ', map ord($_)-33, split //, $fastq), "\n";

よく考えてみると、裏返しでは十分ではありません:)

$fastq =~ s/(.)/(ord($1)-33) . " "/eg;
print FILEQA $fastq;

しかし、翻訳を事前に計算したのは何ですか? そうすれば、サブ (/eコード) を繰り返し呼び出す必要がなくなります。

my %map = map { chr($_) => ($_-33)." " } 0x00..0xFF;

$fastq =~ s/(.)/$map{$1}/g;
print FILEQA $fastq;

もう少しクリーンアップすると、次のようになります。

use strict;
use warnings;

my %map = map { chr($_) => ($_-33)." " } 0x00..0xFF;

my $file = shift;

my $fa_file   = "$file.fa";
my $qual_file = "$file.qual";

open(my $FILE,   '<', $file     ) or die $!;
open(my $FILEFA, '>', $fa_file  ) or die $!;
open(my $FILEQA, '>', $qual_file) or die $!;

while (my $header = <$FILE>) {
    next if $header !~ /^@/;

    my $seq = <$FILE>;
    <$FILE>;
    my $fastq = <$FILE>;

    $header =~ s/@/>/g;
    $fastq =~ s/(.)/$map{$1}/g;

    print $FILEFA $header;
    print $FILEFA $seq;

    print $FILEQA $header;
    print $FILEQA $fastq;
}

print "$fa_file\n";
print "$qual_file\n";
于 2012-04-24T21:55:09.080 に答える