弱极了,请教 Python 多线程如何快速开始

343 天前
 pathetique
文科轻拍

晚上用 python 写雍正实录的词汇统计

雍正的起居官特别能写,一百三十多万字,用 M1 pro 的电脑,半个小时才检索到三万多字(算法应该没问题),看了看 cpu ,只有一个 100%的占用

有没有特别简单的 python 多线程调用入门,希望自己能理解的那种?

不知道问清楚没有
3944 次点击
所在节点    Python
53 条回复
lyz1990
343 天前
半小时 3 万慢得不太正常
pathetique
343 天前
@Kinnice @Weixiao0725 @adoni @aijam @coderluan @fyq @killva4624 @laqow @litguy @liyafe1997

非常感谢各位的帮助!就不一一回复,几位大佬我一起感谢先

先非常感谢对多线程和进程的区分,我已经开始用 multiprocessing module 了,在我的 M1max 上基本上十个小时可以做完,对于雍正可以接受了。但是随着搜索对象正则式的复杂化我怀疑还要更久更久,而且雍正才干几年,乾隆的起居录估计有十倍大,可能个人电脑还是不够。

然后几位大佬怀疑算法有没有问题,我也不知道哪里可以改善的。我把最简单的版本(算二字成词率)代码放在这里,辣大家的眼可能,但是真心请问如果有耐心看完的大佬:有没有改进的空间?如果是单线程的话,我可以从头到尾扫描,扫过的不再碰,复杂度是 n^2/2 ,但是因为多线程,把文本分成多块就没头没尾的,复杂度是 n^2 但是可以多核平均。


checkdict = [] #已经查过的单词词库
list = [] #文本本身
step = 100000 #每个机器人负责多大块

with open('yong3.txt', 'r') as file:
contents = file.read()
for chr in contents:
if chr != '\n' and chr != ' ' and chr != '。' and chr != '、' and chr != '○' and chr != '\u3000': #有些奇怪的字符去掉
list.append(chr)
length = len(list) #雍正大概 100 万字


import multiprocessing.pool #import the multiprocessing module

def worker(num):
"""Worker function for the process"""
print(f'Worker {num} starting')

count = 0
for i in range(0+step*num,min(step+step*num,length-2)): #每个机器人负责 #step 长度的文字
if (list[i:i+2] not in checkdict): #如果不在字典里
count = 0
for j in range(0,length-2): #全本比对,因为分块似乎只能这么做,不能从 i 开始?
if list[i:i+2] == list[j:j+2]:
count = count + 1
checkdict.append(list[i:i+2]) #check 完,添进已查字典
if count > 350: #出现次数高于 350 次的字显示出来
print (list[i:i+2])
print(i, count, f"{num}th worker at percentage = {format((i/step-num)*100, '.2f')}%" )
print(f'Worker {num} finished')


还是挺好玩的,发现很多有趣的事实,比如弄死了年羹尧雍正还常提,比如他喜欢的十三弟其实没那么常提。我其实拿清史资料是因为手头方便,下一步更想用 Colibri Core 处理黏着语(黏着语,比中文不一样的地方在于一个词根会有很多变化,比如 love, loves, loving )。

想问调用 Calobri Core 这样的库啊包的各位大佬还有什么建议呢?还是照着 ChatGPT 的做?(我的 Python 真的很生,刚学,小时候会用 c )

然后想问下,如果有人有时间帮小的看了这个案例,这种算法用显卡( CUDA )来帮助做会有帮助吗?或者我下一步弄大了,比如一千万字的更加模糊的搜索(比如犹太注经动辄几千万),有什么好的建议提速呢?可以借学校的服务器或者云吗?但是感觉云的 CPU 频率应该也一般。

非常感谢大家指路!小的刚刚用电脑编程对付这些,求拍求建议求更多工具。
Kinnice
343 天前
@pathetique #22 首先是做中文分词 eg: https://github.com/fxsjy/jieba ,然后应该可以非常快,提供个 datasource ?。
julyclyde
343 天前
分词这事有前后顺序依赖吧,能多线程??
Anarchy
343 天前
@julyclyde 按章节、段落、句子都可以啊,没人一句话写一本书的吧。
zhzy
342 天前
看了一下,没做分词,直接每两个字作为一个词;
用 list 循环判断是否存在,而且文本里没有重复的文字么,用两个 for 循环感觉没什么必要,相当于每个词都翻一遍全文,O(n^2),不慢才怪吧。其实直接一个循环然后字典里+1 就行了,虽然也怪怪的,但是至少比现在的快;
其实还是建议不要自己写,或者至少了解一下这类算法应该怎么写...完全用自己的思路闷头搞有时候真的不容易意识到代码里的问题...要不还是老老实实上 NLP 库
ispinfx
342 天前
这么点体量多进程要跑 10 小时?
zhzy
342 天前
@zhzy Python 不是 c ,很多东西不需要自己实现的,而且尽量不要用内置的类型作为变量名,快速糊了一个版本,应该会快一些。
zhzy
342 天前
@zhzy #28 惊了,手快了,counter 那个循环里要判断一下有没有 key ,没有的话设置为 1 ,有的话加 1
hellojukay
342 天前
1. list 如果长度非常的长,可能话很多时间在增长扩容上,建议使用 linklist
2. if xx in [] , 这种判断方式效率非常低,应该使用 hash 的方式
pathetique
342 天前
@zhzy 谢过,我去试试用 panda !不用中文的分词 library 是因为用中文只是试试,其实主业是古代西方语言,最后需要 n-gram skipgram flexgram 之类的还是要自己微调很多自己写然后穷尽搜索。请问 regex 或者 panda 有好的入门建议吗?还,就 GPT 就好?
pathetique
342 天前
@hellojukay 感恩,我马上学一下 linklist 和 hash……
zhzy
342 天前
@pathetique #31 如果只是处理一下停用词的话就一两行代码,不需要学,抄一下就行,百万字其实很少的,只要避免循环嵌套这种性能问题不大的
zhzy
342 天前
@zhzy #29 还是把这个补上吧,用 get 的默认值,不用 if in keys 判断
ispinfx
342 天前
不知道你是不是要 28 楼这种效果,100 万字跑了也就 0.几秒。
ispinfx
342 天前
@zhzy #34 直接 collections.Counter()就能直接加了
liyanm169gd
342 天前
猜一下 OP 的意思,如果是每两个字取下来然后统计频率可以这样做,假定你已经把文本读到了变量 tmpstr 里,total = [tmpstr[i]+tmpstr[i+1] for i in range(0,len(a)-1,2)],如果要统计可以直接 set ,然后拿 set 的值当 dict 的 key ,value 是 total.count("这里是 key")
zhzy
342 天前
@ispinfx #36 是的,可以直接根据文本构造一个步长为 1 每个元素长度为 2 的 list ,然后 Counter 就行,不过那样逻辑就被隐藏掉了,OP 的代码主要问题是扫描 list 来计数,这里只是展示一下更合理的逻辑
ispinfx
342 天前
@zhzy #38 我的意思是用 Counter 你就不用 get 一下再加了。
pathetique
342 天前
@zhzy 跑通了,非常感谢!但是您的代码我还在慢慢理解中……因为不太理解 counter.get 或者 counter.items 这样的命令。是需要去 pathlib 的档案找意思吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/945072

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX