0x00前言
近期处理亿级数据,发现对于耗费CPU的程序(正则检索等)而言Python的多线程由于线程调度还不如单线程效率高,然而多CPU环境下,多线程与单线程最多只能使得单个CPU达到100%利用率。利用Python多进程(multiprocessing)可以使得多个CPU同时工作,利用效率大大提升
0x01原理介绍
1.1CPU密集型和IO密集型
CPU密集型:程序线性执行,大量占用CPU,总是接近100%(如:正则匹配替换大量文本)
IO密集型:程序大量时间花费在等待I/O操作,CPU总是闲置,在10%左右(如:网络请求)
1.2python多线程和多进程
python的多线程和其他编程语言的多线程有很大的区别,python多线程即使在多核CPU主机上也只能使用一个CPU,不是真正意义上的并发执行。
对于IO密集型的程序而言,使用多线程技术可以在CPU阻塞等待的间隔执行其他操作,可以提高CPU的使用效率,PS:gevent库协程技术也是只在IO密集型程序比较有效
对于CPU密集型的程序而言,原本CPU就是一直繁忙的状态,强制使用多线程技术,不会增加CPU的利用效率,却增加线程切换的代价,可能导致多线程的执行效率还不如单线程的执行效率。在多核CPU主机可以采用pytho多进程(multiprocessing)使得程序同时使用多个CPU,可以达到程序真实意义上的并行(进程数不要超过CPU核数)
0x02实际对比
测试环境:
Ubuntu系统
16核CPU主机
2.1多线程测试程序
代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#!/usr/bin/env python
# -*- coding: utf-8 -*-
import Queue
import threading
queueLock = threading.Lock()
workQueue = Queue.Queue()
thread_num = 11
threads = []
class MyThread (threading.Thread):
def __init__(self, Queue,id):
threading.Thread.__init__(self)
self.q = Queue
self.id = id
def run(self):
while not workQueue.empty():
get_info(self.q.get(),self.id)
def get_info(data,threading_id):
for i in range(1000000):
a=str(threading)+data
def main():
for i in range(1000):
workQueue.put(str(i))
for i in range(thread_num):
thread = MyThread(workQueue, i)
thread.start()
threads.append(thread)
for t in threads:
t.join()
if __name__ == '__main__':
main()
运行python程序,监控CPU使用情况只有1个CPU在使用状态
2.2多进程测试
代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#!/usr/bin/env python
# -*- coding: utf-8 -*-
import multiprocessing
processors = []
processor_num = 11
workQueue = multiprocessing.Queue()
def single_processor(q,id):
while not workQueue.empty():
get_info(q.get(),id)
def get_info(data,processor_id):
for i in range(1000000):
a=str(processor_id)+data
def main():
for i in range(1000):
workQueue.put(str(i))
for i in range(processor_num):
p = multiprocessing.Process(target=single_processor, args=(workQueue,i))
p.start()
processors.append(p)
for i in processors:
i.join()
if __name__ == '__main__':
main()
运行python程序,监控CPU使用情况可以看出有11个CPU均处于100%利用状态(注:进程数最好不要超过CPU核数)
0x03总结
当程序功能需要大量使用CPU,没有IO等待延迟即程序为CPU密集型的时候,且主机为多核的情况下,Python多进程可以达到极好的效率。