Оптимизировать внешнюю команду Perl - PullRequest
1 голос
/ 14 сентября 2010

Можно ли как-нибудь оптимизировать следующий скрипт, чтобы он работал быстрее?

foreach my $arg (@data){ #  
   @score=();
   `program $arg $arg1 > $result`; #!!! $arg1 is a very large file with lots of data!!!
   open(FH,$result);
   while(<FH>){
      chomp;
      if($_ =~ /\d+.+\s+(\d+\.\d+|\d+\.|\.\d+).+/){ #here i'm looking for any number such as: 21.343 or 12 or 0.22 or -3.0
         push(@score, $1);
      }
   }
   close FH;
   @sorted = sort{$a <=> $b} @score; #a sorted score is what i actually want
}

Ответы [ 4 ]

5 голосов
/ 14 сентября 2010

Я могу видеть несколько вещей (например, не загружать ваш результат в файл сразу), но я подозреваю, что основное преимущество в производительности, которое вы получите, вероятно, будет от использования другого регулярного выражения. Для этого у вас есть лучшее представление о том, какой формат вывода данных из вашей программы?

Вот несколько примеров Perl, которые могут работать немного быстрее:

use strict;
foreach my $arg (@data){
  my @score=();
  open(my $fh, "program $arg $arg1 |");
  while (<$fh>) {
    chomp;
    if (/\d+.+\s+((\d+)?\.?\d+)/o) {
      push(@score, $1);
    }
  }
  close($fh);
  my @sorted = sort { $a <=> $b } @score;
}

Обратите внимание на несколько вещей:

  1. Я использую обработчик программного файла, поэтому я не использую временный файл, поэтому пропускаю весь проход данных.
  2. Я изменил регулярное выражение, чтобы использовать вложенные группы, а не несколько параметров.
  3. Я использую строгие и сохраняю названия пакетов (ради бога, используйте строгий в вашем perl).

Другие люди говорили, что используют темы. Вам НЕ нужно этого делать, так как выполнение процесса, как я делал с помощью завершающего канала (|) в функции open, заставляет perl форкнуть процесс для вас. Затем вы используете стандартные каналы Unix для асинхронного чтения из программы.

2 голосов
/ 14 сентября 2010

Вы профилировали свою программу?Без профилирования вы не знаете, сколько времени уходит во внешнюю программу или в вашу программу.

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

При этом, как сказал hlynur , вы, вероятно, могли бы распараллелить вызовы внешних программ, используя потоки.Вы также можете получить некоторые оптимизации с помощью другого регулярного выражения, но нет реального способа определить, сколько вы получите, не выполнив сначала профилирование.

2 голосов
/ 14 сентября 2010

Почему вы не можете просто запустить программу и передать результаты в ваш Perl-скрипт?

./program $arg $arg1 | myscript

На самом деле, вы, вероятно, могли бы полностью избавиться от Perl:

./program $arg $arg1 | grep /\d...whatever.../ | sort
0 голосов
/ 14 сентября 2010

Да, прежде всего: перенаправить вывод program в файл, а затем прочитать его - глупо и дорого. Почему не просто?

my @result = `program $arg $arg1`;
foreach(@result) {...

Во-вторых, вы можете распараллелить внешнее foreach . темы perldoc, темы :: общая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...