Floating point performance and stability

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
User avatar
perfeco
Posts: 3
Joined: Tue Aug 12, 2014 11:21 am
Location: Lund, Sweden
Contact:

Floating point performance and stability

Post by perfeco » Sat Aug 23, 2014 5:59 pm

Hi,

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
The board was bricked requiring a factory reset here although the previous run from factory reset contued this row, and earlier runs continued with more rows. This last run was with a virgin (unused) pyboard so the "aging" appears to be related to the host PC driver rather than the pyboard.

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')
BR/Joakim

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Floating point performance and stability

Post by dhylands » Sat Aug 23, 2014 10:54 pm

You may want to upgrade the firmware on your pyboard.

There was an issue fixed on Aug 4:

Code: Select all

commit ccacdf44b6c5241ce05769e777008767a7ed8939
Author: Damien George <damien.p.george@gmail.com>
Date:   Mon Aug 4 11:09:51 2014 +0100

    stmhal: Clean up reset/soft-reset code; fix bug init'ing VCP exc.
and this bug fixed on Aug 8:

Code: Select all

commit a1d3ee376c25c0842096535c38e651431028d1b8
Author: Damien George <damien.p.george@gmail.com>
Date:   Fri Aug 8 12:33:49 2014 +0100

    py: Fix bug where GC finaliser table was not completely zeroed out.
Both of those issues would probably affect stability.

Using a build from today: I get the following output when running your script:

Code: Select all

Micro Python v1.3-27-g4f9ebad-dirty on 2014-08-23; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import float_test
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    -2  -2     5   0    12   1     8  -1
     2     0   0     5   1    12   0     8   1
     4     0   1     5   0    12   2     8   1
     8     0   0     5  -1    12   3     8   2
    16     0   0     5   0    12   6     8   1
    32     0  -1     5   0    12  11     8   5
    64     0   0     5   0    12  23     8   7
   128     0   1     5   0    12  43     8  14
   256     0   0     5   0    12  86     8  29
   512     0   0     5   0    12 174     8  57
  1024     0   0     5   0    12 347     8 115
  2048     0   0     5  -1    14  15     8 231
  4096     0   1     5   0    14  32     8 463
  8192     0   0     5   0    14  64     9 247
Time (us) measured using native without interrupts
counts   1*1 gbc   I*I gbc 1.*1. gbc   F*F gbc
     1     0   1     4   0    11   1     6   1
     2     0   0     4   1    11   0     7   0
     4     0  -1     3   0    10   1     7   1
     8     0  -1     3   0    10   3     7   1
    16     0  -1     3   0    10   6     7   3
    32     0  -1     3   0    10  11     7   5
    64     0   1     3   0   bricked     7   7
   128     0  -1     3  -1   bricked     7  14
   256     0   0     3   0   bricked   bricked
   512     0   0     3  -1   bricked   bricked
  1024     0   0     3  -1   bricked   bricked
  2048     0   0     3   0   bricked   bricked
  4096     0   0     3   1   bricked   bricked
  8192     0   1     3   0   bricked   bricked
Time (us) measured using viper 
counts   1*1 gbc   I*I gbc 1.*1. gbc   F*F gbc
     1     0   0     4   0    10   1     6   0
     2     0   0     3   1    10   2     6   1
     4     0   0     3   0    10   2     6   1
     8     0   1     3   0    10   3     7   2
    16     0   0     3  -1     9   5     7   2
    32     0   0     3   0     9  10     7   4
    64     0  -1     3   0   bricked     7   7
   128     0   0     3   0   bricked     7  14
   256     0   0     3   0   bricked   bricked
   512     0   0     3   0   bricked   bricked
  1024   bricked   bricked   bricked   bricked
  2048   bricked   bricked   bricked   bricked
  4096   bricked   bricked   bricked   bricked
  8192   bricked   bricked   bricked   bricked
>>> 
I commented out your "brick detection" code and if I put:

Code: Select all

uart = pyb.UART(6,115200)
pyb.repl_uart(uart)
in my boot.py then I get the following on uart (when you get faults, you'll probably not see anything on the USB REPL, but you will on a uart REPL):

Code: Select all

Micro Python v1.3-28-g5936591 on 2014-08-23; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import float_test
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    -2  -3     5   1    12   0     8   1
     2     0   1     5   0    12   1     8   1
     4     0   0     5   0    13   1     8   1
     8     0   0     5   0    13   3     8   0
    16     0   0     5   0    12   6     8   2
    32     0  -1     5   0    12  12     8   3
    64     0   0     5  -1    12  22     8   7
   128     0   0     5   1    12  43     8  13
   256     0   0     5   0    12  86     8  29
   512     0   0     5   0    12 173     8  57
  1024     0   0     5   0    12 347     8 116
  2048     0   1     5   1    14  13     8 232
  4096     0   0     5   0    14  28     8 463
  8192     0   0     5   1    14  55     9 245
Time (us) measured using native without interrupts
counts   1*1 gbc   I*I gbc 1.*1. gbc   F*F gbc
     1     0   0     5   0    11   0     7   1
     2     0   1     3   1    10   0     7   1
     4     0   0     3   0    10   2     7   0
     8     0   1     3   0    10   3     7   1
    16     0   0     3   0    10   5     7   1
    32     0   0     3  -1    10  11     7   3
    64     0  -1     3   1    10  22     7   7
   128     0   0     3   0    10  43     7  14
   256     0   0     3   0
                          FATAL ERROR:
                                      HardFault
It would be good to get a simpler test case that shows one of the 'bricked" cases.

When it hangs for me, I see the LEDs do a little dance which indicates that a fatal error was hit.

[EDIT}: I filed https://github.com/micropython/micropython/issues/820 on github.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Floating point performance and stability

Post by dhylands » Sat Aug 23, 2014 11:25 pm

perfeco wrote: The board was bricked requiring a factory reset here although the previous run from factory reset contued this row, and earlier runs continued with more rows. This last run was with a virgin (unused) pyboard so the "aging" appears to be related to the host PC driver rather than the pyboard.
This feels like heap corruption and/or trying to follow data through an invalid pointer. When the code uses uninitialized data, you can get very weird, and often undeterministic behavior. So I'm pretty confident that this has nothing to do with the host PC driver (I'm running linux) and is a bug in micropython.

I tried running the test case this code by itself:

Code: Select all

import pyb
import gc

I = 1
F = 1.

us = pyb.Timer(2, prescaler=83, period=0x7fffffff).counter
clean = gc.collect
begin = pyb.disable_irq
end = pyb.enable_irq

def _test():
    for i in range(256): 1.*I; pass


def _ref():
    for i in range(256): pass

begin()
clean()
t0 = us()
_test()
t1 = us()
clean()
t2 = us()
_ref()
t3 = us()
clean()
t4 = us()
end()
which I believe is the code that was running when the Hard Fault occurred. By itself it seems to run fine. This also points to some type of heap corruption as being the issue.

I tried not disabling interrupts and also tried using pyb.micros() (I just coded that up today) and it made no difference, so that eliminates a few places the problem might originate from, and in my mind, points towards a heap issue.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Floating point performance and stability

Post by dhylands » Sun Aug 24, 2014 5:08 pm

Damien found and fixed the problem. It turns out that the viper/native code was being garbage collected because the thumb assembler uses an odd address to indicate that it's thumb code, and this wasn't being detected properly by the gc.

So the gc would free the block with the code in it, but the CPU was continuing to execute the code. The block would then get reallocated, and floating point data or something would then overwrite the code and cause the Hard Fault.

I verified that using today's build, I now get this output:

Code: Select all

Micro Python v1.3-32-gc668d51 on 2014-08-24; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import float_test
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    -2  -2     4   0    12   0     9   0
     2     0   1     4   0    12   1     8   0
     4     0   0     5   0    12   1     8   0
     8     0   0     5   0    12   3     8   1
    16     0  -1     5   0    12   6     8   2
    32     0  -1     5  -1    12  11     8   3
    64     0  -1     5   0    12  22     8   8
   128     0   1     5   0    12  44     8  14
   256     0   0     5   0    12  86     8  29
   512     0   0     5  -1    12 173     8  58
  1024     0   1     5   0    12 348     8 115
  2048     0   0     5  -1    13  13     8 233
  4096     0   0     5   0    13  28     8 463
  8192     0   0     5   1    13  55     8 245
Time (us) measured using native without interrupts
counts   1*1 gbc   I*I gbc 1.*1. gbc   F*F gbc
     1    -1   1     3  -1    10   0     8   0
     2     0   0     3   0    10   2     7   0
     4     0   0     3   0    10   1     7   1
     8     0  -1     3  -1    10   3     7   1
    16     0  -1     3   1    10   6     7   1
    32     0   0     3   0    10  11     7   4
    64     0  -1     3   0    10  22     7   7
   128     0   0     3   0    10  44     7  15
   256     0   0     3  -1    10  88     7  29
   512     0   0     3  -1    10 174     7  58
  1024     0  -1     3   0    10 348     7 116
  2048     0   1     3  -1    11  14     7 230
  4096     0   0     3   0    11  29     7 463
  8192     0   0     3   0    11  60     7 246
Time (us) measured using viper 
counts   1*1 gbc   I*I gbc 1.*1. gbc   F*F gbc
     1    -1   1     4   0    11   0     6   0
     2     0  -1     3   0    10   1     6   0
     4     0   0     3   0    10   2     7   1
     8     0   0     3  -1    10   3     7   1
    16     0   0     3  -1     9   5     7   1
    32     0   0     3   0     9  10     7   4
    64     0   0     3  -1     9  22     7   7
   128     0  -1     3   0     9  42     7  15
   256     0   0     3   0     9  87     7  28
   512     0   0     3   0     9 174     7  58
  1024     0   1     3   0     9 348     7 116
  2048     0   1     3   0    11  14     6 231
  4096     0  -1     3   0    11  29     6 464
  8192     0   0     3   1    11  57     7 247
when running this code:

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:
            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')

User avatar
perfeco
Posts: 3
Joined: Tue Aug 12, 2014 11:21 am
Location: Lund, Sweden
Contact:

Re: Floating point performance and stability

Post by perfeco » Mon Aug 25, 2014 10:58 pm

Thanks guys!

I feel much more confident to use MicroPython in control applications now. :)

Here is an improved benchmark.py that measures with sub-us resolution:

Code: Select all

import pyb
import gc

usx84 = pyb.Timer(2, prescaler=0, period=0x7fffffff).counter
begin = pyb.disable_irq
end = pyb.enable_irq
clean = gc.collect

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(%d): " % N if N else ""
    testbench = """
        %s
        def _test():
            %s%s; pass
        
        %s
        def _ref():
            %spass
        
        def _run():
            %s
            clean()
            t0 = usx84()
            _test()
            t1 = usx84()
            clean()
            t2 = usx84()
            _ref()
            t3 = usx84()
            clean()
            t4 = usx84()
            %s
            dt = ((t1-t0) - (t3-t2))/84.
            dtgc = ((t2-t1) - (t4-t3))/84.
            return dt, dtgc
        """.replace("""
        """, "\r\n") % (
            prefix, wrap, code, prefix, wrap, begins, ends)
    if debug:
        return testbench
    exec(testbench)
    dt, dtgc = _run()
    return dt/N if N else dt, dtgc

I = 1
F = 1.
def tabulate(opt=None, irqOff=True):
    codes = "1+1*1", "I+I*I", "1.+1.*1.", "F+F*F"
    print("Time (us) measured using", opt or 'bytecode', 
          "without interrupts" if irqOff else "")
    print("%6s"% 'counts', end="")
    for code in codes:
        print(" %8s %3s"% (code, 'gc'), end="")
    print()
    for i in range(14):
        print("%6d"% 2**i, end="")
        for code in codes:
            print(" %8.2f %3d"% test(code, 2**i, opt), end="")
        print()

for opt in (None, 'native', 'viper'):
    tabulate(opt)
I ran this benchmark for standard multiply-accumulate (MAC) operations - inverse of FLOPS:

Code: Select all

Micro Python v1.3-36-g7310fd4 on 2014-08-25; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import benchmark
Time (us) measured using bytecode without interrupts
counts    1+1*1  gc    I+I*I  gc 1.+1.*1.  gc    F+F*F  gc
     1     0.24   0     7.38   0    21.19 -35    12.74 -36
     2     0.13   0     7.30   0    21.00 -35    12.54 -36
     4     0.07   0     7.24   0    20.99 -34    12.59 -35
     8     0.03   0     7.23   0    20.88 -31    12.55 -34
    16     0.02   0     7.21   0    20.82 -26    12.55 -32
    32     0.01   0     7.21   0    20.82 -16    12.56 -28
    64     0.00   0     7.21   0    20.82   3    12.50 -20
   128     0.00   0     7.20   0    20.84  43    12.54  -4
   256     0.00   0     7.20   0    20.81 123    12.52  27
   512     0.00   0     7.20   0    20.79 283    12.49  91
  1024     0.00   0     7.20   0    20.78 603    12.44 219
  2048     0.00   0     7.20   0    22.32 480    12.42 475
  4096     0.01   0     7.20   0    23.09 234    13.21 224
  8192     0.00   0     7.20   0    23.09 504    13.22 484
Time (us) measured using native without interrupts
counts    1+1*1  gc    I+I*I  gc 1.+1.*1.  gc    F+F*F  gc
     1     0.26   0     5.67   0    18.12 -35    11.31 -36
     2     0.12   0     5.51   0    18.12 -35    11.12 -36
     4     0.07   0     5.42   0    18.17 -34    11.10 -35
     8     0.03   0     5.38   0    18.03 -31    11.10 -34
    16     0.02   0     5.35   0    17.97 -26    11.07 -32
    32     0.01   0     5.34   0    17.94 -16    11.04 -28
    64     0.00   0     5.34   0    17.95   3    11.02 -20
   128     0.00   0     5.35   0    17.98  43    11.03  -4
   256     0.00   0     5.35   0    17.94 123    11.03  27
   512     0.01   0     5.35   0    17.92 283    11.03  91
  1024     0.00   0     5.35   0    17.91 603    11.01 219
  2048     0.00   0     5.35   0    19.44 480    11.01 475
  4096     0.01   0     5.35   0    20.21 235    11.77 224
  8192     0.00   0     5.35   0    20.21 508    11.77 486
Time (us) measured using viper without interrupts
counts    1+1*1  gc    I+I*I  gc 1.+1.*1.  gc    F+F*F  gc
     1     0.21   0     5.38   0    18.29 -35    11.00 -36
     2     0.12   0     5.18   0    18.06 -35    10.90 -36
     4     0.06   0     5.07   0    18.00 -34    10.92 -35
     8     0.03   0     5.02   0    17.78 -31    10.93 -34
    16     0.01   0     4.99   0    17.69 -26    10.92 -32
    32     0.01   0     4.98   0    17.64 -16    10.89 -28
    64     0.00   0     4.97   0    17.65   3    10.88 -20
   128     0.00   0     4.97   0    17.65  43    10.88  -4
   256     0.01   0     4.97   0    17.62 123    10.88  27
   512     0.00   0     4.97   0    17.60 283    10.87  91
  1024     0.00   0     4.96   0    17.59 603    10.86 219
  2048     0.00   0     4.96   0    19.12 480    10.86 475
  4096     0.01   0     4.96   0    19.89 235    11.63 224
  8192     0.00   0     4.96   0    19.89 508    11.63 486
>>>
The expression using integer constants measured zero clock cycles, so MicroPython actually optimized it away. Nice!
The negative values for garbage collection time are a little disturbing. What is it doing >36 us only when empty?

Happy coding!
/Joakim

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Floating point performance and stability

Post by dhylands » Tue Aug 26, 2014 4:21 am

perfeco wrote:The expression using integer constants measured zero clock cycles, so MicroPython actually optimized it away. Nice!
The negative values for garbage collection time are a little disturbing. What is it doing >36 us only when empty?
36 usec is only 6000 cpu instructions. It probably depends on how many objects are in thee heap.

User avatar
perfeco
Posts: 3
Joined: Tue Aug 12, 2014 11:21 am
Location: Lund, Sweden
Contact:

Re: Floating point performance and stability

Post by perfeco » Tue Aug 26, 2014 12:19 pm

dhylands wrote:36 usec is only 6000 cpu instructions. It probably depends on how many objects are in thee heap.
Of course, but <0.3us extra time on the first float operation leading to 36 us faster gc afterwards indicates that the few allocations done for a float operation gets rid of garbage much more efficiently than the garbage collection algorithm itself.:? Perhaps the garbage collector can also use defragmentation of consecutive objects before collecting them to speed up execution.:idea:

Post Reply