Added a good example for range vs while vs pointer arithmetic

master
bixb922 2024-05-04 10:26:55 -04:00
rodzic d927ee8951
commit 9b313453b3
1 zmienionych plików z 49 dodań i 2 usunięć

@ -557,7 +557,7 @@ def function_returns_object(x)->object:
## Range vs. while
`range()` does work under viper, so you could write: ```for x in range(10)```. It is a bit faster to use a while loop, with viper ints for j, limit and step.
`range()` does work under viper, so you could write: ```for x in range(10)```. It is a bit faster to use a while loop, with viper ints for j, limit and step.
```py
limit:int = 100
step:int = 2
@ -567,6 +567,53 @@ def function_returns_object(x)->object:
j += step
```
You can also use pointer arithmetic to get rid of a counter to control the while loop, and that's even faster! Using pointer arithmetic also enables to use `p[0]` instead of `p[I]`, again an improvement. The timing was done on a 80Mhz Cortex-M3 in the W600:
```py
from array import array
from time import ticks_us, ticks_diff
a = array('i', (2*i+1 for i in range(10000)))
@micropython.viper
def vip_add1(p: ptr32, l: int) -> int:
r:int = 0
for k in range(l): # range() works, but is not fastest
r += p[k] # accessing with p[i]
return r
@micropython.viper
def vip_add2(p: ptr32, l: uint) -> int:
r:int = 0
k:uint = uint(0)
while k < l: # a while loop is faster
r += p[k] # accessing with p[i]
k += 1
return r
@micropython.viper
def vip_add3(p: ptr32, l: uint) -> int:
r:int = 0
pstop: uint = uint(p) + 4*l
while uint(p) < pstop: # directly looping the pointer to the array and indexing
r += p[0] # with p[0] is faster than accessing with p[i]
p = ptr32(uint(p) + 4) # casts necessary because the types are fixed in viper
return r
t0 = ticks_us()
sum1 = vip_add1(a, len(a)) # --> 100000000
t1 = ticks_us()
sum2 = vip_add2(a, len(a)) # --> 100000000
t2 = ticks_us()
sum3 = vip_add3(a, len(a)) # --> 100000000
t3 = ticks_us()
print('vip_add1:', sum1, 'time:', ticks_diff(t1, t0)/10000, 'µs per it.') # --> 0.7064 µs
print('vip_and2:', sum2, 'time:', ticks_diff(t2, t1)/10000, 'µs per it.') # --> 0.5767 µs
print('vip_and3:', sum3, 'time:', ticks_diff(t3, t2)/10000, 'µs per it.') # --> 0.3635 µs
```
## Global variables
If you need to do integer arithmetic with a global variable, this works:
```py
@ -746,7 +793,7 @@ Step by step with a real problem: https://luvsheth.com/p/making-micropython-comp
The MicroPython tests for viper have some examples, see all cases prefixed by "viper_": https://github.com/micropython/micropython/tree/master/tests/micropython
The issue that gave origin to this wiki page, with interesting discussions: [#14297](https://github.com/orgs/micropython/discussions/14297)
The issue that gave origin to this wiki page, with interesting discussions. This also is the source for some examples here: [#14297](https://github.com/orgs/micropython/discussions/14297)
Search https://forum.micropython.org and https://github.com/orgs/micropython/discussions for viper. There are many insights and examples.