Recent

Author Topic: Free Pascal vs C++: The First Results Are In  (Read 26729 times)

mischi

  • Full Member
  • ***
  • Posts: 189
Re: Free Pascal vs C++: The First Results Are In
« Reply #30 on: December 30, 2019, 12:24:19 pm »
Code: Pascal  [Select][+][-]
  1.       if (Abs(WaveL[i][j]) > 1) then WaveL[i][j] := Sign(WaveL[i][j]) * 2 - WaveL[i][j];
Do you really need the inversion? If not, a branchless modulo might do the job without "if":
Code: Pascal  [Select][+][-]
  1. WaveL[i][j] := WaveL[i][j] mod 1;
Although I am not 100% sure whether negative values yield a negative remainder.
« Last Edit: December 30, 2019, 12:29:36 pm by mischi »

syntonica

  • Full Member
  • ***
  • Posts: 120
Re: Free Pascal vs C++: The First Results Are In
« Reply #31 on: December 30, 2019, 12:27:50 pm »
Here's an interesting tidbit.  In my original test, I had my lines interleaved like so:
Code: Pascal  [Select][+][-]
  1.       WaveL[i][j] := (WaveL[Wave1][j] * (1 - Knob1) + WaveL[Wave2][j + l] * Knob1) * 2;
  2.       if (Abs(WaveL[i][j]) > 1) then WaveL[i][j] := Sign(WaveL[i][j]) * 2 - WaveL[i][j];
  3.       WaveR[i][j] := (WaveR[Wave1][j] * (1 - Knob1) + WaveR[Wave2][j + l] * Knob1) * 2;
  4.       if (Abs(WaveR[i][j]) > 1) then WaveR[i][j] := Sign(WaveR[i][j]) * 2 - WaveR[i][j];
  5.  
By performing the both assignments prior to the tests like so:
Code: Pascal  [Select][+][-]
  1.       WaveL[i][j] := (WaveL[Wave1][j] * (1 - Knob1) + WaveL[Wave2][j + l] * Knob1) * 2;
  2.       WaveR[i][j] := (WaveR[Wave1][j] * (1 - Knob1) + WaveR[Wave2][j + l] * Knob1) * 2;
  3.       if (Abs(WaveL[i][j]) > 1) then WaveL[i][j] := Sign(WaveL[i][j]) * 2 - WaveL[i][j];
  4.       if (Abs(WaveR[i][j]) > 1) then WaveR[i][j] := Sign(WaveR[i][j]) * 2 - WaveR[i][j];
  5.  
I got significant speedups on both C and Pascal! I haven't looked at the assembly to see why.  I'm guessing that the peephole optimizer can more easily see it already has some needed values. But applying this to my C++ base, I got a tiny, but perceptible speed up in my full test project.

syntonica

  • Full Member
  • ***
  • Posts: 120
Re: Free Pascal vs C++: The First Results Are In
« Reply #32 on: December 30, 2019, 12:38:42 pm »
Code: Pascal  [Select][+][-]
  1.       if (Abs(WaveL[i][j]) > 1) then WaveL[i][j] := Sign(WaveL[i][j]) * 2 - WaveL[i][j];
Do you really need the inversion? If not, a branchless modulo might do the job without "if":
Code: Pascal  [Select][+][-]
  1. WaveL[i][j] := WaveL[i][j] mod 1;
Although I am not 100% sure whether negative values yield a negative remainder.
Wavefolding isn't a modulus operation. You can see a version of it here: https://www.keithmcmillen.com/blog/simple-synthesis-part-8-wavefolding/

Abs and Sign functions are ridiculously slow on computers and I try to avoid them whenever I can.  Having to do both per sample is painful!

mischi

  • Full Member
  • ***
  • Posts: 189
Re: Free Pascal vs C++: The First Results Are In
« Reply #33 on: December 30, 2019, 01:00:18 pm »
Wavefolding isn't a modulus operation. You can see a version of it here: https://www.keithmcmillen.com/blog/simple-synthesis-part-8-wavefolding/

Abs and Sign functions are ridiculously slow on computers and I try to avoid them whenever I can.  Having to do both per sample is painful!
Got the difference between mod and wave folding. too bad, it cannot be used. If abs and sign are hurting, separate if (WaveL[j] > 1) and if (WaveL[j] < -1) should still help.

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Free Pascal vs C++: The First Results Are In
« Reply #34 on: December 30, 2019, 02:05:44 pm »
Hi!

If abs is too slow give the following a try

Code: Pascal  [Select][+][-]
  1. type
  2. Tbits = Bitpacked array[0..63] of boolean;
  3. TDoubleRec = packed record
  4.        case boolean of
  5.        true : (B : TBits);
  6.        false: (D : Double);
  7.        end;
  8.  
  9. var Doub : TDoubleRec;
  10.  

To get the absolut value of the Double just do

Code: Pascal  [Select][+][-]
  1. Doub.D := -123.456;
  2. Doub.B[63] := false;
  3.  
  4.  

Perhaps it helps!

Winni
 

syntonica

  • Full Member
  • ***
  • Posts: 120
Re: Free Pascal vs C++: The First Results Are In
« Reply #35 on: December 30, 2019, 10:14:40 pm »
Hi!

If abs is too slow give the following a try

Code: Pascal  [Select][+][-]
  1. type
  2. Tbits = Bitpacked array[0..63] of boolean;
  3. TDoubleRec = packed record
  4.        case boolean of
  5.        true : (B : TBits);
  6.        false: (D : Double);
  7.        end;
  8.  
  9. var Doub : TDoubleRec;
  10.  

To get the absolut value of the Double just do

Code: Pascal  [Select][+][-]
  1. Doub.D := -123.456;
  2. Doub.B[63] := false;
  3.  
  4.  

Perhaps it helps!

Winni
Now that's creative! But I was apparently thinking of Abs(Integer) when I said that, where it has to take the 2's complement. With a float, it is indeed just a bit flip.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12645
  • FPC developer.
Re: Free Pascal vs C++: The First Results Are In
« Reply #36 on: December 30, 2019, 10:20:56 pm »
To be honest, abusing variant records/unions to escape typing in Pascal is at least 40 years old. If not 50.

Keep in mind that to use such tricks the result first has to be stored into memory (into the union record). This is already a bottleneck. A good intrinsic that operates on a registers should easily beat it.

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Free Pascal vs C++: The First Results Are In
« Reply #37 on: December 30, 2019, 11:07:23 pm »
To be honest, abusing variant records/unions to escape typing in Pascal is at least 40 years old. If not 50.

I learned that by reading the UCSD Sources. It was heavily used in the UCSD kernel.
But in those days packed and bitpacked were not necessary. They were the default.

Winni

syntonica

  • Full Member
  • ***
  • Posts: 120
Re: Free Pascal vs C++: The First Results Are In
« Reply #38 on: December 30, 2019, 11:43:16 pm »
FillQWord is likely to be the one of the Fill* routines that's the least optimized. I'd suggest you to use FillChar instead, which is usually the best optimized one.
Wow! I just tested it. FillByte/Char is about 1.5x faster!

Who do I call to complain?  :D

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Free Pascal vs C++: The First Results Are In
« Reply #39 on: December 31, 2019, 12:59:40 am »
Hi!

First the bad new: My attempt with bit flipping is only 2%..3% faster than abs.

Now the good news: I found a way to speed up sign around 25%.


Code: Pascal  [Select][+][-]
  1. var
  2. MinusPlus : array[false..true] of integer = (-1,+1);      
  3. ....
  4. if (Abs(WaveL[i][j]) > 1) then WaveL[i][j] := MinusPlus(WaveL[i][j]>=0) * 2 - WaveL[i][j];
  5.  

The zero-case of sign is not used in your code because you just tested the value > 1.

And if you need more distortion Fuzzers as hardware: I have made them when I was 15. Just two germanium AC 151r , some resistors, two potis  and 9 Volt ...

Winni

syntonica

  • Full Member
  • ***
  • Posts: 120
Re: Free Pascal vs C++: The First Results Are In
« Reply #40 on: December 31, 2019, 01:10:15 am »
Thanks! Unfortunately, I don't play much of anything anymore. My left hand is fairly useless.  :(

But with a gnarly fuzzbox, maybe nobody will notice?  O:-)

I've tried all the optimizations I've found. Unfortunately, nothing seems to make a dent.  So, I'm back to Square 1.

There's a huge chunk of CPU being used up front that has nothing to do with what my code is doing. It seems it's part of the runtime and I need to shut it off.




mr-highball

  • Full Member
  • ***
  • Posts: 233
    • Highball Github
Re: Free Pascal vs C++: The First Results Are In
« Reply #41 on: December 31, 2019, 01:18:10 am »

syntonica

  • Full Member
  • ***
  • Posts: 120
Re: Free Pascal vs C++: The First Results Are In
« Reply #42 on: December 31, 2019, 02:26:48 am »
I don't know if this will help at all?
https://forum.lazarus.freepascal.org/index.php?topic=15880.0
I think this is just about removing a data table from the executable. I'm not concerned about size.

Yet.  >:D

syntonica

  • Full Member
  • ***
  • Posts: 120
Re: Free Pascal vs C++: The First Results Are In
« Reply #43 on: December 31, 2019, 03:13:28 am »
I found the culprit and never in my wildest dreams would I imagine it was the cause. A single, solitary instruction...

Floor.

Yes. Explicitly turning a Double into an Integer apparently takes about 5,000,000 cycles.  :o

Changing all my Floors into Truncs with the implicit conversion to Integer changed my numbers.

Instead of 7% Idle and 12% Run, I'm now getting...

(wait for it)

5% Idle and 6.5% Run!

Against the C++ 3%/4.5%, color me a Happy Camper!  :D

Free Pascal (except for Floor...) is a winner!

Thanks for all of your help and suggestions! Now to try and shave off that extra 2%...  ;)

As an aside: Would this be considered a bug? In my test, Trunc was 2x faster where they should be more or less identical in speed.

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: Free Pascal vs C++: The First Results Are In
« Reply #44 on: December 31, 2019, 10:26:31 am »
People who are still confusing high level languages with code generation should be banned from programming. >:( >:D

Happy New Year! :D
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

 

TinyPortal © 2005-2018