Combining Ken and David's tips, this version processes a byte-array of
sizd 1920000 in about 13 milliseconds on my machine:

(def buffer-size 1920000)
(def array (byte-array buffer-size))

(defn java-like [^bytes cpuArray]
  (loop [i (int 0)]
    (if (< i buffer-size)
      (let [b (aget cpuArray i)
            g (aget cpuArray (unchecked-add i (int 1)))
            r (aget cpuArray (unchecked-add i (int 2)))
            a (aget cpuArray (unchecked-add i (int 3)))]
        (aset cpuArray i a)
        (aset cpuArray (unchecked-add i (int 1)) b)
        (aset cpuArray (unchecked-add i (int 2)) g)
        (aset cpuArray (unchecked-add i (int 3)) r)
        (recur (unchecked-add i (int 4)))))))

user=> (time (java-like array))
"Elapsed time: 13.648662 msecs"

Found something interesting when I tried to emulate how Robert's
version aliased 'unchecked-add' as '+':

(defn java-like [^bytes cpuArray]
  (loop [i (int 0)]
    (if (< i buffer-size)
      (let [+ unchecked-add
            b (aget cpuArray i)
            g (aget cpuArray (+ i (int 1)))
            r (aget cpuArray (+ i (int 2)))
            a (aget cpuArray (+ i (int 3)))]
        (aset cpuArray i a)
        (aset cpuArray (+ i (int 1)) b)
        (aset cpuArray (+ i (int 2)) g)
        (aset cpuArray (+ i (int 3)) r)
        (recur (+ i (int 4)))))))

When I try to compile this, Clojure complains that I'm trying to
rebind i, a primitive local, with a value of the wront type in
'recur'.

It seems that 'unchecked-add' returns a primitive (note that in the
first version, 'recur' happily accepts the return from 'unchecked-add'
without coercion), but when 'unchecked-add' is bound to a new name,
the return gets boxed.

Is this the correct interpretation, or am I missing something?

On Jan 28, 9:06 am, David Nolen <dnolen.li...@gmail.com> wrote:
> On Fri, Jan 28, 2011 at 10:48 AM, Robert McIntyre <r...@mit.edu> wrote:
> > I tried to convert this java code line for line to clojure to compare
> > the speed differences, and boy was I surprised!
>
> >        public static void ConvertToAWT(byte[] cpuArray){
> >                // Given an array of bytes representing a c-style bgra
> > image,
> >                // converts to a java style abgr image
> >                int len = java.lang.reflect.Array.getLength(cpuArray);
> >                for (int i = 0; i < len; i+=4){
> >                        byte b = cpuArray[i+0];
> >                        byte g = cpuArray[i+1];
> >                        byte r = cpuArray[i+2];
> >                        byte a = cpuArray[i+3];
> >                        cpuArray[i+0] = a;
> >                        cpuArray[i+1] = b;
> >                        cpuArray[i+2] = g;
> >                        cpuArray[i+3] = r;  }}
>
> > (defn java-like []
> >  (loop [i (int 0)] (if (< i buffer-size)
> >                      (let [ + clojure.core/unchecked-add
> >                            b (aget cpuArray i)
> >                            g (aget cpuArray (+ 1 i))
> >                            r (aget cpuArray (+ 2 i))
> >                            a (aget cpuArray (+ 3 i))]
> >                        (aset-byte cpuArray i a)
> >                        (aset-byte cpuArray (+ 1 i) b)
> >                        (aset-byte cpuArray (+ 2 i) g)
> >                        (aset-byte cpuArray (+ 3 i) r)
> >                        (recur (int (+ i 4)))))))
>
> > (defn clojure-like []
> >  (doall (flatten (map (fn [[b g r a]] [a b g r]) (partition 4 4
> > cpuArray)))))
>
> I'm assuming you're using 1.2.0. cpuArray needs to be hinted. All the
> literals also need to be hinted. Don't use aset-byte, use aset.
>
> In 1.3.0 you no longer have to hint the literals and you can use the
> *unchecked-math* compiler flag instead of redefining unchecked-add as a
> local.
>
> David

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to