[cl-gd-devel] performance issue with CL-GD on SBCL, UFFI vs. CFFI

Edi Weitz edi at agharta.de
Wed May 27 08:17:31 UTC 2009


Thanks for the report.  I myself haven't used CL-GD for quite some
time and if I do I usually don't use it with SBCL, so I can't really
comment on these numbers.  Right now, I don't have the time to work on
CL-GD myself, but you're welcome to send reasonably documented and
tested patches and I'll try to make a new release ASAP although I
can't promise anything.

  http://weitz.de/patches.html

Thanks,
Edi.

On Thu, May 21, 2009 at 4:46 PM, Anon Alex <alexfs04 at gmail.com> wrote:
> Hello, I wanted to report a performance-related issue with CL-GD and
> UFFI vs CFFI-UFFI-COMPAT
>
> Here is a simple function for comparing two images:
> As you can see, this loops over every pixel of both images, compares
> the R,G,B components.
>
> (defun compare-images (image1 image2)
>  "Comapre two images -- uses API exported by CL-GD"
>  (declare (optimize (debug 0) (speed 3)(safety 0)))
>  ;(declare (optimize (debug 3) (speed 0)))
>  (let ((err 0)
>        (height (cl-gd:image-height image1))
>        (width (cl-gd:image-width image1)))
>    (declare (fixnum err height width))
>    (format t "height1=~a, height2=~a" height width)
>    (assert (and (= height (cl-gd:image-height image2))
>                 (= width (cl-gd:image-width image2))))
>    (loop for y fixnum from 0 below height do
>          (loop for x fixnum from 0 below width do
>                (let ((img-color (cl-gd:get-pixel y x :image image2))
>                      (target-color (cl-gd:get-pixel y x :image image1)))
>                  (incf err (square (- (the fixnum(cl-gd:color-component :red
> img-color :image image2))
>                                       (the fixnum(cl-gd:color-component :red target-color :image
> image1)))))
>                  (incf err (square (- (the fixnum (cl-gd:color-component :blue
> img-color :image image2))
>                                       (the fixnum(cl-gd:color-component :blue target-color :image
> image1)))))
>                  (incf err (square (- (the fixnum(cl-gd:color-component :green
> img-color :image image2))
>                                       (the fixnum(cl-gd:color-component :green target-color
> :image image1))))))))
>    err))
>
>
> Here's another version, which uses non-exported functions to speed it
> up a little bit (and for benchmarking, eliminate some of the the
> API-level overhead)
>
> (defun compare-images-raw (image1 image2)
>  "Compare two images -- use internal functions to eliminate overhead
> added by CL-GD API"
>  (declare (optimize (debug 0) (speed 3)(safety 0)))
>  ;(declare (optimize (debug 3) (speed 0)))
>  (let ((err 0)
>        (height (cl-gd:image-height image1))
>        (width (cl-gd:image-width image1))
>        (img1 (cl-gd::img image1))
>        (img2 (cl-gd::img image2)))
>    (declare (fixnum err height width))
>    (format t "height1=~a, height2=~a" height width)
>    (assert (and (= height (cl-gd:image-height image2))
>                 (= width (cl-gd:image-width image2))))
>    (loop for y fixnum from 0 below height do
>          (loop for x fixnum from 0 below width do
>                (let ((img2-color (cl-gd:get-pixel y x :image image2))
>                      (img1-color (cl-gd:get-pixel y x :image image1)))
>                  (incf err (square (- (the fixnum(cl-gd::gd-image-get-red img2 img2-color))
>                                       (the fixnum(cl-gd::gd-image-get-red img1 img1-color)))))
>                  (incf err (square (- (the fixnum(cl-gd::gd-image-get-green img2 img2-color))
>                                       (the fixnum(cl-gd::gd-image-get-green img1 img1-color)))))
>                  (incf err (square (- (the fixnum(cl-gd::gd-image-get-blue img2 img2-color))
>                                       (the fixnum(cl-gd::gd-image-get-blue img1 img1-color))))))))
>    err))
>
>
>
> This is the result of running the above pair of functions on a 1024x768 image.
>
> ----
> First, the timing with the standard CL-GD:
> (SBCL 1.0.28, CL-GD 0.5.6, UFFI-1.6.1, 3GHz Intel Core2 Duo, Linux))
>
> CL-GD uses UFFI by default on SBCL
>
>
> EVO-LISA> (progn
>  (defparameter *image1* (cl-gd:create-image-from-file "023.JPG"))
>  (defparameter *image2* (cl-gd:create-image-from-file "023.JPG"))
>  (time (compare-images *image1* *image2*)))
>
> height1=1024, height2=768
> Evaluation took:
>  1.684 seconds of real time
>  1.688105 seconds of total run time (1.688105 user, 0.000000 system)
>  100.24% CPU
>  5,061,067,326 processor cycles
>  141,296 bytes consed
>
> 0
>
>
> EVO-LISA> (progn
>  (defparameter *image1* (cl-gd:create-image-from-file "023.JPG"))
>  (defparameter *image2* (cl-gd:create-image-from-file "023.JPG"))
>  (time (compare-images-raw *image1* *image2*)))
>
> height1=1024, height2=768
> Evaluation took:
>  1.476 seconds of real time
>  1.424088 seconds of total run time (1.420088 user, 0.004000 system)
>  96.48% CPU
>  4,437,702,108 processor cycles
>  106,112 bytes consed
>
> 0
>
> -----
>
> After changing cl-gd.asd so that CFFI-UFFI-COMPAT is used for SBCL
> instead of UFFI:
>
> ;;;;;;;;
>
> EVO-LISA> (progn
>  (defparameter *image1* (cl-gd:create-image-from-file "023.JPG"))
>  (defparameter *image2* (cl-gd:create-image-from-file "023.JPG"))
>  (time (compare-images *image1* *image2*)))
>
> height1=1024, height2=768
> Evaluation took:
>  0.336 seconds of real time
>  0.336021 seconds of total run time (0.336021 user, 0.000000 system)
>  100.00% CPU
>  1,010,111,976 processor cycles
>  21,712 bytes consed
>
> 0
> EVO-LISA> (progn
>  (defparameter *image1* (cl-gd:create-image-from-file "023.JPG"))
>  (defparameter *image2* (cl-gd:create-image-from-file "023.JPG"))
>  (time (compare-images-raw *image1* *image2*)))
>
> height1=1024, height2=768
> Evaluation took:
>  0.282 seconds of real time
>  0.284018 seconds of total run time (0.284018 user, 0.000000 system)
>  100.71% CPU
>  845,516,097 processor cycles
>  21,936 bytes consed
>
> 0
>
> ------------
>
> Surprisingly,  there is a 5x difference between using CFFI and UFFI.
>
> Pixel-level access to an image, as provided by
> cl-gd:get-pixel, and cl-gd:color-component, is usually used in image
> processing, where cl-gd:get-pixel, and cl-gd:color-component will be
> called for many pixels on the image (usually the whole image), so the
> speed of these accessors is critical for image processing, and
> for some reason, CFFI (viat cffi-uffi-compat) offers 5x faster pixel
> level access than UFFI.
>
> I don't know much about either CFFI or UFFI, but
> CFFI-UFFI-COMPAT is the default already for CLISP and OpenMCL.
> Maybe it's worth considering making CFFI-UFFI-COMPAT the default for
> SBCL as well?
>
>
> Regards,
> Alex Fukunaga
>
> _______________________________________________
> cl-gd-devel site list
> cl-gd-devel at common-lisp.net
> http://common-lisp.net/mailman/listinfo/cl-gd-devel
>
>




More information about the Cl-gd-devel mailing list