Micropython中的IF语句的奇怪表现
m24h2024/04/22原创 软件综合 IP:上海

今天对一段关键代码测时 惊奇地发现 micropython在if的逻辑判断上 耗时是出人意料的大 而且表现非常奇怪非常不稳定

比如这段代码 在我的ESP32C3 耗时有56us左右 (预设使得条件通过)

if st[0]!=t and st[1]==t:
    st[0]=t
    st[2]=st[2]+1

这个代码运行非常频繁 而t t[0] t[1]仅仅有0和1两种取值 于是优化了一下

q=(st[0]^t)&(st[0]^st[1])
st[0]=st[0]^q
st[2]=st[2]+q

虽然看起来运算复杂了很多 但是实际上 耗时仅仅只有30us 因为这段代码每1ms要执行一次 所以优化效果是比较可观的

但是这不是最重要的 关键第一段代码的耗时测试在不同情况下 表现非常奇怪

在裸机不加载其他代码的情况下  耗时150us 如果加载了我的其他代码 使用了定时器0 也是150us  使用定时器1 有时候是50多微秒 有时候是150us 如果仅仅加载了其他代码 没有使用定时器 就是得到56us的结果

而优化的代码 无论哪种情况 都稳定在30us

也许和内存屏蔽有关 也许和分支预测有关 但是就这延时量级看 只怕主要是和micropython的IF语句处理方式有关 总之 测试下来 micropython的IF语句非常不省油

所以 在速度要求较高的情况下 micropython应该尽量避免采用逻辑判断

来自:计算机科学 / 软件综合
4
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
xa87
8个月12天前 IP:上海
931458

解释语言就这样

如果编译性的语言,两者就没有区别。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
xa87
8个月12天前 IP:上海
931459

解释性的语言,你在中间多打100个空格最终执行时间可能都不一样。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
m24h作者
8个月12天前 IP:上海
931461
引用xa87发表于2楼的内容
解释性的语言,你在中间多打100个空格最终执行时间可能都不一样。

那倒是一样的 因为运行前会编成字节码才运行的 并不是那种无编译的解释性语言 而且我计时自然是不会把编译时间包括在内的

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
m24h作者
8个月12天前 IP:上海
931464

又仔细测试了一下 代码如下

>>> from time import sleep, ticks_us as ticks
run_times=1
def test1():
    t1=ticks()
    for i in range(run_times):
        x1=0
        x2=1
        x3=1
        x4=0
        if x1!=x2 and x1!=x3:
            x1=x3
            x4=x4+1
    t2=ticks()
    print(t2-t1)
def test2():
    t1=ticks()
    for i in range(run_times):
        x1=0
        x2=1
        x3=1
        x4=0
        q=(x1^x2)&(x1^x3)
        x1=x1^q
        x4=x4+q
    t2=ticks()
    print(t2-t1)
sleep(1)
test1()
sleep(1)
test2()

32
15
>>> from time import sleep, ticks_cpu as ticks
run_times=1
def test1():
    t1=ticks()
    for i in range(run_times):
        x1=0
        x2=1
        x3=1
        x4=0
        if x1!=x2 and x1!=x3:
            x1=x3
            x4=x4+1
    t2=ticks()
    print(t2-t1)
def test2():
    t1=ticks()
    for i in range(run_times):
        x1=0
        x2=1
        x3=1
        x4=0
        q=(x1^x2)&(x1^x3)
        x1=x1^q
        x4=x4+q
    t2=ticks()
    print(t2-t1)
sleep(1)
test1()
sleep(1)
test2()

5010
2246
>>> from time import sleep, ticks_cpu as ticks
run_times=10
def test1():
    t1=ticks()
    for i in range(run_times):
        x1=0
        x2=1
        x3=1
        x4=0
        if x1!=x2 and x1!=x3:
            x1=x3
            x4=x4+1
    t2=ticks()
    print(t2-t1)
def test2():
    t1=ticks()
    for i in range(run_times):
        x1=0
        x2=1
        x3=1
        x4=0
        q=(x1^x2)&(x1^x3)
        x1=x1^q
        x4=x4+q
    t2=ticks()
    print(t2-t1)
sleep(1)
test1()
sleep(1)
test2()

16096
12813
>>> from time import sleep, ticks_cpu as ticks
run_times=100
def test1():
    t1=ticks()
    for i in range(run_times):
        x1=0
        x2=1
        x3=1
        x4=0
        if x1!=x2 and x1!=x3:
            x1=x3
            x4=x4+1
    t2=ticks()
    print(t2-t1)
def test2():
    t1=ticks()
    for i in range(run_times):
        x1=0
        x2=1
        x3=1
        x4=0
        q=(x1^x2)&(x1^x3)
        x1=x1^q
        x4=x4+q
    t2=ticks()
    print(t2-t1)
sleep(1)
test1()
sleep(1)
test2()

126486
119600
>>>

循环次数增加  感觉逐渐拉平

在电脑上 使用time_ns代替ticks_xxx 循环100000次  是37:64 (ms) 是if判断更快

另外一个测试 这里难以完全描述 是在整个系统里的实际应用临时增加一个计时  对运行时间进行累加和平均 使用if判断又反而比运算法来得快 大概耗时比是94:116

最终决定 还是用回if法 

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
m24h
进士 学者 机友
文章
55
回复
905
学术分
1
2020/01/22注册,6时9分前活动

个人开源项目: XXXXXXXXXXXXXX

主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:上海
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}