私は同じサブルーチンを何回か連続して呼び出し、同じデータを処理し、呼び出しごとにコードが連続して長くなるという奇妙な問題があります。私のプログラムは行列の数学を行っていますが、誰かが同じ問題を抱えているかどうかをより一般的な質問で尋ねていますので、そのことが重要かどうかはわかりません。以下は私のメインプログラムのループの最下部にあるコードです。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);
}
万が一、他にどこかでいっぱいになっているので、全体的なプログラムが遅くなっていますか? – Jarmund
私は見てきましたが、唯一の他の変数は、他のサブルーチンでローカルに定義されているか、まったく最初に一度定義されてから再び触れられませんでした。私も各呼び出しの間に@blah_LU_v2行列を 'undef'しようとしましたが、それは良い結果をもたらしませんでした。 – user1164453
'invert_LU_v2'実装を投稿してみませんか? – Zaid