2012-01-23 7 views
0

私は同じサブルーチンを何回か連続して呼び出し、同じデータを処理し、呼び出しごとにコードが連続して長くなるという奇妙な問題があります。私のプログラムは行列の数学を行っていますが、誰かが同じ問題を抱えているかどうかをより一般的な質問で尋ねていますので、そのことが重要かどうかはわかりません。以下は私のメインプログラムのループの最下部にあるコードです。Perlサブルーチンが連続して呼び出されるたびに遅くなります

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データで動作します。私は各サブルーチンコール(正確には前回の検証)から全く同じ答えを得ているので、入力データが壊れていないことは分かっています。サブルーチンはシンプルなシングルスレッド構造でもあり、96GBのRAMを搭載したアイドル状態の12コアワークステーションで実行されます。このマシンはこの比較的小さなマトリックスを処理するのに十分なパワーを持っているので、ディスク交換またはCPUの問題はないはずです。しかし、このようなもので、プログラムの結果の出力(明らかに、サブルーチンの5つの連続呼び出しを実行している):

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

万が一、他にどこかでいっぱいになっているので、全体的なプログラムが遅くなっていますか? – Jarmund

+0

私は見てきましたが、唯一の他の変数は、他のサブルーチンでローカルに定義されているか、まったく最初に一度定義されてから再び触れられませんでした。私も各呼び出しの間に@blah_LU_v2行列を 'undef'しようとしましたが、それは良い結果をもたらしませんでした。 – user1164453

+0

'invert_LU_v2'実装を投稿してみませんか? – Zaid

答えて

3

使用Benchmarkたぶん問題ではありません、あなたのプログラムではなく、あなたのmeasurmentに

:-)ベンチマークを行うには?

デバッグにはDevel::NYTProfを使用してください。それはあなたに多くの有用な情報、タイミングなどを表示します。

+0

NYTProfは素晴らしいです。それはあなたの時間がどこに費やされているかを実際に示しています。 –

+0

私はBenchmarkモジュールを試してみました。結果は私のTime :: Hiresメソッドの時間と一致します。私はNYTProfをまだ試していませんが、次にこれを行います。助けてくれてありがとう! – user1164453

+0

NYTProfは本当に素晴らしいです。これは、サブルーチンの各呼び出しが、予想どおり正確に同じ数の '計算'を持つことを示しています。 2回目に呼び出されたときのサブルーチンの追加時間は、Math :: Complex :: _ multiplyとMath :: Complex :: _ minusに集中しています。これは、時間差の95%以上を占めています。上記のメインの質問に私のサブを含めましたが、そこにある問題が問題を引き起こしたり、これがMath :: Complexの問題ですか? – user1164453

関連する問題