1

I'm trying to squeeze every optimization possible from a particularly heavy function. Currently, there is this part:

//m: array of Integer;
//We get it from some other part
N:= Length(m)-1;
for i:=0 to N do
   m[i]:=-m[i];

I need to do this twice per loop (i.e. with two arrays). So, I wonder: is there a better way?

Maybe bitwise operation? I don't know much about them. Will it be faster? How to make it quick?

Should I even try to optimize this part, or it is fine enough?

Alexander
  • 388
  • 1
  • 12
  • It is super fast as it is. (But maybe you don't know about the [`High`](http://docwiki.embarcadero.com/Libraries/en/System.High) function?) You need to measure to find out where the bottlenecks are in your app. I seriously doubt the above code is a bottleneck. Unless -- of course -- there is a way to solve your actual problem without changing the sign of every integer in an array. – Andreas Rejbrand Aug 16 '20 at 18:29
  • @AndreasRejbrand Sorry, I didn't get it. How High() could help me? – Alexander Aug 16 '20 at 18:31
  • `High(m)` looks nicer than `Length(m) - 1`. You save six characters. And semantically, `High` is exactly what you want -- the last index. (Just like in English, "go to the last house on the street" sounds more natural than "go to the house with index equal to the number of houses minus one".) It's unlikely to make your code faster, though. – Andreas Rejbrand Aug 16 '20 at 18:32
  • Oh thanks. Also, I just found out the way to avoid the sign reversing... Should I delete my question? – Alexander Aug 16 '20 at 18:35
  • 1
    If you want to. Maybe someone has some nice assembly tricks to share, but in any case, you really shouldn't try to optimize code without first measuring it and determining the actual bottlenecks. Your code in this Q will complete within a tiny fraction of a second even with N = 10 000 000. – Andreas Rejbrand Aug 16 '20 at 18:37

1 Answers1

0

Like Andreas mentionned in comment, that would probably be premature/pointless optimisation. But you can try

//var
//  pInt, pLast : PInteger;
pInt := @m[0];
pLast := @m[high(m)];
while NativeUInt(pInt) <= NativeUInt(pLast) do
begin
  pInt^ := -pInt^;
  Inc(pInt);
end;

That should work (Can't test it right now...). I believe it should compile to less operations... Assuming the compiler doesn't already optimise your original code in a similar way.

That being said, it's not because you are doing less that you're going to be faster. At that level of optimisation, branch prediction, cache misses and... probably quite a few other factors I don't know about comes into play.

I don't really advise doing that kind of optimisation (unless that loop is proven to be a mission-critical bottleneck), but for educational purpose, that can be interesting.

Ken Bourassa
  • 6,363
  • 1
  • 19
  • 28
  • I don't see the point of this code. It's harder to read and likely is slower. – David Heffernan Aug 17 '20 at 14:33
  • I just tested it... Depending on compiler options, worst case this code takes 15% longer (compared to original code with same options), best case cuts execution time in half. I've seen no combination of options that makes this slower if Optimization is ON. – Ken Bourassa Aug 17 '20 at 16:19