找回密码
 立即注册
搜索
查看: 3570|回复: 19

[软件] python代码多线/进程性能问题

[复制链接]
     
发表于 2022-12-4 23:18 | 显示全部楼层 |阅读模式
本帖最后由 子虚乌有 于 2022-12-4 23:19 编辑

挺简单一段代码。不过又是多线程,又是多进程

def updateResultDict(key, result,lockCaculator,caculateResult):
        lock.acquire()
        lockCaculator.acquire()       
        caculateResult[key] = (datetime.datetime.now(), list(map(lambda x: x[0], result)))       
        lockCaculator.release()
        lock.release()


本身这个方法实际逻辑就一句话:把计算结果放到一个普通dict里。
但是result是有几十个线程,每个线程都会生产出一个result,根据key来更新。所以会有多线程访问这个caculateResult。然后要有线程锁lock
caculateResult又作为计算结果会被其它进程访问,又有进程锁lockCaculator
现在问题出在lock.acquire()上,很慢。要4秒。
整个程序只有这个地方用到这个线程锁,进程锁在另外一个读结果的客户端用到,实际上目前没有enable所以可以认为其它地方也没用到。
而caculateResult[key] = (datetime.datetime.now(), list(map(lambda x: x[0], result)))        只是个dict的upda特。用时几乎可以忽略。
所以这个4秒很奇怪

回复

使用道具 举报

     
 楼主| 发表于 2022-12-4 23:22 | 显示全部楼层
或者说是不是我开了进程锁,就不需要线程锁了。
不知道python是个什么机制。
回复

使用道具 举报

     
发表于 2022-12-5 02:08 来自手机 | 显示全部楼层
一你这个map要花多长时间啊,第二你考虑考虑一定要这么写么,已知字典本身的单个操作算是线程安全的吧
回复

使用道具 举报

     
发表于 2022-12-5 02:09 来自手机 | 显示全部楼层
那么你这么一长串的句子里哪些是一定要加锁的,哪些不用加锁得想清楚
回复

使用道具 举报

     
发表于 2022-12-5 02:10 来自手机 | 显示全部楼层
至于python本身的机制,你应该也知道有GIL,对cpu密集型的程序来说多线程没有意义,当然io密集型除外
回复

使用道具 举报

     
 楼主| 发表于 2022-12-5 06:59 | 显示全部楼层
chenwanqq 发表于 2022-12-5 02:09
那么你这么一长串的句子里哪些是一定要加锁的,哪些不用加锁得想清楚

caculateResult[key] = xxx
需要锁,caculateResult本身是被多个线程共享的。
这个操作一瞬间。
后面那个map也是一瞬间,因为list很小,里面是浮点数,数量才不到100。
回复

使用道具 举报

     
 楼主| 发表于 2022-12-5 07:00 | 显示全部楼层
我每一行都打印时间了,大头都是第一句
“         lock.acquire()”
回复

使用道具 举报

头像被屏蔽
发表于 2022-12-5 07:07 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

头像被屏蔽
     
发表于 2022-12-5 08:22 来自手机 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

头像被屏蔽
发表于 2022-12-5 08:41 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

     
发表于 2022-12-5 12:17 | 显示全部楼层
python线程推荐写在一个class里 把线程锁也设置成instance variable就好
然后用就 with self.lock 去更新另外一个instance variable

回复

使用道具 举报

     
发表于 2022-12-5 12:42 | 显示全部楼层
我说下我的直觉体会
算你8进程50线程,那一共是400次调用,4000ms/400 = 10ms,也就是平均这套操作下来需要耗时10毫秒,那可不得卡在lock acquire上面么
回复

使用道具 举报

头像被屏蔽
     
发表于 2022-12-5 15:14 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

头像被屏蔽
     
发表于 2022-12-5 15:18 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

     
 楼主| 发表于 2022-12-5 15:55 | 显示全部楼层
jjy376195855 发表于 2022-12-5 15:18
为啥要上两道锁????太迷幻了,你是在作课设么

实际上现实中的多线程多进程的第一步就是识别那些东西需 ...

不算吧。
因为这个caculateResult这个dict事实上就是既被多线程往里放数据,又被多进程读数据。
lock是线程锁
lockCaculator是进程锁
回复

使用道具 举报

     
 楼主| 发表于 2022-12-5 15:56 | 显示全部楼层
jjy376195855 发表于 2022-12-5 15:14
你为啥要这么写这个东西,我没搞懂真的

顺序执行会慢么?

你这个倒是提醒我了,真的没试过顺序执行。我有时间试试看。
回复

使用道具 举报

     
发表于 2022-12-6 02:05 来自手机 | 显示全部楼层
概念都很模糊的时候就别上多线程了

看你代码写的是计算,尽可能想办法用numpy去凑

比你写的这种可能快100倍



—— 来自 Xiaomi Mi 10, Android 12上的 S1Next-鹅版 v2.5.4
回复

使用道具 举报

头像被屏蔽
     
发表于 2022-12-6 12:13 来自手机 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

     
发表于 2022-12-6 12:51 | 显示全部楼层
如果 result 是一个内部类型,其实不用加线程锁。
python 因为有 GIL,单个进程只能同时执行一条字节码指令,所以插入 dict 是原子操作,除非你自己实现了 __hash__ 方法。
回复

使用道具 举报

     
发表于 2022-12-6 19:11 | 显示全部楼层
锁就是锁,一个锁就可以,留multiprocessing那个
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|上海互联网违法和不良信息举报中心|网上有害信息举报专区|962110 反电信诈骗|举报电话 021-62035905|Stage1st ( 沪ICP备13020230号-1|沪公网安备 31010702007642号 )

GMT+8, 2024-9-22 01:58 , Processed in 0.173500 second(s), 5 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表