2012-11-07 3 views
1

디렉토리를 스캔하고 imgsize http://dktools.sourceforge.net/imgsize.html을 사용하여 작업하는 펄 스크립트가 png 파일의 너비 등을 가져옵니다. 누구든지이 프로세스의 속도를 높이는 데 도움이되는 조언이 있습니까 (현재 1000 개 파일 당 평균 5 분). 코드가 어떻게 최적화 될 수 있는지 궁금합니다. 감사.펄에서 foreach 루프를 가속화합니다.

use strict; 
use warnings; 

use File::Find; 

my @files; 
my $directory = '/Graphics/'; 
my $output_file = '/output_file'; 
my $max_height = 555; 
my $count = 0; 

open (OUTPUT, '>>', $output_file); 

find(\&wanted, $directory); 

foreach my $file (@files) { 
     if ($file =~ /\.png$/) { 
       my $height = `imgsize $file | cut -d\'\"\' -f4`; 
       if ($height > $max_height) { 
         print OUTPUT "$file\n"; 
       } 

       $count++; 

       my $int_check = $count/1000; 
       if ($int_check !~ /\D/) { 
         print "processed: $count\n"; 
       } 
     } 
} 

print "total: $count\n"; 
close (OUTPUT); 
exit; 

sub wanted { 
    push @files, $File::Find::name; 
    return; 
} 

솔루션 : 나는이 Image::Info 모듈을 사용 할 수 있었다고 밝혀졌습니다. 나는 매 5 분마다 1000 개의 img를 처리 할 때마다 12 초으로 갔다. 관심있는 사람이 있으면 관련 코드 스 니펫을 참조하십시오.

use Image::Info qw(image_info); 

    foreach my $file (@files) { 
      if ($file =~ /\.png$/) { 
        my $output = image_info($file); 
        my $height = ${$output}{height}; 

        if ($height > $max_height) { 
          print OUTPUT "$file\n"; 
        } 

        $count++; 

        my $int_check = $count/1000; 
        if ($int_check !~ /\D/) { 
          print "processed: $count\n"; 
        } 
      } 
    } 
+4

스크립트를 프로파일 링 했습니까? [DeveL :: NYTProf] (http://p3rl.org/Devel::NYTProf)는 프로파일 링에 유용합니다. – choroba

+0

병목 현상이'imgsize' 어플리케이션이라고 가정합니다. 병렬로 여러 인스턴스를 실행할 수도 있습니다. 예를 들어 [Parallel :: ForkManager] (http : // p3rl/Parallel :: ForkManager)를 참조하십시오. – ElPaco

+0

고맙습니다. @choroba 내가 살펴볼 것입니다. –

답변

8

표시 한 Perl 코드는 범인이 아닙니다. @choroba가 말했듯이 Devel::NYTProf으로 프로파일 링 할 수 있습니다. 그러나 대부분의 시간은 이미지 당 두 개의 외부 프로세스 (imgsizecut)를 포크하는 것으로부터 얻을 수 있습니다. 외부 프로세스를 실행하지 않고 이미지의 높이를 검색 할 수있는 Perl 모듈을 조사해야합니다. Image::Info과 같은 모듈이 떠오른다.

+0

예, 아마도 다른 모듈을 조사해야합니다. 내가 언급하지 못한 한 가지 주름은 Image :: Info의 가능성을 무효로하는 메타 데이터가이 이미지에 포함되어 있지 않다는 것입니다. –

+1

'Image :: Info'가 어떻게 내부적으로 작동하는지 모르지만 각각의 모든 이미지는 적어도 그 크기가 헤더에 저장되어 있어야합니다. 그렇지 않으면 디코딩 할 수 없습니다 (정보가 외부에 저장되어 있지 않은 경우, 그렇지 않은 경우). 그래서'Image :: Info'가 당신의 이미지에 대해 작동하지 않는다면 다른 사람들은 여전히 ​​그 필수 헤더들을 파싱 할 수 있어야합니다. –

+0

아, 이미지에 대해 알지 못했습니다. 추가 정보를 제공해 주셔서 감사합니다. –

2

일반적으로 외부 프로세스를 루프로 실행하면 상황을 천천히 진행할 수 있습니다. 다른 프로세스를 시작하는 데 상당한 비용이 들며, 모든 이미지에 대해이를 수행하는 경우 비용을 꽤 빨리 알아 차릴 것입니다. 또한 cut을 호출합니다. 즉, 루프를 통해 매번 두 번 호출됩니다.

첫 번째 단계는 cut이 원시 Perl 문자열 연산을 사용하므로 조작 당 하나의 루프 당 하나의 프로세스 시작을 제거하는 것입니다.

불행히도 프로세스 비용을 완전히 없애는 유일한 방법은 모든 것을 처리하는 것입니다. 즉, 이미지를 읽고 크기를 얻을 수있는 Perl에서 호출 할 수있는 라이브러리가 필요하다는 것을 의미합니다. 나는 그것을 시도하지 않았다. 그러나 Perl::ImageMagick는보고 가치가 있을지도 모른다. 그리고 나는 다른 것이있을 것이라고 확신한다.

자신의 프로세스를 fork 또는 스레드로 분할하고 각 하위가로드의 일부를 병렬로 처리하도록 시도 할 수도 있지만 시스템에서 I/O 가용성 문제가 발생할 수 있습니다.

+0

Matthew에게 감사하지만, Perl :: ImageMagick을 사용할 수 없지만 분명히 다른 모듈을 조사 할 수 있습니다. –

관련 문제