HP Forums

Full Version: Can my CAS Savage benchmark be improved? CAS newbie
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
When I first got my HP Prime, I implemented the Savage benchmark and then unsuccessfully tried to implement it in CAS, but never got to see the perfect 2500 result...
I was busy learning about my new Prime rather than the CAS, and somewhat put off further experimentation by the corruption referred to in this old thread - I didn't want to risk my new toy Smile: (the corruption referred to is long gone).

http://www.hpmuseum.org/forum/thread-195...ght=savage

I've just tried again and now see the perfect 2500 result, but wonder if the time can be improved.

Corrected code: (updated. To fix bad syntax)

Code:

SAVAGED()
 BEGIN
  A:=1;
  FOR I FROM 1 TO 2499 DO
    A:=TAN(ATAN(e^(LN(√(A*A)))))+1
  END;
 END;

#CAS
SAVAGEDCAS1(f):=
 BEGIN
  A:=1;
  FOR I FROM 1 TO 2499 DO
    A:=TAN(ATAN(e^(LN(√(A*A)))))+1
  END;
  RETURN (A);
 END;
#END

SAVAGEDCAS2()
 BEGIN
  A:=1;
  FOR I FROM 1 TO 2499 DO
    A:=CAS(TAN(ATAN(e^(LN(√(A*A))))))+1;
    //RECT_P();
    //TEXTOUT_P(A,0,100)
  END;
  //WAIT;
  RETURN A;
 END;

EXPORT SAVAGE()
 BEGIN
  LOCAL RR;
  PRINT();
  PRINT({"Prime: ",TEVAL(RR:=SAVAGED()),RR});
  PRINT({" CAS1 : ",TEVAL(RR:=SAVAGEDCAS1("")),RR});
 
  PRINT({" CAS2 : ",TEVAL(RR:=SAVAGEDCAS2()),RR});
 //RETURN {TEVAL(RR:=SAVAGED()),RR,TEVAL(RR:=SAVAGEDCAS()),RR};
 END;

My working code (CAS2) runs a FOR loop repeatedly calling CAS and I thought that taking the CAS out of the FOR loop ought to speed things up.

But my #CAS (CAS1) version is consistently slower.

I haven't used #CAS much yet, so I'm probably not doing it right.
Can #CAS1 be made faster than CAS2?
MAKELIST is faster than FOR loops.

Why the call to exact()?

Your CAS1 (and CAS2) function appears to use the global variable A, but is doing exact calculations. I wonder if there is overhead from converting between CAS objects (the expression in your calculation) and non-CAS objects (the global variable A, which is a likely a "Home" object and encoded in BCD).
The call to exact was just something I tried to see if it affected timings.

Changing from PPL A to CAS a improved the timings, and changing from Global variables to local improved timings further.

I tried using a MAKELIST, but although it was quicker my implementation didn't give the correct answer.

Unfortunately, my Android App has just lost all its programs, so I've got some re-typing to do.
Here's my latest code, using local variables and L1...
My attempt at using MAKELIST doesn't give the desired result, but the other versions are fine.

Code:


SAVAGEPPL()
 BEGIN
  LOCAL AA;
  AA:=1;
  FOR I FROM 1 TO 2499 DO
    AA:=TAN(ATAN(EXP(LN(√(AA*AA)))))+1
  END;
 END;

#CAS
SAVAGECAS1(f):=
 BEGIN
  LOCAL aa;
  aa:=1;
  FOR I FROM 1 TO 2499 DO
    aa:=TAN(ATAN(EXP(LN(√(aa*aa)))))+1
  END;
  RETURN (aa);
 END;
#END

SAVAGECAS2()
 BEGIN
  LOCAL aa;
  aa:=1;
  FOR I FROM 1 TO 2499 DO
    aa:=CAS(TAN(ATAN(EXP(LN(√(aa*aa))))))+1;
  END;
  RETURN aa;
 END;

SAVAGEML()
 BEGIN
  L1:={1};
  
  L1:=MAKELIST(CAS(TAN(ATAN(EXP(LN(√(L1(0)*L1(0)))))))+1,I,1,2499);
 
  RETURN L1(0);
 END;


EXPORT SAVAGE()
 BEGIN
  LOCAL RR;
  PRINT();
  PRINT({" PPL1: ",TEVAL(RR:=SAVAGEPPL()),RR});
  PRINT({" CAS1: ",TEVAL(RR:=SAVAGECAS1("")),RR});
 
  PRINT({" CAS2: ",TEVAL(RR:=SAVAGECAS2()),RR});
  PRINT({"ML1:WRONG: ",TEVAL(RR:=SAVAGEML()),RR});
  PRINT("DONE");
 //RETURN {TEVAL(RR:=SAVAGED()),RR,TEVAL(RR:=SAVAGEDCAS()),RR};
 END;
I have now placed this code into the software library for ease of reference.
http://www.hpmuseum.org/forum/thread-962...ght=savage
(04-04-2017 08:22 PM)StephenG1CMZ Wrote: [ -> ]Unfortunately, my Android App has just lost all its programs, so I've got some re-typing to do.

In case you weren't aware: you can use the connectivity kit to copy (back up) programs between your Android device, physical Prime and PC emulator.
(04-05-2017 09:51 AM)StephenG1CMZ Wrote: [ -> ]Here's my latest code, using local variables and L1...
My attempt at using MAKELIST doesn't give the desired result, but the other versions are fine.

Code:


SAVAGEPPL()
 BEGIN
  LOCAL AA;
  AA:=1;
  FOR I FROM 1 TO 2499 DO
    AA:=TAN(ATAN(EXP(LN(√(AA*AA)))))+1
  END;
 END;

#CAS
SAVAGECAS1(f):=
 BEGIN
  LOCAL aa;
  aa:=1;
  FOR I FROM 1 TO 2499 DO
    aa:=TAN(ATAN(EXP(LN(√(aa*aa)))))+1
  END;
  RETURN (aa);
 END;
#END

SAVAGECAS2()
 BEGIN
  LOCAL aa;
  aa:=1;
  FOR I FROM 1 TO 2499 DO
    aa:=CAS(TAN(ATAN(EXP(LN(√(aa*aa))))))+1;
  END;
  RETURN aa;
 END;

SAVAGEML()
 BEGIN
  L1:={1};
  
  L1:=MAKELIST(CAS(TAN(ATAN(EXP(LN(√(L1(0)*L1(0)))))))+1,I,1,2499);
 
  RETURN L1(0);
 END;


EXPORT SAVAGE()
 BEGIN
  LOCAL RR;
  PRINT();
  PRINT({" PPL1: ",TEVAL(RR:=SAVAGEPPL()),RR});
  PRINT({" CAS1: ",TEVAL(RR:=SAVAGECAS1("")),RR});
 
  PRINT({" CAS2: ",TEVAL(RR:=SAVAGECAS2()),RR});
  PRINT({"ML1:WRONG: ",TEVAL(RR:=SAVAGEML()),RR});
  PRINT("DONE");
 //RETURN {TEVAL(RR:=SAVAGED()),RR,TEVAL(RR:=SAVAGEDCAS()),RR};
 END;

If you used AA as a variable because you didn't know it, you can still use A as a local variable.

LOCAL A;
Tom,
I am in the habit of using two-letter names when I use PPL.

" LOCAL A;" would obscure access to global A (or worse, risk the code accessing global A, if in one Procedure you forgot to include the "Local"). There can also be confusion with some single-letter names, such as M, which is a matrix not a real. Although not required, I find it much easier to make my own variable.

When benchmarking, it is possible that accessing " global A " might be quicker than "LOCAL AA"...
But then running the benchmark might change a value that other programs are depending on, and would need wrapping up inside a save/restore.
Hello,

'A' or 'AA' should make absolutely no noticeable difference.

Cyrille
Here's my own opinion about optimizing benchmark programs: don't do it (except...)

This would give you a true benchmark of one firmware vs the next -- because the benchmark is literally unchanged. Any performance differences can therefore be completely attributed to firmware changes. If you are constantly optimizing your benchmark, then one set of tests will no longer be comparable to another set of tests -- especially across different firmwares (which is what you would want if you are trying to benchmark firmwares).

Instead, if you can do any optimization, simply create a new function with a similar name so that you still have the old function to cross reference against older firmware. For example, if BENCH1 is a program that can then be optimized, keep BENCH1 exactly as is and make a copy to BENCH2, and add the optimizations to BENCH2. Then your benchmark suite will not only enable you to see performance differences between different techniques, but it will also enable you to consistently compare firmware differences as well.

EDIT: Also, to use MAKELIST for a for loop:

Code:

FOR J FROM 1 TO 1000 DO
  ... code for FOR loop here ...
END;

Can be converted to:

Code:

MYFORLP()
BEGIN
  ... code for FOR loop here ...
END;


EXPORT MAIN()
BEGIN
MAKELIST(MYFORLP(),I,1,2499);
END;
Han, thank you for your comments and tips on how to use MAKELIST for a FOR.
I have tried it, but for the Savage benchmark I find the timing is not consistently better - on Android, sometimes FOR is faster and sometimes MAKELIST.
http://www.hpmuseum.org/forum/thread-962...l#pid85168

I agree that optimising benchmarks can be a bad idea - but I cheat a little by starting my version numbers at 0.1, and until it reaches version 1 I think some changes can be expected.

By then, I might have discovered a clear winner in terms of speed and accuracy.
Reference URL's