Lệnh của bạn thực sự kết thúc với điều này:
convert -size 600x400 xc:none \
\( 1.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 2.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 3.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 4.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 5.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 6.png -fill rgb\(x,y,z\) -colorize 100% \) -composite \
result.png
Suy nghĩ của tôi như sau:
Điểm 1:
-composite
đầu tiên lên một canvas trống có vẻ vô nghĩa - có lẽ là 1.png
là PNG 600x400 với độ trong suốt, vì vậy dòng đầu tiên của bạn có thể tránh thao tác tổng hợp và tiết kiệm 16% thời gian xử lý bằng cách thay đổi thành:
convert -background none 1.png -fill ... -colorize 100% \
\( 2.png ..
\( 3.png ...
Điểm 2
Tôi đặt lệnh tương đương của bạn vào một vòng lặp và thực hiện 100 lần lặp và mất 15 giây. Sau đó, tôi đã thay đổi tất cả các lần đọc tệp PNG của bạn thành lần đọc MPC
tệp - hoặc tệp Magick Pixel Cache. Điều đó đã giảm thời gian xử lý xuống chỉ còn dưới 10 giây, tức là 33%. Magic Pixel Cache chỉ là một tệp được giải nén trước, được giải mã trước, có thể được đọc trực tiếp vào bộ nhớ mà không cần bất kỳ nỗ lực nào của CPU. Bạn có thể tạo trước chúng bất cứ khi nào danh mục của bạn thay đổi và lưu trữ chúng cùng với tệp PNG. Để làm một điều bạn làm
convert image.png image.mpc
và bạn sẽ thoát ra khỏi image.mpc
và image.cache
. Sau đó, bạn chỉ cần thay đổi mã của mình trông giống như sau:
convert -size 600x400 xc:none \
\( 1.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 2.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 3.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 4.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 5.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \
\( 6.mpc -fill rgb\(x,y,z\) -colorize 100% \) -composite \
result.png
Điểm 3
Rất tiếc, bạn vẫn chưa trả lời câu hỏi của tôi, nhưng nếu danh mục tài sản của bạn không quá lớn, bạn có thể đặt nó (hoặc MPC tương đương ở trên) vào đĩa RAM khi khởi động hệ thống.
Điểm 4
Bạn chắc chắn nên chạy song song - điều đó sẽ mang lại lợi ích lớn nhất. Nó rất đơn giản với GNU Parallel - ví dụ ở đây.
Nếu bạn đang sử dụng REDIS, nó thực sự dễ dàng hơn thế. Chỉ LPUSH
hình ảnh được mã hóa MIME của bạn vào danh sách REDIS như sau:
#!/usr/bin/perl
################################################################################
# generator.pl <number of images> <image size in bytes>
# Mark Setchell
# Base64 encodes and sends "images" of specified size to REDIS
################################################################################
use strict;
use warnings FATAL => 'all';
use Redis;
use MIME::Base64;
use Time::HiRes qw(time);
my $Debug=0; # set to 1 for debug messages
my $nargs = $#ARGV + 1;
if ($nargs != 2) {
print "Usage: generator.pl <number of images> <image size in bytes>\n";
exit 1;
}
my $nimages=$ARGV[0];
my $imsize=$ARGV[1];
# Our "image"
my $image="x"x$imsize;
printf "DEBUG($$): images: $nimages, size: $imsize\n" if $Debug;
# Connection to REDIS
my $redis = Redis->new;
my $start=time;
for(my $i=0;$i<$nimages;$i++){
my $encoded=encode_base64($image,'');
$redis->rpush('images'=>$encoded);
print "DEBUG($$): Sending image $i\n" if $Debug;
}
my $elapsed=time-$start;
printf "DEBUG($$): Sent $nimages images of $imsize bytes in %.3f seconds, %d images/s\n",$elapsed,int($nimages/$elapsed);
và sau đó điều hành nhiều công nhân mà tất cả đều ngồi đó làm BLPOP công việc cần làm
#!/usr/bin/perl
################################################################################
# worker.pl
# Mark Setchell
# Reads "images" from REDIS and uudecodes them as fast as possible
################################################################################
use strict;
use warnings FATAL => 'all';
use Redis;
use MIME::Base64;
use Time::HiRes qw(time);
my $Debug=0; # set to 1 for debug messages
my $timeout=1; # number of seconds to wait for an image
my $i=0;
# Connection to REDIS
my $redis = Redis->new;
my $start=time;
while(1){
#my $encoded=encode_base64($image,'');
my (undef,$encoded)=$redis->blpop('images',$timeout);
last if !defined $encoded;
my $image=decode_base64($encoded);
my $l=length($image);
$i++;
print "DEBUG($$): Received image:$i, $l bytes\n" if $Debug;
}
my $elapsed=time-$start-$timeout; # since we waited that long for the last one
printf "DEBUG($$): Received $i images in %.3f seconds, %d images/s\n",$elapsed,int($i/$elapsed);
Nếu tôi chạy một quy trình trình tạo như trên và để nó tạo ra 100.000 hình ảnh 200kB mỗi hình ảnh và đọc chúng với 4 quy trình công nhân trên iMac thông số kỹ thuật hợp lý của tôi, thì mất 59 giây hoặc khoảng 1.700 hình ảnh / s có thể chuyển qua REDIS.