HP Forums
Optimizing HPP program - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html)
+--- Forum: HP Prime (/forum-5.html)
+--- Thread: Optimizing HPP program (/thread-12585.html)



Optimizing HPP program - Oulan - 03-08-2019 08:45 AM

Trying to speed up code I found this strange behavior:

With the following program named test01
Code:

#pragma mode(separator(.,;) integer(h32))

LOCAL ff00() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff01() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff02() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff03() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff04() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff05() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff06() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff07() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff08() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff09() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff10() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff11() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff12() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff13() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff14() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff15() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff16() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff17() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff18() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff19() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff20() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff21() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff22() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff23() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff24() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff25() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff26() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff27() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff28() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff29() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff30() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff31() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff32() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff33() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff34() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff35() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff36() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff37() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff38() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff39() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff40() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff41() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff42() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff43() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff44() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff45() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff46() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff47() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff48() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff49() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff50() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff51() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff52() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff53() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff54() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff55() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff56() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff57() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff58() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff59() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff60() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff61() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff62() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff63() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff64() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff65() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff66() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff67() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff68() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff69() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff70() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff71() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff72() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff73() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff74() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff75() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff76() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff77() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff78() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff79() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff80() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff81() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff82() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff83() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff84() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff85() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff86() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff87() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff88() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff89() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff90() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff91() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff92() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff93() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff94() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff95() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff96() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff97() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff98() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;
LOCAL ff99() BEGIN FOR I FROM 1 TO 99 DO A:=A+1; END;END;

LOCAL f0() BEGIN A:=10;END;
LOCAL f1() BEGIN A:=20;END;
LOCAL f2() BEGIN A:=30;END;
LOCAL f3() BEGIN A:=40;END;
LOCAL f4() BEGIN A:=50;END;
LOCAL f5() BEGIN A:=60;END;
LOCAL f6() BEGIN A:=70;END;
LOCAL f7() BEGIN A:=80;END;
LOCAL f8() BEGIN A:=90;END;
LOCAL f9() BEGIN A:=100;END;
LOCAL fA() BEGIN A:=110;END;
LOCAL fB() BEGIN A:=120;END;
LOCAL fC() BEGIN A:=130;END;
LOCAL fD() BEGIN A:=140;END;
LOCAL fE() BEGIN A:=150;END;
LOCAL fF() BEGIN A:=160;END;

LOCAL ff={'f0','f1','f2','f3','f4','f5','f6','f7','f8','f9','fA','fB','fC','fD','​fE','fF'};

LOCAL sel00() BEGIN
 CASE
  IF J=0 THEN A:=10; END;
  IF J=1 THEN A:=20; END;
  IF J=2 THEN A:=30; END;
  IF J=3 THEN A:=40; END;
  IF J=4 THEN A:=50; END;
  IF J=5 THEN A:=60; END;
  IF J=6 THEN A:=70; END;
  IF J=7 THEN A:=80; END;
  IF J=8 THEN A:=90; END;
  IF J=9 THEN A:=100; END;
  IF J=10 THEN A:=110; END;
  IF J=11 THEN A:=120; END;
  IF J=12 THEN A:=130; END;
  IF J=13 THEN A:=140; END;
  IF J=14 THEN A:=150; END;
  DEFAULT A:=160;
 END;
END;

LOCAL sel01() BEGIN
 CASE
  IF J=0 THEN f0(); END;
  IF J=1 THEN f1(); END;
  IF J=2 THEN f2(); END;
  IF J=3 THEN f3(); END;
  IF J=4 THEN f4(); END;
  IF J=5 THEN f5(); END;
  IF J=6 THEN f6(); END;
  IF J=7 THEN f7(); END;
  IF J=8 THEN f8(); END;
  IF J=9 THEN f9(); END;
  IF J=10 THEN fA(); END;
  IF J=11 THEN fB(); END;
  IF J=12 THEN fC(); END;
  IF J=13 THEN fD(); END;
  IF J=14 THEN fE(); END;
  DEFAULT fF();
 END;
END;

LOCAL sel02() BEGIN
 EVAL(ff(J));
END;

LOCAL tt00() BEGIN
 B:=0;
 FOR I FROM 1 TO 1000000 DO
  J:=(I MOD 16);sel00();B:=B+A;
 END;
 PRINT(B);
END;

LOCAL tt01() BEGIN
 B:=0;
 FOR I FROM 1 TO 1000000 DO 
  J:=(I MOD 16);sel01();B:=B+A;
 END;
 PRINT(B);
END;

LOCAL tt02() BEGIN
 B:=0;
 FOR I FROM 1 TO 1000000 DO
  J:=(I MOD 16)+1;sel02();B:=B+A;
 END;
 PRINT(B);
END;

EXPORT test01()
BEGIN
 PRINT();
 PRINT(TEVAL(tt00));
 PRINT(TEVAL(tt00));
 PRINT(TEVAL(tt01));
 PRINT(TEVAL(tt01));
 PRINT(TEVAL(tt02));
 PRINT(TEVAL(tt02));
END;

The speed of tt02 function depend on the number of local functions defined in the program.

On a virtual Prime I got an average of 4.7 seconds for the TEVAL(tt02).

When I remove the 100 useless local ffxx functions in the program I got an average of 3.7 seconds for the TEVAL(tt02).

TEVAL(tt00) is still at 5.5 seconds and TEVAL(tt01) is still at 5.7 seconds.

On a real program the use of EVAL(list(I)) is even slower than using CASE constructions, which is a very strange behavior.

I got the same behavior on a real Prime too.

More fun about speed:
Use the following program
Code:

#pragma mode( separator(.,;) integer(h32) )
local b:=0;
LOCAL tt0() BEGIN
 local a:=0;
 FOR a FROM 1 TO 1000000 DO 
 END;
END;
LOCAL tt1() BEGIN
 FOR b FROM 1 TO 1000000 DO 
 END;
END;
LOCAL tt2() BEGIN
 FOR A FROM 1 TO 1000000 DO 
 END;
END;

EXPORT test02()
BEGIN
 PRINT();PRINT("");
 PRINT(TEVAL(tt0));
 PRINT(TEVAL(tt0));
 PRINT(TEVAL(tt1));
 PRINT(TEVAL(tt1));
 PRINT(TEVAL(tt2));
 PRINT(TEVAL(tt2));
END;
Run it several times and look at the numbers ... sometimes 10 seconds are lost somewhere ...

Generally the bevahior is VERY erratic, even for a such complex system as the PRIME (it is my own opinion). I agree that some stuff must be running at lower level than USER use but such erratic behavior is somewhat strange (nothing very reproducable).


RE: Optimizing HPP program - cyrille de brébisson - 03-11-2019 06:53 AM

Hello,

Well, your program is a little bit screwy, so you get strange behaviors :-)

Anyhow, If you want to speed up a program, the main guidelines are:
- use local variables, not globals (locals are faster).
- your 100 "dummy" function are of course slowing down any lookup of non local variables as they enter relatively high in the variable precedence order and the lookup is (sorry about this) linear (the name list is not sorted). So adding 100 extra items to look through will slow down any search that has to traverse it.
- EVAL is a slow function.
- Put loops IN function, not function in loops. I know that it makes things less readable, but for (100) call_function end; is was slower than a function that does function(params, number of loops) for (number) do operation... This is mostly important for inner critical loops of course. Outside loops are much less impacted.

Cyrille


RE: Optimizing HPP program - Oulan - 03-11-2019 08:47 AM

Yes, this program is a bit strange but is related to 'Major bug on G2'
  • yes, I know that local variable are faster but 'persistent' such as 'A..Z' are even faster, I use them as 'C register qualified' essentially in 'FOR' loops. See second program to test loop variables. local is at 4.0 seconds, global at 4.5 seconds and persistent at 2.4 seconds.
  • the local functions are here to avoid the tests in the CASE structure (average of 8 in this example), when your program is short with few functions (under 20), EVAL is a winner. I made a small test and when I saw this I tried on a larger scale but due to linear search, it does not scale, too bad.
  • see previous point. With few functions and globals EVAL is a real winner. Test without the 100 local functions is at 3.7 seconds with EVAL and 5.5 seconds with direct code in the CASE structure.
  • FOR loops are just here to make some load, real functions can bee seen in 'Major bug on G2'

So if I understand correctly, {'f0','f1',..} is not stored as list of 'direct_reference' to the functions? but as "string" and a search is done in the unordered list of local stuff {local variables + local functions} or is it the {}(index) which is done in linear time ? (I don't think so, in this case the search time should be constant).

If so, this mean that you should not declare too much local stuff, perhaps it is better to use Lists to hide the search at a second level. And we should break the app with smaller units (more hpprgm outside the main hppgm of the app) ? But the problem of the exported variables will raise again (and also the problem of circular use of exported variables (egg&chicken pb)).

Btw did you reproduce the bug in 'Major bug on G2' ? It can need several runs before hitting the 'reboot'

Anyway I am very pleased with the prime, HPP langage is quite nice and rather fast (around the level of non optimized C code on a TI83PCE) which is really good.

I will try other way to optimize (perhaps list constructions ...)

EDIT:

I made other tests on this kind of program. Conclusion is: any kind of call (fxx(), EVAL('fxx')) will take more time if you have more functions defined. Even if you call the first function or the last one ... this is strange I don't completly understand this behavior ... (perhaps linked to the hiden parser and structure).

Olivier