| layout | default |
|---|---|
| title | Image Processing Example - PNWScala |
| short_title | Image Processing Example - PNWScala |
The following example is based on the miniboxing presentation at PNWScala. A huge thanks to Thomas Lockney and the PNWScala organizers for the wonderful conference and the confreaks guys who recorded the presentation!
<iframe width="800px" height="400px" src="//www.youtube.com/embed/RnIupOJv_oM" frameborder="0" allowfullscreen></iframe>This page will guide you through the steps necessary to run the example in the presentation. The pureimage library is located at github.com/stephenjudkins/pureimage. The mock-up used for the presentation is located at github.com/VladUreche/image-example.
To start, clone the pureimage mock-up:
{% highlight text %} $ git clone https://github.com/VladUreche/image-example.git Cloning into 'image-example'... ...
$ cd image-example {% endhighlight %}
Let's generate the Eclipse project files to load the project in the IDE:
{% highlight text %} $ sbt eclipse [info] Loading global plugins from /home/sun/.sbt/0.13/plugins ... [info] Done updating. [info] Successfully created Eclipse project files for project(s): [info] image-example {% endhighlight %}
Cool. Now, all you need is the latest Scala IDE for Eclipse to load the project. Please use a version for Scala 2.11, in order to stay compatible with the rest of the project. Now, to load the project:
File>Import ...>General>Existing Projects into Workspace- point Eclipse to the
image-exampledirectory, selectimage-exampleand hitFinish
You should see the project in Eclipse:
Open Test.scala from package image.example, located in src/main/scala, and run it:
On my laptop, I got the following times:
{% highlight text %} Operation took 4192 milliseconds. Operation took 4957 milliseconds. Operation took 4755 milliseconds. Operation took 3969 milliseconds. Operation took 4073 milliseconds. {% endhighlight %}
The miniboxing plugin generated a couple of warnings during compilation:
One such warning is:
{% highlight text %} The class image.example.Pixel would benefit from miniboxing type parameter Repr, since it is instantiated by a primitive type. {% endhighlight %}
So let's go in and fix that. Open Pixel.scala and mark the type parameter Repr of class Pixel by @miniboxed:
{% highlight scala %} abstract class Pixel[@miniboxed Repr: Manifest] { def r(t: Repr): Double // red def g(t: Repr): Double // green def b(t: Repr): Double // blue def a(t: Repr): Double // alpha def pack(r: Double, g: Double, b: Double, a: Double): Repr // to allow Image to build an array: implicit def manifest = implicitly[Manifest[Repr]] } {% endhighlight %}
We can fix the other 8 warnings that appear and recompile. Surprisingly, after compiling again, we get an error:
{% highlight text %} The method map in class ImageImpl overrides method map in class Image therefore needs to have the follwing type parameters marked with @miniboxed: type Repr2. {% endhighlight %}
This is because we added the @miniboxed annotation to method map in Image:
{% highlight scala %} abstract class Image[Repr: Pixel] { def width: Int def height: Int def apply(x: Int, y: Int): Repr def map[@miniboxed Repr2: Pixel](f: Image[Repr] => Generator[Repr2]): Image[Repr2] } {% endhighlight %}
but did not add the annotation to method map in ImageImpl, which extends Image:
{% highlight scala %} private class ImageImpl[Repr: Pixel](val width: Int, val height: Int) extends Image[Repr] { ... def map[Repr2: Pixel](f: Image[Repr] => Generator[Repr2]): Image[Repr2] = { ... } } {% endhighlight %}
Let's fix that:
{% highlight scala %} private class ImageImpl[Repr: Pixel](val width: Int, val height: Int) extends Image[Repr] { ... def map[@miniboxed Repr2: Pixel](f: Image[Repr] => Generator[Repr2]): Image[Repr2] = { ... } } {% endhighlight %}
If we recompile, the error is gone, but we get another batch of 26 warnings:
Let's try to run the program now, despite the warnings:
So by adding a couple of annotations, we just shaved off one quarter of the running time:
{% highlight text %} Operation took 3082 milliseconds. Operation took 2998 milliseconds. Operation took 3017 milliseconds. Operation took 2535 milliseconds. Operation took 2615 milliseconds. {% endhighlight %}
Maybe this miniboxing thing is actually worth it...
Let's now address all the warnings. But let's be smart about it:
- go to
Project>Properties(if that's disabled, make sure theimage-exampleproject is selected) - in the window go to
Scala Compilerand add-P:minibox:mark-allto theAdditional command line parametersfield.
As explained in the command line options, the -P:minibox:mark-all flag will mark all type parameters with @miniboxed automatically.
Recompile and you should not see any more warnings. Now let's run again:
{% highlight text %} Operation took 1346 milliseconds. Operation took 1187 milliseconds. Operation took 1178 milliseconds. Operation took 1094 milliseconds. Operation took 1163 milliseconds. {% endhighlight %}
Wow, that's four times faster than our initial running time. That's what miniboxing can do for numeric-intensive applications!
