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:
Multithreading | Radius 10 | Radius 25 | Radius 50 |
---|---|---|---|
None | 2.75 sec | 5.986 sec | 11.121 sec |
2 Threads | 2.082 sec | 3.515 sec | 6.597 sec |
4 Threads | 2.202 sec | 3.601 sec | 7.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:
Multithreading | Radius 10 | Radius 25 | Radius 50 |
---|---|---|---|
None | 2.561 sec | 5.706 sec | 10.829 sec |
2 Threads | 1.624 sec | 3.17 sec | 5.826 sec |
4 Threads | 1.42 sec | 2.652 sec | 4.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:
Multithreading | Radius 10 | Radius 25 | Radius 50 |
---|---|---|---|
None | 8.581 sec | 18.968 sec | 35.674 sec |
2 Threads | 9.128 sec | 19.745 sec | 36.257 sec |
4 Threads | 9.089 sec | 19.949 sec | 36.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:
Post a Comment