Page 1 of 1

Faster Array Element Assignment - Solved

Posted: Mon Jan 10, 2022 1:58 am
by samneggs
Looking for the faster way to assign elements to a small array. Is there an native way to do this? arry[0:2] <-- 100,200,300
The idea is that the values 100,200,300 would be constantly changing.
Here is a way for 1-3 elements that is up to 1.45x faster than the traditional way.

Code: Select all

import array

a=array.array('i',(0,0,0))

@micropython.asm_thumb        
def array_asm(r0,r1,r2,r3): #r0=array, r1=value1, r2=value2, r3=value3
    str(r1, [r0, 0]) # strh(r1, [r0, 0])  for 2 byte arrays, eg. 'h' or 'H'
    str(r2, [r0, 4]) # strh(r2, [r0, 2]) 
    str(r3, [r0, 8]) # strh(r2, [r0, 4]) 
    
array_asm(a,100,200,300)
    
 #traditional way
 a[0] = 100
 a[1] = 200
 a[2] = 300   
The asm_thumb is limited to 4 parameters so if there was a way to embed an array address in the code all four could be used.

Sam

Re: Faster Array Element Assignment (not Lists)

Posted: Tue Jan 11, 2022 8:57 am
by pythoncoder
Unfortunately there isn't. You can put immediate data in code, but this won't help because the array address isn't constant. The only way I've found of overcoming the 4-arg limit is putting the extra args in an array - which in your case rather defeats the object ;)

Re: Faster Array Element Assignment (not Lists)

Posted: Wed Jan 12, 2022 2:27 am
by samneggs
Thanks for the reply. I was hoping I overlooked some simple method of loading an array.
Sam

Re: Faster Array Element Assignment - Solved

Posted: Thu Jan 13, 2022 2:01 am
by samneggs
I figured out a way of loading up to 16 arguments in one line.
Here is four at one time but it can be repeated four times.
There is 1.6x speed improvement over repeating this four times: my_array[0] = my_value.

The store_asm() function takes four parameters and returns the memory address that they are stored at.
Then that address is fed into my main assembly routine. It sounds the same as feeding the routine an array right?
But each parameter can be changed on a single line. So this could be possible:

my_assembly(store_asm1(1,2,3,4),store_asm2(5,6,7,9),store_asm3(9,10,11,12),store_asm4(13,14,15,16))

Sam

Code: Select all

from time import sleep_ms, sleep_us, ticks_diff, ticks_us, sleep
import array

@micropython.asm_thumb
def store_asm(r0,r1,r2,r3):
    mov(r4,pc) 
    b(SKIP)
    data(2,1,2,3,4)    
    align(2)
    label(SKIP)
    strh(r0,[r4,0])
    strh(r1,[r4,2])
    strh(r2,[r4,4])
    strh(r3,[r4,6])
    mov(r0,r4)

@micropython.asm_thumb
def retrieve_asm(r0):
    ldrh(r3,[r0,6])
    ldrh(r2,[r0,4])
    ldrh(r1,[r0,2])
    ldrh(r0,[r0,0])
    
def asm_test():
    gticks=ticks_us()
    for i in range(1000):
        x=retrieve_asm(store_asm(5,6,7,8))
    print(ticks_diff(ticks_us(), gticks),x)


def array_test():
    gticks=ticks_us()
    for i in range(1000):
        a[0]=5
        a[1]=6
        a[2]=7
        a[3]=8
    print(ticks_diff(ticks_us(), gticks))


a=array.array('h',(1,2,3,5))
array_test()
asm_test()