LoginLogin

faster FOR loop

Root / Submissions / [.]

12Me21Created:
Often people use something like FOR I=0 TO LEN(ARRAY)-1 to loop through an array, but this isn't optimal since it checks the length on each pass through the loop. A simple fix is to do: VAR L=LEN(ARRAY)-1:FOR I=0 TO L, but there is a better way: FOR I=LEN(ARRAY)-1 TO 0 STEP -1. This will only check the length once, and it doesn't have to set an extra variable. It will loop backwards, but that's fine if you're making an uppercase conversion function or something.

Yeah, I've thought about that But I'm sure LEN(ARRAY) only fetches a quick value, no real computations are done, so the changes would be negligible But, when a for loop has a huge number of iterations to do, function calls can be a lot more computationally expensive (from experience) so this would be a smart trick to consider.

I thought step -1 was actually really slow. Like... it actually runs twice as slow as a regular empty for loop or something. Or was that PTC?

Replying to:haloopdy
I thought step -1 was actually really slow. Like... it actually runs twice as slow as a regular empty for loop or something. Or was that PTC?
I think it's about the same speed as normal.

actually, you shouldn't define L and just do this: FOR I = LEN(ARRAY)-1 TO 0 STEP -1 because defining takes time

Replying to:DFrost
actually, you shouldn't define L and just do this: FOR I = LEN(ARRAY)-1 TO 0 STEP -1 because defining takes time
One other thing to mention: having a step of two is faster than a step of one:
DEF whatever N
'stuff
END
FOR I = LEN(ARRAY) - 2 TO 0 STEP -2
 CALL "whatever",ARRAY[I]
 CALL "whatever",ARRAY[I+1]
NEXT

Replying to:DFrost
actually, you shouldn't define L and just do this: FOR I = LEN(ARRAY)-1 TO 0 STEP -1 because defining takes time
>you shouldn't define L and just do this because defining takes time you always post the dumbest non-help The page suggests not defining L because there's a workaround, but um, yes, pre-calculating an end value (if appropriate) is going to be faster than leaving an expression that has to be evaluated every iteration. Variable definition and lookup is almost never going to be slower than evaluating a variable expression. The only exception I can think of is an actual table for functions that are built in, e.g. sine lookup table is slower than just calling SIN() evaluating two cells at once STILL doesn't make sense usually. If you're worried about FOR overhead, why not just unroll the loop entirely? In any case, stepping by 2 only works if it is given that ARRAY will be even. If you do know some special properties about the array then yes, it is possible to operate on more than one cell per iteration... but I would never think of this in terms of performance.

Replying to:DFrost
actually, you shouldn't define L and just do this: FOR I = LEN(ARRAY)-1 TO 0 STEP -1 because defining takes time
you're right

Replying to:DFrost
actually, you shouldn't define L and just do this: FOR I = LEN(ARRAY)-1 TO 0 STEP -1 because defining takes time
actually... I may have to take back what I said about partial unrolling. I tested using this code:
DIM A[0], K%, M%
M% = MILLISEC
FOR I% = 0 TO 1000000
  PUSH A, RND(512)
NEXT
?"array generation took ";MILLISEC-M%

?"Step 1"
M% = MILLISEC
FOR I% = 999999 TO 0 STEP -1
  K% = A[I%]
NEXT
?MILLISEC - M%

?"Step 2"
M% = MILLISEC
FOR I% = 999999 TO 0 STEP -2
  K% = A[I%]
  K% = A[I% - 1]
NEXT
?MILLISEC - M%
array generation took 3954
Step 1
2163
Step 2
1699
Results were consistent on cold run and 100000 elements But maybe I messed something up, so someone should check me. Still, the overhead only matters on huge arrays. The difference scaled down to 40ms at 100000 elements.

Replying to:DFrost
actually, you shouldn't define L and just do this: FOR I = LEN(ARRAY)-1 TO 0 STEP -1 because defining takes time
That is a VERY important thing I learned a while back

Replying to:DFrost
actually, you shouldn't define L and just do this: FOR I = LEN(ARRAY)-1 TO 0 STEP -1 because defining takes time
it looks OK to me. K% is set once for every step(twice for 2 steps,once for 1 step) so it is an even 'fight' Also, I hope this is perfect code because this could help Simeon with SIM.3D