I found some severe problems with floating point operations on my pyboards (Micro Python v1.2-15-g951ed9d on 2014-07-20; PYBv1.0 with STM32F405RG). This prevents me from currently recommending Micro Python in a control application I am working with. Have other experienced memory leaks, garbage collection problems etc when using floating point operations? Here are my observations:
1. Calculation time and board stability detoriates gradually after floating point operations. Tested with all three compilation modes (bytecode, native, viper).
2. Board stability depends on the history of the host PC driver.
I am running Windows 7 64bit and Micro Python v1.2-15-g951ed9d.
Here is a trace of how many microseconds a multiplication takes depending on history. I=1 and F=1.0 during the tests. gbc is the time consumed by a garbage collection after the 'counts' operations measured.
Code: Select all
Micro Python v1.2-15-g951ed9d on 2014-07-20; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import benchmark
Hold USR button until GREEN+YELLOW after reset to recover bricked pyboard
Time (us) measured using bytecode without interrupts
counts 1*1 gbc I*I gbc 1.*1. gbc F*F gbc
1 -1 -2 6 -2 13 -37 7 -38
2 0 -2 6 -2 14 -37 8 -38
4 0 -2 5 -2 16 -37 8 -37
8 0 -2 6 -2 19 -35 9 -37
16 0 -1 6 -2 22 -32 10 -36
32 0 -2 6 -2 27 -27 11 -34
64 0 -2 6 -1 35 -14 12 -31
128 0 -2 6 -2 50 9 14 -23
256 0 -2 6 -2 75 58 18 -7
512 0 -2 6 -2 117 153 25 26
1024 0 -1 6 -2 197 344 35 89
2048 0 -2 6 -1 352 -32 54 217
4096 0 -2 6 -2 352 -26 91 474
8192 0 -2 6 -1 352 -13 109 225
Time (us) measured using native without interrupts
counts 1*1 gbc I*I gbc 1.*1. gbc F*F gbc
1 -1 -2 4 -2 10 -37 6 -38
2 0 -1 4 -2 12 -37 6 -38
4 0 -2 4 -2 15 -37 7 -38
8 0 -2 4 -2 18 -35 7 -37
16 0 -1 4 -2 21 -33 9 -35
32 0 -2 4 -2 25 -27 10 -34
64 0 -2 4 -2 bricked 11 -30
128 0 -2 4 -2 bricked 13 -23
256 0 -3 4 -3 bricked bricked
512 0 -3 4 -1 bricked bricked
1024 0 -1 4 -1 bricked bricked
2048 0 -1 4 -2 bricked bricked
4096 0 -2 4 -2 bricked bricked
8192 0 -2 4 -2 bricked bricked
Time (us) measured using viper
counts 1*1 gbc I*I gbc 1.*1. gbc F*F gbc
1 -1 -1 5 -2 12 -38 8 -38
2 0 -1 4 -2 12 -37 6 -37
4 0 -1 4 -2 14 -36 7 -37
8 0 -2 4 -2 17 -35 7 -37
16 0 -3 4 -2 20 -31 8 -36
32 0 -1 4 -2 24 -27 9 -34
64 0 -1 4 -3 bricked 11 -30
128 0 -2 4 -3 bricked 13 -22
256 0 -1 4 -2 bricked bricked
512 0 -2
For completeness, here is the benchmark module I ran:
Code: Select all
import pyb
import gc
us = pyb.Timer(2, prescaler=83, period=0x7fffffff).counter
clean = gc.collect
begin = pyb.disable_irq
end = pyb.enable_irq
def test(code='pass', N=None, opt=None, irqOff=True, debug=False):
prefix = "@micropython.%s" % opt if opt else ""
begins, ends = ("begin()", "end()") if irqOff else ("", "")
wrap = "for i in range(%s): " % N if N else ""
testbench = ("""if 1:
%s
def _test():
%s%s; pass
%s
def _ref():
%spass
%s
clean()
t0 = us()
_test()
t1 = us()
clean()
t2 = us()
_ref()
t3 = us()
clean()
t4 = us()
%s
""" % (prefix, wrap, code, prefix, wrap, begins, ends))
if debug:
print(testbench)
return
exec(testbench)
dt = (t1-t0) - (t3-t2)
dtgc = (t2-t1) - (t4-t3)
return dt/N if N else dt, dtgc
#test('1*1', 8192, debug=True)
I = 1
F = 1.
def tabulate(opt=None, irqOff=True, ):
codes = "1*1", "I*I", "1.*1.", "F*F"
print("Time (us) measured using", opt or 'bytecode',
"without interrupts" if irqOff else "")
print("%6s"% 'counts', end="")
for code in codes:
print(" %5s %3s"% (code, 'gbc'), end="")
print()
for i in range(14):
print("%6d"% 2**i, end="")
for code in codes:
if ((opt=='native' and
("." in code and 2**i >= 64 or
"F" in code and 2**i >= 256)) or
(opt=='viper' and
("1" in code and 2**i >= 1024 or
"I" in code and 2**i >= 1024 or
"." in code and 2**i >= 64 or
"F" in code and 2**i >= 256))):
# These cases bricked a pyboard
print(" bricked", end="")
else:
print(" %5d %3d"% test(code, 2**i, opt), end="")
print()
print("Hold USR button until GREEN+YELLOW after reset to recover bricked pyboard")
for opt in (None, 'native', 'viper'):
tabulate(opt, opt!='viper')