2010-12-13 14 views
6

Xin chào, tôi có một tập lệnh đơn giản có một tệp và chạy một tập lệnh Perl khác trên đó. Tập lệnh thực hiện điều này với mọi tệp hình ảnh trong thư mục hiện tại. Điều này đang chạy trên một máy với 2 bộ xử lý Xeon lõi tứ, 16GB ram, chạy RedHat Linux.Làm cách nào để sửa đổi tập lệnh perl của tôi để sử dụng nhiều bộ xử lý?

Kịch bản lệnh work.pl đầu tiên về cơ bản gọi magicplate.pl chuyển một số tham số và tên của tệp cho magicplate.pl để xử lý. Magic Plate mất khoảng một phút để xử lý từng hình ảnh. Bởi vì work.pl là preforming chức năng tương tự hơn 100 lần và bởi vì hệ thống có nhiều bộ vi xử lý và lõi tôi đã suy nghĩ về tách nhiệm vụ lên để nó có thể chạy nhiều lần song song. Tôi có thể chia hình ảnh lên các thư mục khác nhau nếu cần. Bất kỳ sự trợ giúp nào đều sẽ là tuyệt vời. Cảm ơn bạn

Dưới đây là những gì tôi có cho đến nay:

use strict; 
use warnings; 


my @initialImages = <*>; 

foreach my $file (@initialImages) { 

    if($file =~ /.png/){ 
     print "processing $file...\n"; 
     my @tmp=split(/\./,$file); 
     my $name=""; 
     for(my $i=0;$i<(@tmp-1);$i++) { 
      if($name eq "") { $name = $tmp[$i]; } else { $name=$name.".".$tmp[$i];} 
     } 

     my $exten=$tmp[(@tmp-1)]; 
     my $orig=$name.".".$exten; 

     system("perl magicPlate.pl -i ".$orig." -min 4 -max 160 -d 1"); 
    } 
}  

Trả lời

3

Bạn có thể sử dụng song song :: ForkManager (đặt $ MAX_PROCESSES tới số lượng tập tin xử lý cùng một lúc):

use Parallel::ForkManager; 
use strict; 
use warnings; 

my @initialImages = <*>; 

foreach my $file (@initialImages) { 

    if($file =~ /.png/){ 
     print "processing $file...\n"; 
     my @tmp=split(/\./,$file); 
     my $name=""; 
     for(my $i=0;$i<(@tmp-1);$i++) { 
      if($name eq "") { $name = $tmp[$i]; } else { $name=$name.".".$tmp[$i];} 
     } 

     my $exten=$tmp[(@tmp-1)]; 
     my $orig=$name.".".$exten; 

    $pm = new Parallel::ForkManager($MAX_PROCESSES); 
    my $pid = $pm->start and next; 
     system("perl magicPlate.pl -i ".$orig." -min 4 -max 160 -d 1"); 
    $pm->finish; # Terminates the child process 

    } 
}  

Nhưng theo đề nghị của Hugmeir chạy thông dịch perl một lần nữa và một lần nữa cho mỗi tập tin mới không phải là một ý tưởng hay.

+2

"chạy thông dịch viên perl một lần nữa và một lần nữa cho mỗi tập tin mới không phải là một ý tưởng tốt" - Có, nhưng khi bạn ngã ba, bạn không bắt đầu một thông dịch viên perl mới. Fork sao chép tiến trình cha, và Linux sử dụng CoW, vì vậy nó thậm chí còn rẻ hơn một bản sao đầy đủ. – JimB

+2

Ngoài ra, tại sao bạn bắt đầu một thông dịch viên mới sau khi ngã ba? Chạy mã perl trong tiến trình con mới. – JimB

+0

@JimB: Tôi có nghĩa là cuộc gọi hệ thống không phải forking. Và tôi sử dụng cuộc gọi hệ thống vì mã ban đầu đã sử dụng nó. – gangabass

7

Bạn nên cân nhắc KHÔNG tạo ra một quy trình mới cho mỗi tập tin mà bạn muốn xử lý - Đó là khủng khiếp không hiệu quả, và có lẽ những gì đang diễn hầu hết thời gian của bạn ở đây. Chỉ cần tải lên Perl và bất kỳ mô-đun bạn sử dụng hơn và hơn nên được tạo ra một số chi phí. Tôi nhớ lại một áp phích trên PerlMonks đã làm điều gì đó tương tự và kết thúc việc chuyển kịch bản lệnh thứ hai của mình thành một mô-đun, giảm thời gian làm việc từ một giờ xuống còn một số phút. Không phải là bạn nên mong đợi một sự cải thiện đáng kể, nhưng người ta có thể mơ ước ..

Với tập lệnh thứ hai được cấu trúc lại thành một mô-đun, here's an example of thread usage, trong đó BrowserUK tạo ra một hồ bơi chủ đề.

+5

Bắt đầu một trình thông dịch perl mới là khủng khiếp không hiệu quả, nhưng việc tạo một quy trình mới với fork() rất nhanh (đặc biệt là khi Linux sử dụng CoW). – JimB

+2

No. Nếu công việc của bạn sẽ sử dụng 1 phút của thời gian CPU, thời gian dành cho việc khởi động nhiệm vụ mới sẽ khá đáng kể.Perl có thể sử dụng, ví dụ, 1 giây của CPU để khởi động môi trường của nó (nếu bạn có khá nhiều mô-đun được tải; tôi đã thấy điều này) nhưng sau đó, đó là tất cả của bạn. Đọc kỹ câu hỏi. – MarkR

+1

NB: Perl chủ đề hút. Thực sự, họ làm. Họ tạo ra vô số bản sao của tất cả mọi thứ (không phải bản sao CoW, bản sao thực). Chúng không hoạt động ngay trong một số trường hợp, nhưng vẫn sử dụng hết đống tài nguyên không cần thiết. Ngã ba thay vào đó, đó là cách hiệu quả hơn và có nhiều khả năng để làm việc. – MarkR

3
  • Nhập "maigcplate" và sử dụng luồng.
  • Bắt đầu magicplate.pl ở chế độ nền (bạn sẽ cần phải thêm quá trình throttling)
  • Nhập "magicplate" và sử dụng fork (thêm quá trình điều tiết và gặt Kiddy)
  • Make "maigcplate" một daemon với một hồ bơi công nhân = # CPU
    • sử dụng một thực hiện MQ để liên lạc
    • ổ cắm sử dụng để liên lạc
  • sử dụng máy chủ web (nginx, apache, ...) và quấn trong REST cho một webservice
  • etc ...

Tất cả các trung tâm này tạo ra nhiều công nhân có thể chạy trên cpu của chính họ. Một số triển khai nhất định sẽ sử dụng tài nguyên tốt hơn (những tài nguyên không bắt đầu một quy trình mới) và dễ triển khai và duy trì hơn.