加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

关于linux下python多线程cpu占用率高的问题

(2018-09-06 17:08:49)
分类: my_work

Python能否占满CPU,Python多线程?

 

因为Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock。

任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。

这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。

    Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。

 

昨天晚上在寝室写python多线程的时候,用了几个测试的程序,分别是递归方法求斐波那契数的值。分别采用单线程一个一个执行的方法和采用多线程调用的方法。观察所用的时间基本上差不多的。

然后我在每个函数内部加入sleep()函数以后,分别让它们睡零点几秒钟。这样一来,明显多线程执行所用的时间要少很多。

这时我突然好奇,想看看在用python多线程执行的时候,是否可以利用CPU多个核心呢?我的笔记本是i3处理器,双核,4线程(我至今不知道这里所指的4线程具体是什么意思,之前和老师交流过,猜测可能是在硬件上做了像我们软件执行的时候的躲进程这样类似的东西,但是不确定),反正在我的系统下的系统监视器里面可以看到有4个核的利用率频线。我就观察这种曲线的变化方式:当我每一个都是单线程地运行的时候。显示的画面中有一个CPU爆满;但是在多线程运行的时候,是每一个利用一些。

 

显然多线程运行的时候时间反而长了很多,虽然有上下文切换的时间损耗,但是若是能够利用多核的话也不至于那么慢,另外由系统监视器可以看出多线程的时候也没有把各个核利用率达到很高的一个水平。所以当时推断python的多线程并没有很多的利用多核CPU,其实之前也有听说过python对于多核CPU支持是个缺陷,现在是有真的体会,但是我只是凭自己的小实验,也不能有很打保证啊,也只是猜测,后来翻了一下《python参考手册》发现有这么一句话,看来是真的证实了我自己的猜想啊!!!

 

尽管是很低级的问题,但是对于初学的我来说,还是有很大的喜悦的。

下面是实验的代码:

fab.py:

 1 # -*- coding: utf-8 -*-
2 from myThread import MyThread
3 from time import ctime
4 from time import sleep
5 import sys
6 
7 def fib(x):
8 #    sleep(0.005)
9     if x<2:return 1
10     return (fib(x-2) + fib(x-1))
11 
12 def fac(x):
13 #    sleep(0.05)
14     if x<2:return 1
15     return (fac(x-2)+fac(x-1))
16 
17 def sum(x):
18 #    sleep(0.05)
19     if x<2:return 1
20     return (sum(x-2)+sum(x-1))
21 
22 funcs = [fib,fac,sum]
23 n = 35
24 
25 def main():
26     nfuncs = range(len(funcs))
27     sys.stdout.write('***SINGLE THREAD\n')
28     for i in nfuncs:
29         sys.stdout.write('starting %s at: %s\n' %(funcs[i].__name__,ctime()))
30         print funcs[i](n)
31         sys.stdout.write("%s finished at: %s\n"% (funcs[i].__name__,ctime()))
32     sys.stdout.write('\n***MULTIPLE THREADS\n')
33 
34     threads = []
35 
36     for i in nfuncs:
37         t = MyThread(funcs[i],(n,),funcs[i].__name__)
38         threads.append(t)
39 
40     for i in nfuncs:
41         threads[i].start()
42 
43     for i in nfuncs:
44         threads[i].join()
45         print threads[i].getResult()
46 
47     sys.stdout.write('all done\n')
48 
49 if __name__ == '__main__':
50     main()
myThread.py:
 1 import threading 
2 from time import ctime
3 import sys
4 
5 class MyThread(threading.Thread):
6     def __init__(self,func,args,name=''):
7         threading.Thread.__init__(self)
8         self.name = name
9         self.func = func
10         self.args = args
11     
12     def getResult(self):
13         return self.res
14 
15     def run(self):
16         sys.stdout.write("starting %s at: %s\n" % (self.name,ctime()))
17         self.res = apply(self.func,self.args)
18         sys.stdout.write("%s finished at: %s\n" % (self.name,ctime()))

 

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有