I’m using the kmeans feature in version 7 of ImageMagick.
time convert in.png -kmeans 20 out.png
This command completes rather quickly on my machine (1.7s
)
However when running within docker it goes much slower (48.8s
).
I’ve tried docker on my same machine, and also docker in AWS Lambda. Doesn’t seem to matter what type of image I use either. Same slow speed everywhere within docker.
I’m using this docker: FROM amazon/aws-lambda-nodejs:20.2024.02.07.18 as build
and compiling ImageMagic 7 via source (because only ImageMagick version 6
is available as a package via dnf
on AmazonLinux2023).
Have I done something wrong with compiling ImageMagick perhaps? A missing library or some sort of optimisation?
This is the ImageMagick version running within docker:
bash-5.2# convert -version
Version: ImageMagick 7.1.1-29 Q16-HDRI x86_64 cfc71f0aa:20240225 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI
Delegates (built-in): bzlib fontconfig freetype jng jpeg lzma png xml zlib
Compiler: gcc (11.4)
This is the faster ImageMagick running directly on my machine:
Version: ImageMagick 7.1.1-25 Q16-HDRI aarch64 21883 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenMP(5.0)
Delegates (built-in): bzlib fontconfig freetype gslib heic jng jp2 jpeg jxl lcms lqr ltdl lzma openexr png ps raw tiff webp xml zlib zstd
Compiler: gcc (4.2)
To compile ImageMagick within Docker I used this approach:
FROM amazon/aws-lambda-nodejs:20.2024.02.07.18 as build
RUN dnf -y update && dnf install -y g++ gdb ninja-build gcc cpp cmake make automake autoconf chkconfig pkgconfig clang clang-libs gcc-c++ dos2unix bzip2 bzip2-libs zlib-devel libpng libpng-tools libpng-devel openjpeg2 openjpeg2-tools openjpeg2-devel libwebp-devel giflib-devel fftw-libs fontconfig-devel libtool xz xz-libs tar bc && dnf clean all
ADD build /root/build
RUN /root/build/imagemagick.sh
with this build script:
#!/usr/bin/env bash
set -e
# libjpg
cd /root
curl https://github.com/winlibs/libjpeg/archive/refs/tags/libjpeg-9c.tar.gz -L -o tmp-libjpeg.tar.gz
tar xf tmp-libjpeg.tar.gz
cd libjpeg*
dos2unix *
dos2unix -f configure
chmod +x configure
PKG_CONFIG_PATH=/root/build/cache/lib/pkgconfig
./configure
CPPFLAGS=-I/root/build/cache/include
LDFLAGS=-L/root/build/cache/lib
--disable-dependency-tracking
--disable-shared
--enable-static
--prefix=/root/build/cache
dos2unix -f libtool
make
make install
# libpng
cd /root
curl http://prdownloads.sourceforge.net/libpng/libpng-1.6.37.tar.xz -L -o tmp-libpng.tar.xz
tar xf tmp-libpng.tar.xz
cd libpng*
PKG_CONFIG_PATH=/root/build/cache/lib/pkgconfig
./configure
CPPFLAGS=-I/root/build/cache/include
LDFLAGS=-L/root/build/cache/lib
--disable-dependency-tracking
--disable-shared
--enable-static
--prefix=/root/build/cache
make
make install
# imagemagick
cd /root
curl https://github.com/ImageMagick/ImageMagick/archive/refs/tags/7.1.1-29.tar.gz -L -o tmp-imagemagick.tar.gz
tar xf tmp-imagemagick.tar.gz
cd ImageMagick*
PKG_CONFIG_PATH=/root/build/cache/lib/pkgconfig
./configure
CPPFLAGS=-I/root/build/cache/include
LDFLAGS="-L/root/build/cache/lib -lstdc++"
--disable-dependency-tracking
--disable-shared
--enable-static
--prefix=/root/result
--enable-delegate-build
--disable-installed
--without-modules
--disable-docs
--without-magick-plus-plus
--without-perl
--without-x
--disable-openmp
--with-openjp2=no
--with-webp=no
--with-tiff=no
make clean
make all
make install
*edit: I also tried re-compiling without disable-openmp
after reading that it can improve performance. Same time with and without that compilation option.
2
Answers
Here are some things you could try…
Run the following on both machines to see the exact options each version was built with and compare the output:
Try building a Q8 version to see if that is any faster:
Try using compiler optimisation and targeting the exact architecture of your machine, along these lines depending on your compiler:
Try disabling OpenCL:
Check your docker config files to see how much RAM and how many CPU cores it is giving your container.
Maybe you are open to using a different tool? For example, on an
alpine:latest
container, you can install OpenCV with:Then you can do K-means clustering like this:
Or maybe you do lots of other processing and ImageMagick is more appropriate and flexible.
You can speed up kmeans in Imagemagick by using its optional arguments for number of iterations or convergence tolerance. So reduce the number of iterations from the default or increase the tolerance from the default. The arguments are:
Defaults are: iterations=300 and convergence=0.0001