ulab, or what you will  numpy on bare metal

 Posts: 698
 Joined: Mon Nov 20, 2017 10:18 am
Re: ulab, or what you will  numpy on bare metal
I see this ;libiary has featured on Hackster.io https://www.hackster.io/news/zoltanvor ... 9oOo5qu1I
Re: ulab, or what you will  numpy on bare metal
It must have leaked from hackaday.com, or perhaps the blog of adafruit.com. Though, the reaction on hackaday was really bashing But the hackster.io article is nice. Thanks!OutoftheBOTS_ wrote: ↑Wed Oct 30, 2019 8:38 pmI see this ;libiary has featured on Hackster.io https://www.hackster.io/news/zoltanvor ... 9oOo5qu1I
Re: ulab, or what you will  numpy on bare metal
Yes, runtime.c will do this when none of the previous options have worked and it would otherwise raise TypeError. It changes the op from FOO to REVERSE_FOO and calls your binary op method with the args reversed.
This means for commutative operators, your binary op can treat FOO and REVERSE_FOO the same but obviously things like subtraction or division need to be handled differently.
Re: ulab, or what you will  numpy on bare metal
I am trying to compile ulab for the PYBD_SF6 on macOS following instructions found at https://github.com/v923z/micropythonul ... e/ulab.rst. When I run
I get the following error:
Am I missing something obvious? This is my first attempt at building my own firmware and I'm obviously over my head.
If I may suggest: I suspect many "regular" numpy users out there would find it very useful to have access to precompiled firmwares for all three pyboardD models.
Many thanks to v923z for this impressive piece of work!
Code: Select all
make BOARD=PYBD_SF6 CROSS_COMPILE=/usr/local/bin/armnoneeabi
Code: Select all
make: *** No rule to make target `lib/mbedtls/library/aes.c', needed by `buildPYBD_SF6/genhdr/qstr.i.last'. Stop.
If I may suggest: I suspect many "regular" numpy users out there would find it very useful to have access to precompiled firmwares for all three pyboardD models.
Many thanks to v923z for this impressive piece of work!
Re: ulab, or what you will  numpy on bare metal
Jim,
The problem is that upcasting can be done on a casebycase basis, i.e., you have to inspect all possible typecode combinations. This happens here: https://github.com/v923z/micropythonul ... ray.c#L758. In order to simplify the procedure, I do this inspection once, and for 8 operators. Otherwise, the ugly decision tree would have to be repeated 8 times. Now, does the abovementioned comment mean that the switch statement at https://github.com/v923z/micropythonul ... ray.c#L719 has to be written as
(this would add a lot to the code) or can I expand as
I think, the simplest solution would be, if I could swap the two operands at the very beginning, like so
but that does not seem to work. Even if
returns [6, 7, 8],
throws a TypeError exception, meaning that the type of 5 (or a) was not preserved. (I had the prinout, so I know that flow control entered the very first if statement.) Is there a way of overcoming this? What is the trick in your implementation?
And what about relational operators? I don't find reversion for those.
works, but
doesn't, and it seems, this can't even be made to work. Is that correct?
Subtractions and divisions will make life a bit difficult, that is true, but I think they are not a serious predicament. What bugs me a bit more is this comment from runtime0.hjimmo wrote: ↑Wed Oct 30, 2019 9:39 pm
Yes, runtime.c will do this when none of the previous options have worked and it would otherwise raise TypeError. It changes the op from FOO to REVERSE_FOO and calls your binary op method with the args reversed.
This means for commutative operators, your binary op can treat FOO and REVERSE_FOO the same but obviously things like subtraction or division need to be handled differently.
Code: Select all
// MP_BINARY_OP_REVERSE_* must follow immediately after MP_BINARY_OP_*
Code: Select all
switch(op) {
case MP_BINARY_OP_EQUAL:
...
break;
...
case MP_BINARY_OP_ADD:
ugly decision tree...
...
break;
case MP_BINARY_OP_REVERSE_ADD:
ugly decision tree...
...
break;
...
Code: Select all
switch(op) {
case MP_BINARY_OP_EQUAL:
...
break;
...
case MP_BINARY_OP_ADD:
case MP_BINARY_OP_REVERSE_ADD:
case MP_BINARY_OP_MULTIPLY:
case MP_BINARY_OP_REVERSE_MULTIPLY:
case MP_BINARY_OP_TRUE_DIVIDE:
case MP_BINARY_OP_REVERSE_TRUE_DIVIDE:
ugly decision tree...
...
break;
Code: Select all
mp_obj_t ndarray_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
if(op == MP_BINARY_OP_REVERSE_ADD) {
printf("reversed");
return ndarray_binary_op(MP_BINARY_OP_ADD, rhs, lhs);
}
...
Code: Select all
import ulab as np
a = np.array([1, 2, 3])
a + 5
Code: Select all
import ulab as np
a = np.array([1, 2, 3])
5+a
And what about relational operators? I don't find reversion for those.
Code: Select all
import ulab as np
a = np.array([1, 2, 3])
a < 5
Code: Select all
import ulab as np
a = np.array([1, 2, 3])
5 > a
Re: ulab, or what you will  numpy on bare metal
Oh, so you are trying to compile without ulab, i.e., the standard firmware, i.e., the error has nothing to do with the module. Is that right?mathieu wrote: ↑Thu Oct 31, 2019 10:21 pmI am trying to compile ulab for the PYBD_SF6 on macOS following instructions found at https://github.com/v923z/micropythonul ... e/ulab.rst. When I run
I get the following error:Code: Select all
make BOARD=PYBD_SF6 CROSS_COMPILE=/usr/local/bin/armnoneeabi
Am I missing something obvious? This is my first attempt at building my own firmware and I'm obviously over my head.Code: Select all
make: *** No rule to make target `lib/mbedtls/library/aes.c', needed by `buildPYBD_SF6/genhdr/qstr.i.last'. Stop.
I agree. If I had time, I would do that, though, there are at least 20 different boards supporting micropython now, and if you want to compile for all of them, then the process has to be automatised. By that I mean compilation, and uploading to storage. You have to persuade @Damien. But I am with you. He could automatically pull the ulab repository, whenever something changes there, like the webhook of readthedocs.
Re: ulab, or what you will  numpy on bare metal
I have just tried to compile for the PYBD board (though, I have none), and while I get the standard firmware without issues, with ulab, I get missing references to sqrtf, and sinf in the link step.mathieu wrote: ↑Thu Oct 31, 2019 10:21 pmI get the following error:Code: Select all
make BOARD=PYBD_SF6 CROSS_COMPILE=/usr/local/bin/armnoneeabi
Code: Select all
make: *** No rule to make target `lib/mbedtls/library/aes.c', needed by `buildPYBD_SF6/genhdr/qstr.i.last'. Stop.
Code: Select all
Including User C Module from ../../../ulab/code
LINK buildPYBD_SF6/firmware.elf
buildPYBD_SF6/code/linalg.o: In function `linalg_eig':
linalg.c:(.text.linalg_eig+0x100): undefined reference to `sqrtf'
linalg.c:(.text.linalg_eig+0x118): undefined reference to `sqrtf'
linalg.c:(.text.linalg_eig+0x124): undefined reference to `sqrtf'
linalg.c:(.text.linalg_eig+0x298): undefined reference to `sqrtf'
buildPYBD_SF6/code/fft.o: In function `fft_kernel':
fft.c:(.text.fft_kernel+0x9a): undefined reference to `sinf'
fft.c:(.text.fft_kernel+0xb2): undefined reference to `sinf'
buildPYBD_SF6/code/fft.o: In function `fft_fft_ifft_spectrum':
fft.c:(.text.fft_fft_ifft_spectrum+0x108): undefined reference to `sqrtf'
buildPYBD_SF6/code/numerical.o: In function `numerical_sum_mean_std_single_line':
numerical.c:(.text.numerical_sum_mean_std_single_line+0x70): undefined reference to `sqrtf'
buildPYBD_SF6/code/numerical.o: In function `numerical_sum_mean_std_array':
numerical.c:(.text.numerical_sum_mean_std_array+0x70): undefined reference to `sqrtf'
make: *** [Makefile:514: buildPYBD_SF6/firmware.elf] Error 1
Re: ulab, or what you will  numpy on bare metal
By changing all occurrences of sinf, and sqrtf to sin, and sqrt, I managed to compile the firmware for PYBD:
https://github.com/v923z/micropythonul ... 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...
Re: ulab, or what you will  numpy on bare metal
The PYBD_SF6 uses double precision float, and only provides the double precision math functions (eg sin, cos, not sinf, cosf).
I see in your ulab code that you use "float" exclusively as the FP data type (at the C level). Is this a restriction or can it also work with double?
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.
I see in your ulab code that you use "float" exclusively as the FP data type (at the C level). Is this a restriction or can it also work with double?
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.
Re: ulab, or what you will  numpy on bare metal
I think one must consider various things: if you use doubles, you need twice as much RAM, and I don't know, whether that precision is really necessary in an embedded environment. But I am not dead against doubles.Damien wrote: ↑Fri Nov 01, 2019 10:51 amThe PYBD_SF6 uses double precision float, and only provides the double precision math functions (eg sin, cos, not sinf, cosf).
I see in your ulab code that you use "float" exclusively as the FP data type (at the C level). Is this a restriction or can it also work with double?
On the other hand, if you have both double, and float, then upcasting becomes more involving, especially, that not all platforms support doubles. You would then need #ifdef compiler directives all over the code. Can we define a reasonable common denominator for all platforms? (u)int8_t, (u)int16_t, and mp_float_t, or does that already fail on some (ESP8266, e.g.)?
OK, thanks for the hint. But at the end of the day, one still has to cast to float, I believe: when you create the binary array, you have to set the typecode, or you would have different binary arrays for different platforms (see above). Is it generally true that, where doubles are implemented, you also have more RAM? I work mainly with the STM32F405, and that is why I can't really comment on this. But I absolutely see the problem, and I also know that a decision must be made at one point.
One more comment on this: if the float type is going to be different, depending on the platform, how should one create an array with a specific type?
Code: Select all
a = np.array([1, 2, 3], dtype=float)