ulab, or what you will - numpy on bare metal

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: ulab, or what you will - numpy on bare metal

Post by v923z » Fri Nov 01, 2019 1:57 pm

Hi all,
Damien wrote:
Fri Nov 01, 2019 10:51 am
I would suggest changing all occurrences of "float" to "mp_float_t", that will allow it to compile for all targets with the FP precision supported/configured by the target.
Done. I have also uploaded compiled firmware for pybv11, and pybd_sf6 to https://github.com/v923z/micropython-ulab/releases. With pybd_sf2, and pybd_sf3, I get a linker error

Code: Select all

LINK build-PYBD_SF3/firmware.elf
arm-none-eabi-ld: build-PYBD_SF3/firmware.elf section `.text' will not fit in region `FLASH_APP'
arm-none-eabi-ld: region `FLASH_APP' overflowed by 4216 bytes
make: *** [Makefile:514: build-PYBD_SF3/firmware.elf] Error 1
but I presume, there is not much one can do here. I could make the module configurable (if you don't need fft, or polyfit, or linalg, you could then exclude those), but I have to say that the largest chunk is the base module, ndarray.c, so with configuration, one can't save too much space. Let me know, if you deem a different approach more reasonable!

Cheers,
Zoltán

User avatar
mathieu
Posts: 88
Joined: Fri Nov 10, 2017 9:57 pm

Re: ulab, or what you will - numpy on bare metal

Post by mathieu » Fri Nov 01, 2019 3:00 pm

v923z wrote:
Fri Nov 01, 2019 1:57 pm
Done. I have also uploaded compiled firmware for pybv11, and pybd_sf6 to https://github.com/v923z/micropython-ulab/releases.
Thanks again! I just tried on pybd_sf6 and everything seems to work fine, except that:

- By default I can connect to the board using rshell.
- But after I modify boot.py to include pyb.usb_mode('VCP'), rshell cannot connect to board any more (but screen /dev/tty.usbmodem* still works fine).

Not sure what the problem is.

If I may, I have a feature request. Would it be possible to implement the __mod__ operator (%)? Sometimes it is really useful to do something like the following to efficiently cycle over an array:

Code: Select all

from ulab import linspace

a = linspace(1,3,num=3)
k = linspace(1,10,num=10,dtype='int')

print(a[k%3])
# should print array([2, 3, 1, 2, 3, 1, 2, 3, 1, 2]) 
I would try and do it myself, but apparently I'm still struggling to compile the firmware... :|

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: ulab, or what you will - numpy on bare metal

Post by v923z » Fri Nov 01, 2019 3:16 pm

mathieu wrote:
Fri Nov 01, 2019 3:00 pm
If I may, I have a feature request. Would it be possible to implement the __mod__ operator (%)? Sometimes it is really useful to do something like the following to efficiently cycle over an array:

Code: Select all

from ulab import linspace

a = linspace(1,3,num=3)
k = linspace(1,10,num=10,dtype='int')

print(a[k%3])
# should print array([2, 3, 1, 2, 3, 1, 2, 3, 1, 2]) 
I would try and do it myself, but apparently I'm still struggling to compile the firmware... :|
You are asking for two things, actually. One is the modulus operator, and the other is indexing. You want to be able to index the array with an arbitrary sequence. I think this would be a cool feature, but I have to think about how involving that is. It is certainly doable, but not entirely trivial.
By the way, you have to initialise the array like

Code: Select all

k = linspace(1,10,num=10,dtype=np.uint8)
Retrieving a single uin8 from the keyword argument is much easier than dealing with the string, so unless people really demand it, I would like to stick with np.uint8. That is also numpy-conform.

In this special case, you can also do

Code: Select all

array([1, 2, 3]*5)

User avatar
mathieu
Posts: 88
Joined: Fri Nov 10, 2017 9:57 pm

Re: ulab, or what you will - numpy on bare metal

Post by mathieu » Sun Nov 03, 2019 3:02 pm

v923z wrote:
Fri Nov 01, 2019 1:57 pm
Damien wrote:
Fri Nov 01, 2019 10:51 am
I would suggest changing all occurrences of "float" to "mp_float_t", that will allow it to compile for all targets with the FP precision supported/configured by the target.
Done. I have also uploaded compiled firmware for pybv11, and pybd_sf6 to https://github.com/v923z/micropython-ulab/releases.
I gave your pybd_sf6 firmware a try and the speed gains are indeed spectacular (I'm mixing different sound tracks in real time at 16kHz; ulab really shines).

I did notice that with this firmware I lost the ability to use DAC.write_timed in DAC.NORMAL mode. When I run the code below on the latest official firmware (PYBD-SF6-20191103-v1.11-549-gf2ecfe8b8.dfu) everything works as expected, but using your firmware the calls to DAC.write_timed(mode = DAC.NORMAL) yield no sound at all (but DAC.write_timed(mode = DAC.CIRCULAR) still works fine).

Would you like me to open this as an issue on github rather than spam the micropython forum? Not sure what the proper netiquette calls for.

Code: Select all

from pyb import DAC
from math import sin, pi
from array import array
from time import sleep

dac = DAC(1, bits = 8)

buf = array('b')
for k in range(8000):
    buf.append(127 + int(8 * sin(2*pi*k/20)))

dac.write_timed(buf, 8000, mode = DAC.CIRCULAR)

while True:
    dac.write_timed(buf, 8000, mode = DAC.NORMAL)
    sleep(2)

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: ulab, or what you will - numpy on bare metal

Post by jimmo » Sun Nov 03, 2019 11:57 pm

mathieu wrote:
Sun Nov 03, 2019 3:02 pm
I did notice that with this firmware I lost the ability to use DAC.write_timed in DAC.NORMAL mode. When I run the code below on the latest official firmware (PYBD-SF6-20191103-v1.11-549-gf2ecfe8b8.dfu) everything works as expected, but using your firmware the calls to DAC.write_timed(mode = DAC.NORMAL) yield no sound at all (but DAC.write_timed(mode = DAC.CIRCULAR) still works fine).
There was a bugfix to this a couple of ago (https://github.com/micropython/micropython/issues/4944) so is it possible that you're building against an older revision of the micropython codebase?

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: ulab, or what you will - numpy on bare metal

Post by jimmo » Mon Nov 04, 2019 12:02 am

v923z wrote:
Thu Oct 31, 2019 11:29 pm
By changing all occurrences of sinf, and sqrtf to sin, and sqrt, I managed to compile the firmware for PYBD:
https://github.com/v923z/micropython-ul ... s/tag/0.23. I can't test the results, so I can only hope that it works for you.

But then the compilation fails for the pyboard.v.1.1. There must be a better way...
Yeah I think the intention was that MicroPython firmware would either be exclusively all-float or all-double. You'd never use float when you have double-precision mode enabled.

I guess numpy / ulab is an interesting case... Would you consider (for now at least) making ulab always use the "default" floating point type. i.e. dtype=float means that you get double on SF6 (or any other board using soft-double), and single everywhere else.

If you haven't seen it already, the MICROPY_FLOAT_CONST(x) and MICROPY_FLOAT_C_FUN(fun) macros might be useful for you. i.e. use MICROPY_FLOAT_C_FUN(sin) rather than sin or sinf directly.

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: ulab, or what you will - numpy on bare metal

Post by v923z » Mon Nov 04, 2019 6:00 pm

jimmo wrote:
Mon Nov 04, 2019 12:02 am
v923z wrote:
Thu Oct 31, 2019 11:29 pm
By changing all occurrences of sinf, and sqrtf to sin, and sqrt, I managed to compile the firmware for PYBD:
https://github.com/v923z/micropython-ul ... s/tag/0.23. I can't test the results, so I can only hope that it works for you.

But then the compilation fails for the pyboard.v.1.1. There must be a better way...
Yeah I think the intention was that MicroPython firmware would either be exclusively all-float or all-double. You'd never use float when you have double-precision mode enabled.

I guess numpy / ulab is an interesting case... Would you consider (for now at least) making ulab always use the "default" floating point type. i.e. dtype=float means that you get double on SF6 (or any other board using soft-double), and single everywhere else.
That is exactly what I have done, so there is no disagreement here, then. I have also explained this in the manual, and I believe, this should probably be the long-term solution.
jimmo wrote:
Mon Nov 04, 2019 12:02 am
If you haven't seen it already, the MICROPY_FLOAT_CONST(x) and MICROPY_FLOAT_C_FUN(fun) macros might be useful for you. i.e. use MICROPY_FLOAT_C_FUN(sin) rather than sin or sinf directly.
I have found those, thanks!

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: ulab, or what you will - numpy on bare metal

Post by v923z » Mon Nov 04, 2019 6:11 pm

mathieu wrote:
Sun Nov 03, 2019 3:02 pm
I gave your pybd_sf6 firmware a try and the speed gains are indeed spectacular (I'm mixing different sound tracks in real time at 16kHz; ulab really shines).
:D
mathieu wrote:
Sun Nov 03, 2019 3:02 pm
I did notice that with this firmware I lost the ability to use DAC.write_timed in DAC.NORMAL mode. When I run the code below on the latest official firmware (PYBD-SF6-20191103-v1.11-549-gf2ecfe8b8.dfu) everything works as expected, but using your firmware the calls to DAC.write_timed(mode = DAC.NORMAL) yield no sound at all (but DAC.write_timed(mode = DAC.CIRCULAR) still works fine).

Would you like me to open this as an issue on github rather than spam the micropython forum? Not sure what the proper netiquette calls for.
Sorry for the trouble! First, I haven't pulled the micropython repository for a while now (very wise), and second, I haven't a D series pyboard, so I couldn't possibly test the firmware (even wiser). So, yeah, this was my fault. I will take down the firmware on github.

In any case, if you can compile a working piece of firmware with the latest source as @jimmo suggested, would you mind reporting back here? If it is still not working, then I would be interested in finding out where the problem lies.

Thanks,
Zoltán

User avatar
mathieu
Posts: 88
Joined: Fri Nov 10, 2017 9:57 pm

Re: ulab, or what you will - numpy on bare metal

Post by mathieu » Mon Nov 04, 2019 9:17 pm

v923z wrote:
Mon Nov 04, 2019 6:11 pm
In any case, if you can compile a working piece of firmware with the latest source as @jimmo suggested, would you mind reporting back here? If it is still not working, then I would be interested in finding out where the problem lies.
I did compile a working version based on micropython 1.11 (6f75c4f) and ulab 0.24 (43cda00). It seems to work (based on limited testing). I have sent you a link by PM.

- Mathieu

v923z
Posts: 168
Joined: Mon Dec 28, 2015 6:19 pm

Re: ulab, or what you will - numpy on bare metal

Post by v923z » Mon Nov 04, 2019 9:23 pm

mathieu wrote:
Mon Nov 04, 2019 9:17 pm
v923z wrote:
Mon Nov 04, 2019 6:11 pm
In any case, if you can compile a working piece of firmware with the latest source as @jimmo suggested, would you mind reporting back here? If it is still not working, then I would be interested in finding out where the problem lies.
I did compile a working version based on micropython 1.11 (6f75c4f) and ulab 0.24 (43cda00). It seems to work (based on limited testing). I have sent you a link by PM.

- Mathieu
Thanks, I uploaded your firmware to github.

Post Reply