gpt4 book ai didi

performance - 为什么我的程序使用 Tie::File 运行得这么慢?

转载 作者:行者123 更新时间:2023-12-04 03:13:27 27 4
gpt4 key购买 nike

#!/usr/bin/perl
use strict;
use warnings;
use Tie::File;
use Data::Dumper;
use Benchmark;

my $t0 = Benchmark->new;

# all files in the current folder with $ext will be input.
# Default $ext is "pileup"
# if entered, second user entered input will be set to $ext
my $ext = "pileup";
if(exists $ARGV[1]) {
$ext = $ARGV[1];
}

# open current directory & store filenames with $ext into @pileupfiles
opendir (DIR, ".");
my @pileupfiles = grep {-f && /\.$ext$/} readdir DIR;

my $dnasegment;
my $pos;
my $total;
my $g_total;
my @index; #hold current index for each tied file
my @totalfiles; #hold total files in each sub-index

# $filenum is iterator to cycle through all pileup files whose names are stored in pileupfiles
my $filenum = 0;
# @tied is an array holding all arrays of tied files
my @tied;
# array of the current line number for each @file,
my @linenum;
# tie each file to an array that is an element of the @tied array
while($filenum < scalar @pileupfiles) {
my @file;
tie @file, 'Tie::File', $pileupfiles[$filenum], recsep => "\n" or die;
push(@tied, [@file]);
# set each line's value of $linenum to 0
push(@linenum, 0);
$filenum++;
}

# open user list of dnasegments
open(LIST, $ARGV[0]);
# open file for output
open(OUT, ">>tempfile.tab");

while(<LIST>) {
$dnasegment = $_;
chomp $dnasegment;

my $exit = 0;
$pos = 1;
my %flag;

while(scalar(keys %flag) < scalar @tied) {
$total = 0;
$filenum = 0;
while($filenum < scalar @tied) {
if(exists $tied[$filenum][$linenum[$filenum]]) {
my @line = split(/\t/, $tied[$filenum][$linenum[$filenum]]);
#print $line[0], "\t", $line[1], "\t", $line[3], "\n\n";
if($line[0] eq $dnasegment) {
if($line[1] == $pos) {
$total += $line[3];
$linenum[$filenum]++;
$g_total += $line[3];
print OUT "$dnasegment\t$filenum\t$pos\t$line[3]\n";
}
} else {
$flag{$filenum} = 1;
}
} else {
#print $flag, "\n";
$flag{$filenum} = 1;
}
$filenum++;
}
if($total > 0) {
print OUT "$dnasegment\t$total\n";
}
$pos++;
}
}

close (LIST);
close(OUT);

my $t1 = Benchmark->new;
my $td = timediff($t1, $t0);
print timestr($td), "\n";

以上代码获取目录中所有具有默认或用户输入的文件扩展名的文件,并计算特定条目(输入文件的第 1 列)的位置(输入文件的第 2 列)的总出现次数输入文件,其中第 1 列与命令行提供的文件中包含的名称相匹配)。程序要使用的文件布局是:文件 1:

    Gm02    11896804    G   2   .,  \'
Gm02 11896805 G 7 ......, U`
Gm02 11896806 G 3 .,. Sa
Gm02 11896807 T 2 ., U\
Gm02 11896808 T 2 ., ZZ
Gm02 11896809 T 2 ., ZZ
Gm02 11896810 T 2 ., B\
Gm02 11896811 G 3 .,^!, B]E
Gm02 11896812 A 3 T,, BaR
Gm02 11896822 G 3 .,, B`D

文件 2:

    Gm02    11896804    G   3   .,, \'
Gm02 11896805 G 7 ......, U`
Gm02 11896806 G 3 .,. Sa
Gm02 11896807 T 2 ., U\
Gm02 11896808 T 2 ., ZZ
Gm02 11896809 T 2 ., ZZ
Gm02 11896810 T 2 ., B\
Gm02 11896811 G 3 .,^!, B]E
Gm02 11896812 A 3 T,, BaR
Gm02 11896813 G 3 .,, B`D

文件 3:

    Gm02    11896804    G   3   .,, \'
Gm02 11896805 G 7 ......, U`
Gm02 11896806 G 3 .,. Sa
Gm02 11896807 T 2 ., U\
Gm02 11896808 T 2 ., ZZ
Gm02 11896809 T 2 ., ZZ
Gm02 11896810 T 2 ., B\
Gm02 11896811 G 3 .,^!, B]E
Gm02 11896812 A 3 T,, BaR
Gm02 11896833 G 3 .,, B`D

在这种情况下,传递给程序的唯一命令行参数将是一个以“Gm02”为内容的文本文件。

散列用于跟踪已经处理过的位置。在上面的示例文件中,在遇到位置 11896804 处的第一个值之前,将检查所有三个文件以从位置 1 到 11896803 计数。这是为了确保在递增位置之前检查所有文件中的所有位置并求和。

我的问题与性能有关。我决定使用 Tie::File 是因为我认为这会提高性能,因为所有文件都不会读入内存。程序要处理的实际数据是数十万行的长度乘以数十个文件。此时,单独运行示例文件 1 和所有 3 个示例文件所花费的时间分别为 42 秒(41.96 usr + 0.00 sys = 41.96 CPU)和 110 秒(109.76 usr + 0.00 sys = 109.76 CPU)。非常感谢任何关于为什么这个程序运行如此缓慢的信息或关于如何加速它的建议。

编辑美国东部时间晚上 10:17:程序的输出如下:

Gm02    0   11896804    2
Gm02 1 11896804 3
Gm02 2 11896804 3
Gm02 8
Gm02 0 11896805 7
Gm02 1 11896805 7
Gm02 2 11896805 7
Gm02 21
Gm02 0 11896806 3
Gm02 1 11896806 3
Gm02 2 11896806 3
Gm02 9
Gm02 0 11896807 2
Gm02 1 11896807 2
Gm02 2 11896807 2
Gm02 6
Gm02 0 11896808 2
Gm02 1 11896808 2
Gm02 2 11896808 2
Gm02 6
Gm02 0 11896809 2
Gm02 1 11896809 2
Gm02 2 11896809 2
Gm02 6
Gm02 0 11896810 2
Gm02 1 11896810 2
Gm02 2 11896810 2
Gm02 6
Gm02 0 11896811 3
Gm02 1 11896811 3
Gm02 2 11896811 3
Gm02 9
Gm02 0 11896812 3
Gm02 1 11896812 3
Gm02 2 11896812 3
Gm02 9
Gm02 1 11896813 3
Gm02 3
Gm02 0 11896822 3
Gm02 3
Gm02 2 11896833 3
Gm02 3
Gm02 0 11896804 2
Gm02 1 11896804 3
Gm02 5
Gm02 0 11896805 7
Gm02 1 11896805 7
Gm02 14
Gm02 0 11896806 3
Gm02 1 11896806 3
Gm02 6
Gm02 0 11896807 2
Gm02 1 11896807 2
Gm02 4
Gm02 0 11896808 2
Gm02 1 11896808 2
Gm02 4
Gm02 0 11896809 2
Gm02 1 11896809 2
Gm02 4
Gm02 0 11896810 2
Gm02 1 11896810 2
Gm02 4
Gm02 0 11896811 3
Gm02 1 11896811 3
Gm02 6
Gm02 0 11896812 3
Gm02 1 11896812 3
Gm02 6
Gm02 1 11896813 3
Gm02 3
Gm02 0 11896822 3
Gm02 3
Gm02 0 11896804 2
Gm02 2
Gm02 0 11896805 7
Gm02 7
Gm02 0 11896806 3
Gm02 3
Gm02 0 11896807 2
Gm02 2
Gm02 0 11896808 2
Gm02 2
Gm02 0 11896809 2
Gm02 2
Gm02 0 11896810 2
Gm02 2
Gm02 0 11896811 3
Gm02 3
Gm02 0 11896812 3
Gm02 3
Gm02 0 11896822 3
Gm02 3

最佳答案

我会说“因为您正在使用 Tie::File”,除非您不在以下代码行之外:

my @file;
tie @file, 'Tie::File', $pileupfiles[$filenum], recsep => "\n" or die;
push(@tied, [@file]);

你也可以这样写

open(my $fh, '<', $pileupfiles[$filenum]) or die $!;
push(@tied, [ <$fh> ]);

也许你的意思是

tie my @file, 'Tie::File', $pileupfiles[$filenum], recsep => "\n"  or die;
push(@tied, \@file);

然后我们会回到我原来的答案。 Tie::File 在某些情况下可能会减少开发时间,但它不会是目前最快的解决方案,而且它可能会使用所需的更多内存。


顺便说一下,exist 对数组元素没有意义。

if (exists $tied[$filenum][$linenum[$filenum]])

是一种糟糕的做法

if (defined $tied[$filenum][$linenum[$filenum]])

if ($linenum[$filenum] < @{ $tied[$filenum] })

关于performance - 为什么我的程序使用 Tie::File 运行得这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14820666/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com