Подпрограмма Perl работает медленнее с каждым последующим вызовом - PullRequest
0 голосов
/ 23 января 2012

У меня странная проблема, когда я вызываю одну и ту же подпрограмму несколько раз подряд, обрабатывая одни и те же данные, и мой код занимает больше времени при каждом вызове. Моя программа выполняет некоторую матричную математику, но я задаю здесь более общий вопрос, чтобы увидеть, есть ли у кого-то такая же проблема, поэтому я не знаю, важны ли особенности. Ниже приведен код в самом низу моего основного цикла программы.

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-ядерной рабочей станции с 96 ГБ ОЗУ. Там не должно быть никакого обмена диска или проблемы с процессором, так как эта машина имеет более чем достаточно мощности для обработки этой относительно небольшой матрицы. Однако вывод программы приводит к чему-то вроде этого (очевидно, выполняется пять последовательных вызовов подпрограммы):

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 Ответ

3 голосов
/ 23 января 2012

Используйте Benchmark , чтобы сделать тесты: -)

Может быть, проблема не в вашей программе, а в ваших измерениях?

Используйте Devel :: NYTProf для отладки. Он покажет вам много полезной информации, времени и т. Д.

...