2011-01-26 27 views
1

私は現在、100万行のテキストファイルを取得し、それを塊(1チャンクあたり50〜50,000行)に分解し、計算などを実行する必要のあるperlプログラムを実行していますそれらの上に。今、私はすべてのデータをarray1にロードします。私はarray2を取って、それを使って必要なデータだけを取り出します。次に、配列2で実行する必要がある操作を行い、次に戻って次のセットを取得します。大規模なperlの配列のスローダウン

例えばデータ

A、blah1、blah2

A、blah6、blah7

A、blah4、blah5

B、blah2、blah2

だからつかむであろう最初の3つは配列2に、並べ替え、次に次のセットに移動します。私のプログラムはかなりうまく、効率的に動作しますが、後で深刻な減速を経験します。

50Kは50秒かかり、100Kは184秒かかり、150Kが200Kは581秒かかり、360秒かかり、それが唯一のプログラムは、(ライン500Kで4500秒)続けて指数関数的に悪化する

いいえ、私は使用できません。このプロジェクトのデータベース、任意の提案?

my @Rows1=<FILE>; 
my $temp = @Rows1; 
for($k = 0; $k < $temp; $k++) 
{ 
    my @temp2array =(); 
    my $temp2count = 0; 
    my $thisrow = $Rows1[$k]; 
    my @thisarray = split(',', $thisrow); 
    my $currcode = $thisarray[0]; 
    my $flag123 = 0; 
    $temp2array[$temp2count] = $thisrow; 
    $temp2count++; 
    while ($flag123 == 0) 
    { 
     $nextrow = $tuRows1[$k + 1]; 
     @nextarray = split(',', $nextrow); 
     if ($currcode eq $nextarray[0]) 
     { 
      $temp2array[$temp2count] = $nextrow; 
      $k++; 
      $temp2count++; 
     } 
     else 
     { 
      $flag123 = 1; 
     } 
    } 
} 

私はもっと下の答えに似ていると私のコードを編集した、と私はこれらの時間を持っている:

50K = 42、100K = 133、150K = 280、200K = 467、250K = 699 、300k = 978,350k = 1313

これは厳密に線形に保たれておらず、この傾向によって、このプログラムはまだ14000 +秒かかるでしょう。コードの他の部分を調べます。

+0

あなたのコードといくつかのサンプル入力がうまくいくでしょう。 – CanSpice

+0

少なくとも、ファイルからデータを取得し、独自の配列に格納するコードを入れるように質問を更新しました。それ以前のサンプルデータがあります。 30値のようなコンマで区切られた文字列です。 – ThePirateSheep

+0

@ tuRows1とは何ですか?それは@ Rows1であるはずですか? – ysth

答えて

2

大きなファイル全体をメモリに読み込むと、OSが仮想メモリのページのスワッピングを開始する必要があるため、速度が低下します。そのような場合は、必要なファイルのセクションのみを処理するのが最善です。あなたのケースでは

は、あなたが一緒に最初のフィールドに同じ値を持つ行を処理するように見えるので、あなたのような何かを行うことができます:

my @lines =(); 
my $current_key = ''; 

while (<FILE>) { 
    my ($key) = split /,/;  # get first column 
    if ($key ne $current_key) { 
     # new key. Process all the lines from the previous key. 
     if (@lines > 0) { 
      process(@lines); 
     } 
     @lines =(); 
     $current_key = $key; 
    } 
    push @lines, $_ 
} 
# don't forget the lines from the last key 
if (@lines > 0) { 
    process(@lines); 
} 

この方法は、あなただけのメモリに十分なラインに保存されています1つのグループを構成する。

(私は入力データがキーでソートされていると仮定していますが、そうでない場合、ファイルを複数回通過することができます:最初のパスで処理する必要があるキー、各キーに関連付けられた行を収集するために渡します)。

+0

ファイル自体は最初は最初の値でソートされているため、大きな問題ではありません。そして、ファイル全体をロードすることはコーディングのベストプラクティスではありませんが、なぜ既に読み込まれた後に大幅に減速するのか理解できません。しかし、私はこのようなものを試してみる – ThePirateSheep

+0

ロードされた後でさえ、大きなデータセットは数ページの仮想メモリに広がってしまいます。このデータにアクセスするにはページのスワッピングが必要となり、速度が低下します。 – mob

+0

私はあなたが提供したコードにもっと似ているように自分のコードを編集しました。ファイル全体を読み込むのではなく、行単位で引っ張って、使用する必要があるチャンクを別にしておくなど、今やもっと滑らかに走っていますが、まだ高速ではありません(私は知りませんが、待機時間の増加)。新しい時間は私の元の投稿で編集されます – ThePirateSheep

0

表示されているコードを実行しているだけで減速していますか?そうでなければ、実際に各@ temp2arrayチャンクを処理するコードに問題があります。おそらく、以前のチャンクからデータが残っている可能性があります。

関連する問題