JAI optimizing..

Discussion in 'Java' started by a0a, Sep 24, 2007.

  1. a0a

    a0a Guest

    Hi everyone,

    I did a little benchmark on the speedup that JAI can bring in
    computing the point with minimum distance from a given source point
    (x,y) out of an array of x,y coordinates.

    I did this both with JAI and by brute-forcing it using a simple
    distance check. Although the JAI is very elegant in that it
    automatically returns ALL minimum distance points, it is also 6 times
    slower than the brute-force method.

    I am guessing that I may have gotten something wrong in the set-up,
    but since the information on JAI and tutorials are rather scarce or
    not working at all, I thought maybe someone here could take a look at
    this:


    ------ this is what I want to do ------

    ArrayList<Integer> indexes = new ArrayList<Integer> ();
    int closestPoint = Integer.MAX_VALUE;

    for (int i = 0; i < xvalues.length; i++)
    {
    int xdiff = xvalues - x;
    int ydiff = yvalues - y;
    int sqr = xdiff* xdiff + ydiff*ydiff;
    if ( sqr == closestPoint )
    {
    indexes.add(i);
    }
    if ( sqr < closestPoint )
    {
    closestPoint = sqr;
    indexes.clear();
    indexes.add(i);
    }
    }


    ------ this is what does it, but 6 times slower, in JAI ------


    double[] xSub = new double[]{x};
    double[] ySub = new double[]{y};

    RenderedOp renderedOpXSubXRef = SubtractConstDescriptor.create(imageX,
    xSub, rh);
    RenderedOp renderedOpYSubYRef = SubtractConstDescriptor.create(imageY,
    ySub, rh);
    RenderedOp renderedOpXDiff2 =
    MultiplyDescriptor.create(renderedOpXSubXRef, renderedOpXSubXRef, rh);
    RenderedOp renderedOpYDiff2 =
    MultiplyDescriptor.create(renderedOpYSubYRef, renderedOpYSubYRef, rh);
    RenderedOp renderedOpSum = AddDescriptor.create(renderedOpXDiff2,
    renderedOpYDiff2, rh);
    RenderedOp renderedOpExtrema = ExtremaDescriptor.create(renderedOpSum,
    null, 1, 1, true, 1, rh);

    List minLocations =
    ((List[])renderedOpExtrema.getProperty("minLocations"))[0];

    ------------------------------------------------------------------------------------

    Of course, right before this code I convert the 2 int[] arrays
    containing x values and y values into BufferedImages using a GrayScale
    colorspace, 32 bit colorModel with no alpha, no transparency, no
    premultiplication. I do not alter the rasters during computation, I
    merely fetch the min values from the list "minLocations" afterwards.
    Timing it indicates that processing is extremely slow, however, I
    still have to rewrite the benchmark to warm up first and redo the test
    a number of times, maybe the test may show improvement. However, if
    anyone has ideas how to speed up the operation pipe, I am all ears!
    a0a, Sep 24, 2007
    #1
    1. Advertising

  2. a0a

    a0a Guest

    Warming up the test seems to make a huge difference. The first
    RenderedOp takes about 6 times longer than the whole pojo processing,
    but each additional RenderedOp takes only fractions of the total time,
    leading me to believe the set-up of JAI is slow, but processing is
    extremely fast once you have all the system resources set-up. I
    achieved almost a 100 fold speed increase for processing 5 million
    coordinates, compared to pojo.

    I dived a little deeper in the JAI docs, and essentially tried to
    rewrite the setup using RenderableOp and ParameterBlock's instead of
    RenderedOp. I got it to compile correctly, but during runtime, I get
    an exception that got me rather puzzled:

    Exception in thread "main" com.sun.medialib.mlib.mediaLibException:
    mediaLib: exception in a native method.
    at com.sun.medialib.mlib.Image.ExtremaLocations(Native Method)
    at
    com.sun.media.jai.mlib.MlibExtremaOpImage.accumulateStatistics(MlibExtremaOpImage.java:
    170)
    at
    javax.media.jai.StatisticsOpImage.getProperty(StatisticsOpImage.java:
    292)
    at
    com.sun.media.jai.opimage.ExtremaOpImage.getProperty(ExtremaOpImage.java:
    100)
    at javax.media.jai.RenderedOp$1.getProperty(RenderedOp.java:1808)
    at
    javax.media.jai.PropertyEnvironment.getProperty(PropertyEnvironment.java:
    197)
    at
    javax.media.jai.PropertySourceImpl.getProperty(PropertySourceImpl.java:
    277)
    at
    javax.media.jai.WritablePropertySourceImpl.getProperty(WritablePropertySourceImpl.java:
    130)
    at javax.media.jai.RenderedOp.getProperty(RenderedOp.java:1982)
    at JAIDistanceTest.testDistances2(JAIDistanceTest.java:180)
    at JAIDistanceTest.<init>(JAIDistanceTest.java:71)
    at JAITest.main(JAITest.java:40)

    ------------------------------------------------

    And here is the code I used, maybe someone can spot the obvious
    mistake? Thanks!

    ------------------------------------------------


    int bits[] = new int[] {32};
    ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
    ColorModel colorModel = new ComponentColorModel(colorSpace, bits,
    false, false, Transparency.OPAQUE, DataBuffer.TYPE_INT);
    SampleModel sampleModel =
    colorModel.createCompatibleSampleModel(25,25);;

    DataBufferInt dataBufferX = new DataBufferInt(xvalues,
    xvalues.length);
    WritableRaster rasterX =
    WritableRaster.createWritableRaster(sampleModel, dataBufferX, new
    Point(0,0));
    BufferedImage imageX = new BufferedImage(colorModel, rasterX,
    false, null);

    DataBufferInt dataBufferY = new DataBufferInt(yvalues,
    yvalues.length);
    WritableRaster rasterY =
    WritableRaster.createWritableRaster(sampleModel, dataBufferY, new
    Point(0,0));
    BufferedImage imageY = new BufferedImage(colorModel, rasterY,
    false, null);

    PlanarImage planarImageX = new RenderedImageAdapter(imageX);
    PlanarImage planarImageY = new RenderedImageAdapter(imageY);

    RenderingHints renderingHints = new
    RenderingHints(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
    renderingHints.put(RenderingHints.KEY_ANTIALIASING,
    RenderingHints.VALUE_ANTIALIAS_OFF);
    renderingHints.put(RenderingHints.KEY_DITHERING,
    RenderingHints.VALUE_DITHER_DISABLE);
    renderingHints.put(RenderingHints.KEY_STROKE_CONTROL,
    RenderingHints.VALUE_STROKE_PURE);
    renderingHints.put(RenderingHints.KEY_FRACTIONALMETRICS,
    RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
    renderingHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION,
    RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);

    // create a renderable image with no downsampled piramid
    ParameterBlock parameterBlockX = new ParameterBlock();
    parameterBlockX.addSource(planarImageX);
    parameterBlockX.add(null).add(null).add(null).add(null).add(null);
    RenderableImage renderableImageX = JAI.createRenderable("renderable",
    parameterBlockX);

    // create a renderable image with no downsampled piramid
    ParameterBlock parameterBlockY = new ParameterBlock();
    parameterBlockY.addSource(planarImageY);
    parameterBlockY.add(null).add(null).add(null).add(null).add(null);
    RenderableImage renderableImageY = JAI.createRenderable("renderable",
    parameterBlockY);

    double[] xSub = new double[]{x};
    double[] ySub = new double[]{y};

    long nanoStart = System.nanoTime();
    ParameterBlock parameterBlockSub1 = new ParameterBlock();
    parameterBlockSub1.addSource(renderableImageX);
    parameterBlockSub1.add(xSub);
    RenderableOp renderableOpXSubXRef =
    JAI.createRenderable("subtractconst", parameterBlockSub1);

    ParameterBlock parameterBlockSub2 = new ParameterBlock();
    parameterBlockSub2.addSource(renderableImageY);
    parameterBlockSub2.add(ySub);
    RenderableOp renderableOpYSubYRef =
    JAI.createRenderable("subtractconst", parameterBlockSub2);

    ParameterBlock parameterBlockPow1 = new ParameterBlock();
    parameterBlockPow1.addSource(renderableOpXSubXRef);
    parameterBlockPow1.addSource(renderableOpXSubXRef);
    RenderableOp renderableOpXDiff2 = JAI.createRenderable("multiply",
    parameterBlockPow1);


    ParameterBlock parameterBlockPow2 = new ParameterBlock();
    parameterBlockPow2.addSource(renderableOpYSubYRef);
    parameterBlockPow2.addSource(renderableOpYSubYRef);
    RenderableOp renderableOpYDiff2 = JAI.createRenderable("multiply",
    parameterBlockPow2);

    ParameterBlock parameterBlockSum = new ParameterBlock();
    parameterBlockSum.addSource(renderableOpXDiff2);
    parameterBlockSum.addSource(renderableOpYDiff2);
    RenderableOp renderableOpSum = JAI.createRenderable("add",
    parameterBlockSum);

    AffineTransform screenResolution = new AffineTransform();
    RenderContext renderContext = new
    RenderContext(screenResolution);
    RenderedOp renderedOpExtrema =
    ExtremaDescriptor.create(renderableOpSum.createRendering(renderContext),
    null, 1, 1, true, 1, renderingHints);

    long nanoEnd = System.nanoTime();

    List minLocations =
    ((List[])renderedOpExtrema.getProperty("minLocations"))[0];



    some good references in case you are interested:

    http://72.5.124.55/products/java-me...1guide-unc/Programming-environ.doc.html#55932
    http://java.sun.com/products/java-m..._1guide-unc/Image-manipulation.doc.html#56366
    http://java.sun.com/j2se/1.3/docs/api/java/awt/image/renderable/RenderableImage.html
    (JAI API docs)
    http://www.geocities.com/larryhr/samplecode/samplecode.html (sample
    code)
    http://forums.java.net/jive/thread.jspa?messageID=235530&tstart=0
    (chained calls)
    http://java.sun.com/products/java-media/jai/forDevelopers/jaifaq.html
    (sun tutorials)


    On 24 sep, 20:15, a0a <> wrote:
    > Hi everyone,
    >
    > I did a little benchmark on the speedup thatJAIcan bring in
    > computing the point with minimum distance from a given source point
    > (x,y) out of an array of x,y coordinates.
    >
    > I did this both withJAIand by brute-forcing it using a simple
    > distance check. Although theJAIis very elegant in that it
    > automatically returns ALL minimum distance points, it is also 6 times
    > slower than the brute-force method.
    >
    > I am guessing that I may have gotten something wrong in the set-up,
    > but since the information onJAIand tutorials are rather scarce or
    > not working at all, I thought maybe someone here could take a look at
    > this:
    >
    > ------ this is what I want to do ------
    >
    > ArrayList<Integer> indexes = new ArrayList<Integer> ();
    > int closestPoint = Integer.MAX_VALUE;
    >
    > for (int i = 0; i < xvalues.length; i++)
    > {
    > int xdiff = xvalues - x;
    > int ydiff = yvalues - y;
    > int sqr = xdiff* xdiff + ydiff*ydiff;
    > if ( sqr == closestPoint )
    > {
    > indexes.add(i);
    > }
    > if ( sqr < closestPoint )
    > {
    > closestPoint = sqr;
    > indexes.clear();
    > indexes.add(i);
    > }
    >
    > }
    >
    > ------ this is what does it, but 6 times slower, inJAI------
    >
    > double[] xSub = new double[]{x};
    > double[] ySub = new double[]{y};
    >
    > RenderedOp renderedOpXSubXRef = SubtractConstDescriptor.create(imageX,
    > xSub, rh);
    > RenderedOp renderedOpYSubYRef = SubtractConstDescriptor.create(imageY,
    > ySub, rh);
    > RenderedOp renderedOpXDiff2 =
    > MultiplyDescriptor.create(renderedOpXSubXRef, renderedOpXSubXRef, rh);
    > RenderedOp renderedOpYDiff2 =
    > MultiplyDescriptor.create(renderedOpYSubYRef, renderedOpYSubYRef, rh);
    > RenderedOp renderedOpSum = AddDescriptor.create(renderedOpXDiff2,
    > renderedOpYDiff2, rh);
    > RenderedOp renderedOpExtrema = ExtremaDescriptor.create(renderedOpSum,
    > null, 1, 1, true, 1, rh);
    >
    > List minLocations =
    > ((List[])renderedOpExtrema.getProperty("minLocations"))[0];
    >
    > ------------------------------------------------------------------------------------
    >
    > Of course, right before this code I convert the 2 int[] arrays
    > containing x values and y values into BufferedImages using a GrayScale
    > colorspace, 32 bit colorModel with no alpha, no transparency, no
    > premultiplication. I do not alter the rasters during computation, I
    > merely fetch the min values from the list "minLocations" afterwards.
    > Timing it indicates that processing is extremely slow, however, I
    > still have to rewrite the benchmark to warm up first and redo the test
    > a number of times, maybe the test may show improvement. However, if
    > anyone has ideas how to speed up the operation pipe, I am all ears!
    a0a, Sep 25, 2007
    #2
    1. Advertising

  3. a0a wrote:
    ...
    >And here is the code I used, maybe someone can spot the obvious
    >mistake?


    1) Posting code snippets* to an uncommon API that nobody
    else** can easily compile and run?
    2) Top-posting your reply to an earlier post (does not make
    people well disposed to helping). It is considered better,
    and clearer, to post 'in-line, with trimming'.

    * Much more chance of help, with an SSCCE.
    <http://www.physci.org/codes/sscce.html>
    ** No, I myself have never dealt with JAI, but to get
    the attention and help of those that have, your best
    bet is to make it easy for them.

    --
    Andrew Thompson
    http://www.athompson.info/andrew/

    Message posted via JavaKB.com
    http://www.javakb.com/Uwe/Forums.aspx/java-general/200709/1
    Andrew Thompson, Sep 25, 2007
    #3
  4. a0a

    a0a Guest

    On 25 sep, 15:11, "Andrew Thompson" <u32984@uwe> wrote:
    > 1) Posting code snippets* to an uncommon API that nobody
    > else** can easily compile and run?


    I asked a question was about the proper use of the JAI API. I was
    simply hoping someone with JAI knowledge could spot an obvious error.
    I could have omitted the code, and fantasized about openGL and
    directX, but it so happens it wouldn't have helped me a great big deal
    either in this case.

    JAI, tutorials, docs and examples can be downloaded freely by the way,
    so this is not something which "nobody else can easily compile and
    run". And to my taste, that wasn't the reason why I included the code
    in the first place. I was just trying to give readers an idea about
    the sort of thing I was doing. People proficient in JAI would
    certainly get it.

    > 2) Top-posting your reply to an earlier post (does not make
    > people well disposed to helping). It is considered better,
    > and clearer, to post 'in-line, with trimming'.
    >
    > * Much more chance of help, with an SSCCE.
    > <http://www.physci.org/codes/sscce.html>
    > ** No, I myself have never dealt with JAI, but to get
    > the attention and help of those that have, your best
    > bet is to make it easy for them.


    Fair enough, I was not aware I was causing difficult. I am posting
    through Google Groups, which makes it look ok while posting. My
    biggest problem was not that the code would not run, as it did. The
    problem is that JAI documentation is rather sketchy at best. Do a
    search on com.sun.medialib.mlib.mediaLibException and you will catch
    my drift.

    To give you at least something to take away from this discussion, JAI
    performed rather bad, compared to native c/c++ using Intel's IPP
    library, which is the clear winner in this case. JAI was about 200
    times slower, and that includes JNI overhead. Still, JAI was about 100
    times faster than the pojo algo described previously, contrary to what
    I said in my original post. The trick was indeed to warm up the JAI
    pipe before testing, and then lock the dimensions of the
    BufferedImage, as this would otherwise cause the library to re-
    allocate temporary storage.
    a0a, Oct 4, 2007
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bernhard Messerer
    Replies:
    1
    Views:
    666
    Roedy Green
    Aug 14, 2003
  2. Chuck Taylor
    Replies:
    1
    Views:
    8,268
    Chuck Taylor
    Sep 4, 2003
  3. cyril
    Replies:
    1
    Views:
    767
    cyril
    Sep 8, 2003
  4. Oracle3001
    Replies:
    0
    Views:
    723
    Oracle3001
    Oct 3, 2003
  5. Oracle3001

    Problem Running a JAI App

    Oracle3001, Oct 3, 2003, in forum: Java
    Replies:
    0
    Views:
    318
    Oracle3001
    Oct 3, 2003
Loading...

Share This Page