您的命令实际上归结为:
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
具有透明度的 600x400 PNG,因此您的第一行可以避免合成操作并通过更改为:节省 16% 的处理时间:
convert -background none 1.png -fill ... -colorize 100% \
\( 2.png ..
\( 3.png ...
第 2 点
我将与您的命令等效的内容放入一个循环中并进行了 100 次迭代,这需要 15 秒。然后,我将您对 PNG 文件的所有读取更改为对文件的读取MPC
- 或 Magick Pixel Cache 文件。这将处理时间减少到不到 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 点
您绝对应该并行运行 - 这将产生最大的收益。使用 GNU Parallel- example here非常简单。
如果您使用的是 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);
如果我如上所述运行一个生成器进程并让它生成 100,000 张 200kB 的图像,并在我的合理规格 iMac 上使用 4 个工作进程读取它们,则需要 59 秒,或者大约 1,700 张图像/秒可以通过 REDIS。