Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vector Distance Calculation in Java - Optimization

As part of image processing function I need to calculate a sum of squares between two lines in images.

This part of the code takes 96% of the run time:

for(int dx=0;dx<size;dx++) {
    int left = a[pa+dx];
    int right = b[pb+dx];
    int diff = (left & 0xFF) - (right & 0xFF);
    sum += diff*diff;
}

where:

  • a, b are of type byte[]
  • sum is long
  • size is int and generally has big values (around 400)

Running Java 7 64 bit. I've tried to replace a[pa+dx] with stuff like a[pa++] the performance is not better.

Exactly the same code written in C++ that does exactly the save runs overall twice faster(!) and as far as I see there should be no significant reasons why wouldn't this Java code be as fast especially when boundary checks can be moved out of the loop by the compiler.

How can this stuff be optimized to perform as well as C++ code - as finally it is integer arithmetic it shouldn't be much slower in Java

Edit: C++ sample looks like:

unsigned char const *srcptr=&a[pa];
unsigned char const *tgtptr=&b[pb];
for(int dx=0;dx < size;dx++) {
    int p1=*srcptr++;
    int p2=*tgtptr++;
    int diff = p1 - p2;
    sum += diff * diff;
}

I'd like to find out how to make HotSpot optimizer to create a code that as fast as the C++ code shown above, finally it is quite simple and easy to optimize lines.

like image 743
Artyom Avatar asked May 23 '26 08:05

Artyom


1 Answers

It's only small, but you don't need the & 0xFF to calculate the difference: The difference will be the same signed or unsigned.

100 - -1 = 101  // signed
228 - 127 = 101 // unsigned

Then it would be tighter loop body:

for (int dx = 0; dx < size; dx++) {
    int diff = a[pa+dx] - b[pb+dx];
    sum += diff*diff;
}

Edit:

There seems to be some confusion regarding signed vs unsigned byte arithmetic. If you doubt they are the same, execute this:

byte a = -128;
byte b = 127;
int diff = a - b;
System.out.println(diff); // -255

a = 127;
b = -128;
diff = a - b;
System.out.println(diff); // 255

The reason the range of diff values is greater than byte (-128..127), is that java automatically widens byte to int before the calculation because the destination variable is an int.

like image 116
Bohemian Avatar answered May 24 '26 20:05

Bohemian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!