Designing, coding and debugging Java Rich Client and Java EE Applications

Friday 21 March 2008

Paralellizing image filter operations, part 1

On last December's Javapolis I attended the "filthy makeover" track by Chet Haase.
Chet showed some cool performance hacks for Swing, among them a nasty one for speeding up an image blur filter. While the trick he used was a cool way of cutting corners a little bit for performance sake, I kept on wondering:
Isn't image processing exactly the kind of computation that would hugely benefit from a multithreaded approach? And after all parallelizing such an operation should be fairly straight forward: Just split the image up into tiles and process each one independently. Plus: The new (well not that new anymore) concurrency features of Java 5 should make the job quite a bit easier.
I decided to try it out and developed a little demo in form of a Swing application.
For building this demo I used NetBeans 6. Unfortunately I couldn't resist using some the new features of NetBeans for building Swing Applications: I used
the new Swing Application Framework and Beans Binding. I found that these new frameworks around Swing and the support for them in NetBeans show great potential for making a Swing developers life easier. Even if there are still some rough edges. But I leave that for some other blog entry.
For the demo I used a Gaussian blur filter that I sto...hmm...cop...aah.. well that I got from a Filthy Rich Client example by Romain Guy. I sure hope he doesn't mind that I used his code snipped instead of digging it up myself. Anyway, the filter is applied to a really large image, so the benefits from the parallelizing will be clearly visible and the involved overhead plays less of a role.
Here's what the (for now) finished demo looks like:

The image used is a 3836x2560 pixel photo that a friend of mine took at Frankfurt airport. It is shown either in "scale to fit" view, or in a "1:1" view (the view can be switched by double clicking on it).
Also, the radius for blur operation can be changed through the GUI. The larger the radius is, the more the image gets blurred and the more time-consuming the operation becomes.
If the blur is applied with a 25 pixel radius the results are the following when viewed in the "1:1" zoomed in view:

Okay, but what about the performance now?
To be honest, I wasn't 100 percent sure if the multithreading would really boost the performance, considering the added overhead of the tiling.

So, I was delighted to see the following results on my 2.2 Ghz Core Duo 2 Windows XP Laptop:
MultithreadingRadius 10Radius 25Radius 50
None2.75 sec5.986 sec11.121 sec
2 Threads2.082 sec3.515 sec6.597 sec
4 Threads2.202 sec3.601 sec7.151 sec

While the operation benefits just a little for a small radius of 10 pixels, the performance boost is really there for a 25 and 50 pixels radius! Using 2 Threads the performance is 1.7 times higher than using no multithreading at all. A twofold increase in in performance would be the theoretical maximum. Considering that the approach with one thread avoids the overhead of tiling and creating threads all together, the 1.7 fold increase is not so bad, really.
Using 4 threads is slower than using 2 on a machine with 2 cores, but the performance hit seems not so severe.
So, what happens if I let the demo run on my new 2.33 Ghz quad core desktop machine?
Here are the results:
MultithreadingRadius 10Radius 25Radius 50
None2.561 sec5.706 sec10.829 sec
2 Threads1.624 sec3.17 sec5.826 sec
4 Threads1.42 sec2.652 sec4.786 sec


Damn! It is a little bit faster with 4 threads but not as much as I hoped for. I guess I have to investigate that a bit in profiling.
Oh, here are also some results from my old single core 1,5 Ghz Pentium M
laptop running Ubuntu 7.10:
MultithreadingRadius 10Radius 25Radius 50
None8.581 sec18.968 sec35.674 sec
2 Threads9.128 sec19.745 sec36.257 sec
4 Threads9.089 sec19.949 sec36.888 sec


If you want to try the demo out for yourself you can webstart it up directly from here!

The complete source code is available here: MultithreadingDemoSrc.zip (1.49Mb)
It's in the form of NetBeans 6 project.
The rather large download size is mostly due to the contained high resolution photo, that weights in at 1.33 Mb.

In the next post I'll go further into the details of the demo, posting some code fragments and a little bit of design background...

No comments: