Perintah Anda sebenarnya bermuara pada ini:
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
Pikiran saya adalah sebagai berikut:
Titik 1:
-composite
pertama ke kanvas kosong tampaknya tidak ada gunanya - mungkin 1.png
adalah PNG 600x400 dengan transparansi, sehingga baris pertama Anda dapat menghindari operasi pengomposisian dan menghemat 16% waktu pemrosesan dengan mengubah ke:
convert -background none 1.png -fill ... -colorize 100% \
\( 2.png ..
\( 3.png ...
Titik 2
Saya menempatkan yang setara dengan perintah Anda ke dalam satu lingkaran dan melakukan 100 iterasi dan itu membutuhkan waktu 15 detik. Saya kemudian mengubah semua pembacaan file PNG Anda menjadi pembacaan MPC
file - atau file Magick Pixel Cache. Itu mengurangi waktu pemrosesan menjadi hanya di bawah 10 detik, yaitu sebesar 33%. Magic Pixel Cache hanyalah file pra-dekompresi, pra-dekode yang dapat dibaca langsung ke memori tanpa upaya CPU. Anda dapat membuatnya terlebih dahulu setiap kali katalog Anda berubah dan menyimpannya di samping file PNG. Untuk membuatnya Anda lakukan
convert image.png image.mpc
dan Anda akan keluar image.mpc
dan image.cache
. Kemudian Anda cukup mengubah kode Anda menjadi seperti ini:
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
Titik 3
Sayangnya Anda belum menjawab pertanyaan saya, tetapi jika katalog aset Anda tidak terlalu besar, Anda dapat meletakkannya (atau MPC yang setara di atas) ke disk RAM saat sistem dinyalakan.
Titik 4
Anda pasti harus berlari secara paralel - itu akan menghasilkan keuntungan terbesar dari semuanya. Ini sangat sederhana dengan GNU Parallel - contohnya di sini.
Jika Anda menggunakan REDIS, sebenarnya lebih mudah dari itu. Cukup LPUSH
gambar yang dikodekan MIME Anda ke dalam daftar REDIS seperti ini:
#!/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);
lalu jalankan beberapa pekerja yang semuanya duduk di sana melakukan BLPOP pekerjaan yang harus dilakukan
#!/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);
Jika saya menjalankan satu proses generator seperti di atas dan membuatnya menghasilkan 100.000 gambar masing-masing 200kB, dan membacanya dengan 4 proses pekerja di iMac spesifikasi wajar saya, dibutuhkan 59 detik, atau sekitar 1.700 gambar/dtk dapat melewati REDIS.