[问题] thread 吃光 CPU 效率,想自行控制

楼主: HuangJC (吹笛牧童)   2023-01-29 20:31:15
最近在做一个专案,里面有三十个设备要控制
因为三十个设备不能互相卡住,所以就开了三十个 thread
另外程式要有所展示,所以 main thread 也就是 ui thread
由 main thread 开出 30 个设备 thread, 那现在看到有 31 个了
CPU 的效率拨进来这支程式,假设是平均且 free run
那么每个 thread 都占用了 1/31 的 CPU 时间
我在每个 thread 做过一次判断后,都有 sleep(1)
这意思是每个设备,每秒都判断一次应该要做什么动作
这时 UI 变很卡了...
理想上每个 thread 遇到 sleep 指令,它就睡了
然后 CPU 时间会拨给剩下的 thread 去平均分享
如果每个设备的判断式都执行很快,那么在别的 thread 的 sleep 一秒内,就足以做完
当程式跑久以后,每个 thread 都有可能全速奔驰
只要它们别同时醒著
也许是我写的判断式效率不好,渐渐的感觉到程式变很卡
而把 sleep 加长有助于解决这个问题
其实我想分配每个 thread 的优先权了
一开始的想法便是利用 lock
首先产生一个 lock 当全域物件
30 个 thread 都引用它且互斥
with lock:
设备判断式
这样可使 30 个 thread 同时只能有一个执行
而我在设备判断式里,也只简单的把一个计数器加一
据以观察 30 个设备的执行机率平不平均
结果是非常不平均;但这样写是最简单的
我会担心,会不会运气不好,某设备经常不执行?
后来我想了一个法子,由我自己控制
我产生一个 list, 里面有所有 30 个设备 thread 的指标
只要某 thread 被执行,就把它移到 list 的最尾端
那么最前端就是没被执行到,我希望它执行的
用这个方法等于把 30 个 thread 串起来,因为同时只有一个在动
我等于就把它们变一个 thread (难道 thread group 就是在做这件事?)
我希望的是 30个设备 thread 总共占用 50% CPU 时间
而 main thread 占用另外的 50% CPU 时间;也就是平分~
这样会不会有什么问题呢?有没有更简单的想法呢?
觉得自己打造了不少轮子
而且这样似乎又违反了一开始的初衷(设备不要互相卡住)
因为我只要一个设备有 bug, 卡住不动
剩下 29 个设备会全部赔葬 XD
把话反过来说好了,一开始我就不想写 30 个 thread,我本来要用一个 thread 做完
举例来说,一个射击类电玩里,敌机可能有一百架
难道这电玩就用一百个 thread 来写?
当然是一个 thread 就很好写啊...
但因为我的开发出了点问题,老板就叫我快点改成 multi-thread
至少一个设备卡住也不影响其他设备
另外当初在学同步物件时,有个东西就搞不懂
好像有个叫 信号机 的物件,它不像 lock 是完全互斥
而是它可以允许一个量(比如同时有五个 thread pass,一个结束才能再唤醒一个)
我一直无法想像这东西用在哪,从没用过
难道就用在这?
比如,我 30 个设备会卡,但当初开发到一半时还很顺,大概可以容许 15 个设备
我就设 15 个设备的信号机,这样程式也不会卡,但也不是同时所有 thread 都在动
难道就是用在这?
但我还是会担心,允许 15 个设备,就有哪个设备不受照顾,睡死一方..
这种同步物件,有保证所有 thread 的机率尽量均等吗?
以上请教,谢谢
作者: surimodo (好吃棉花糖)   2023-01-29 23:13:00
叫老板升级CPU
作者: poototo (poototo)   2023-01-29 23:18:00
GIL下,thread本来就是互斥的客制互斥锁没有改变thread互斥性,只会影响公平性可试试Coroutines&Tasks,管理成本比thread低很多
作者: TakiDog (多奇狗)   2023-01-30 01:49:00
当今天出现sleep 应该要思考流程设计asyncio.sleep 会更好的去释放资源你大可一个设备一个process沟通,资料再汇整到一处
作者: timsheu (为道日损)   2023-01-30 09:29:00
asyncio效能比multi-thread好很多,但语法要熟悉一下multi-process的话,若资料要互通要用share memory官方的asyncio用不习惯的话,也可以用trio,比较容易上手asyncio要注意一下python版本,有些语法只适用python3.8+我是用rpi4b架fastapi,python3.7,asyncio+rxpyasyncio要同时跑coroutine的话,要包成task才行。
作者: day831231 (下个地点)   2023-01-31 06:32:00
假设只有一个CPU那用thread 跟 process 速度不会差到太多感觉只是使用方式错误
作者: Falldog (Yo)   2023-01-31 23:19:00
GIL卡的是python layer, C level的不会卡, eg. socket io理论上ui会感到卡一定是main thread做太多事卡住render用thread的话,就尽量用event queue的方式沟通如果在main thread需要跟其他thread用lock抢资源的话会卡似乎也是预期内的事补充一下 GIL, C level 有机会可以 release GIL
作者: poototo (poototo)   2023-02-01 00:52:00
PEP 703就有可能让GIL Optional
作者: zerof (猫橘毛发呆雕像)   2023-02-01 16:38:00
左转 pypy
作者: s9041200 (小明阿)   2023-02-01 20:10:00
试过epoll吗?
作者: eight0 (欸XD)   2023-02-04 00:17:00
https://github.com/eight04/pyWorker 不知道有没有帮助

Links booklink

Contact Us: admin [ a t ] ucptt.com