Perl子程序随着每次连续调用运行得更慢

时间:2012-01-23 07:26:29

标签: perl benchmarking

我有一个奇怪的问题,我连续几次调用相同的子程序,处理相同的数据,每次调用我的代码连续更长。我的程序正在做一些矩阵数学,但我在这里问一个更普遍的问题,看看是否有人有同样的问题,所以我不知道具体细节是否重要。下面是我的主程序循环最底层的代码。

use Time::HiRes qw (gettimeofday);

($lus2_sec,$lus2_usec) = gettimeofday();
@blah_LU_v2 = invert_LU_v2(@zmatrix);
($lue2_sec,$lue2_usec) = gettimeofday();
$lu2_elapsed = sprintf("%.3f", ($lue2_sec+($lue2_usec/1000000))-($lus2_sec+($lus2_usec/1000000)));
syswrite STDOUT, "$lu2_elapsed seconds\n";

($lus2_sec,$lus2_usec) = gettimeofday();
@blah_LU_v2 = invert_LU_v2(@zmatrix);
($lue2_sec,$lue2_usec) = gettimeofday();
$lu2_elapsed = sprintf("%.3f", ($lue2_sec+($lue2_usec/1000000))-($lus2_sec+($lus2_usec/1000000)));
syswrite STDOUT, "$lu2_elapsed seconds\n";

每个子程序都在相同的@zmatrix数据上运行,它不会改变。我从每个子程序调用得到了完全相同的答案(之前验证过),所以我知道它并没有搞砸输入数据。子程序也是一个简单的单线程结构,它运行在一个空闲的12核工作站上,内存为96GB。应该没有磁盘交换或CPU问题,因为这台机器有足够的功率来处理这个相对较小的矩阵。但是,程序的输出会产生类似的结果(显然会运行子程序的五次连续调用):

96.485 seconds
99.116 seconds
100.036 seconds
100.615 seconds
101.494 seconds

对于我运行的尽可能多的测试,子程序会慢一点。如果我从命令行终止并重新启动程序,它将在大约96秒后开始,然后每次从那里开始减速。为什么会这样放慢速度?

有问题的子程序如下所示。请注意,我现在使用NYTProf来确定调用Math :: Complex :: _ multiply和_minus的时间。每次调用invert_LU_v2子例程时,它都会对Math :: Complex进行相同数量的调用,但在后续的invert_LU_v2调用中,它们会花费几个百分点。请随意批评我的代码,让我知道我还有什么问题。我是初学者,没有受过训练,也不知道我在做什么。

sub invert_LU_v2 {
    my(@junk) = (@_);
    my @matrix_local;
    my @matrix_L;
    my @matrix_B;
    my @matrix_inverse;

    my $tt;
    my $row;
    my $col;
    my $temp;
    my $reduced;
    my $normalize = 1;
    my $multiplier = 1;
    my $dimension = @junk - 1;

    for($row=1;$row<=$dimension;$row++){
        for($col=1;$col<=$dimension;$col++){
            $matrix_local[$row][$col]=$junk[$row][$col];
        }
    }

    for($row=1;$row<=$dimension;$row++){
        for($col=1;$col<=$dimension;$col++){
            if($row==$col){$matrix_L[$row][$col] = 1;$matrix_B[$row][$col] = 1;}
            else {$matrix_L[$row][$col] = 0;$matrix_B[$row][$col] = 0;}
        }
    }

    for($row=1;$row<=$dimension;$row++){

        $normalize = $matrix_local[$row][$row];
        $matrix_L[$row][$row] = $normalize;             
        for($col=1;$col<=$dimension;$col++){
            $matrix_local[$row][$col] /= $normalize;
        }

        for($temp=$row+1;$temp<=$dimension;$temp++){
            if(($temp != $row) && (abs($matrix_local[$temp][$row]) != 0)){
                $multiplier = $matrix_local[$temp][$row];
                $matrix_L[$temp][$row] = $multiplier;
                for($col=$row;$col<=$dimension;$col++){
                    $reduced = $matrix_local[$temp][$col] - $matrix_local[$row][$col]*$multiplier;
                    $matrix_local[$temp][$col] = $reduced;
                }
            }
        }
    }

    my @y_intermediate;

    for($col=1;$col<=$dimension;$col++){$y_intermediate[1][$col] = $matrix_B[1][$col]/$matrix_L[1][1]}

    for($col=1;$col<=$dimension;$col++){
        for($row=2;$row<=$dimension;$row++){
            $y_intermediate[$row][$col] = $matrix_B[$row][$col];
            for($tt=1;$tt<=($row-1);$tt++){$y_intermediate[$row][$col] -= ($matrix_L[$row][$tt]*$y_intermediate[$tt][$col])}
            $y_intermediate[$row][$col] /= $matrix_L[$row][$row];
        }
    }

    for($col=1;$col<=$dimension;$col++){$matrix_inverse[$dimension][$col] = $y_intermediate[$dimension][$col]/$matrix_local[$dimension][$dimension]}

    for($col=1;$col<=$dimension;$col++){
        for($row=($dimension-1);$row>=1;$row--){
            $matrix_inverse[$row][$col] = $y_intermediate[$row][$col];
            for($tt=($row+1);$tt<=$dimension;$tt++){$matrix_inverse[$row][$col] -= ($matrix_local[$row][$tt]*$matrix_inverse[$tt][$col])}
            $matrix_inverse[$row][$col] /= $matrix_local[$row][$row];
        }
    }

    return(@matrix_inverse);
}

1 个答案:

答案 0 :(得分:3)

使用Benchmark进行基准测试: - )

也许问题不在您的计划中,而在于您的测量?

使用Devel::NYTProf进行调试。它会向您显示许多有用的信息,时间等。