あなたのコマンドは実際にはこれに要約されます:
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
私の考えは次のとおりです:
ポイント1:
最初の-composite
空白のキャンバスに置くのは無意味に思えます-おそらく1.png
は透明度のある600x400PNGであるため、最初の行で合成操作を回避し、次のように変更することで処理時間を16%節約できます。
convert -background none 1.png -fill ... -colorize 100% \
\( 2.png ..
\( 3.png ...
ポイント2
私はあなたのコマンドに相当するものをループに入れ、100回の反復を行いました。15秒かかります。次に、PNGファイルのすべての読み取りをMPC
の読み取りに変更しました ファイル-またはMagickPixelCacheファイル。これにより、処理時間が10秒弱、つまり33%短縮されました。 Magic Pixel Cacheは、事前に解凍され、事前にデコードされたファイルであり、CPUの負担なしにメモリに直接読み取ることができます。カタログが変更されるたびにそれらを事前に作成し、PNGファイルと一緒に保存することができます。あなたがするものを作るために
convert image.png image.mpc
image.mpc
が表示されます およびimage.cache
。次に、コードを次のように変更するだけです。
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
ポイント3
残念ながら、あなたはまだ私の質問に答えていませんが、アセットカタログが大きすぎない場合は、システムの起動時にそれ(または上記のMPC同等物)をRAMディスクに置くことができます。
ポイント4
あなたは間違いなく並行して実行する必要があります-それはすべての中で最大の利益をもたらすでしょう。 GNUParallelを使用すると非常に簡単です-ここに例があります。
REDISを使用している場合は、実際にはそれよりも簡単です。 LPUSH
だけ MIMEでエンコードされた画像を次のようにREDISリストに追加します:
#!/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);
次に、そこに座ってBLPOPの仕事をしている複数のワーカーを実行します
#!/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);
上記のように1つのジェネレータープロセスを実行し、それぞれ200kBの100,000の画像を生成し、妥当な仕様のiMacで4つのワーカープロセスでそれらを読み取ると、59秒かかります。つまり、約1,700画像/秒でREDISを通過できます。