多线程 VS 多进程?

2015-05-19 09:39:55 +08:00
 cc7756789
初学,多进程使用multiprocessing, 多线程使用threading。

我用一个爬虫测试多线程和多进程,线程为50个,执行完毕为10s;多进程开辟了50个子进程,执行完毕100s和用for循环差不多,而且奇卡无比。

不是说,多线程和多进程没有谁好谁坏之风,那我的思路错在哪里,难道是因为多进程不共享内存,故需要开启50个内存空间,所以奇卡无比,那么什么情况下该用多进程呢?
6481 次点击
所在节点    Python
24 条回复
lhy360121
2015-05-19 09:53:32 +08:00
像爬虫这种io密集的任务用多线程就好,开进程比开线程消耗的系统资源多。 cpu密集的任务才用多进程。

你运行的时候,可以看看2中情况下系统消耗的资源,做个对比。

另外,你用的什么系统。。
nicksite
2015-05-19 09:57:53 +08:00
像这种IO密集的,主要瓶颈不是在于网络的通畅么。
cc7756789
2015-05-19 10:06:00 +08:00
@lhy360121 ubuntu
bengol
2015-05-19 10:10:24 +08:00
你能先把profiler挂上么
clino
2015-05-19 10:15:34 +08:00
"多进程开辟了50个子进程,执行完毕100s和用for循环差不多,而且奇卡无比"
估计你使用姿势不当

另外爬虫是不是也可以考虑用协程如gevent,占用资源更少
zzh161
2015-05-19 10:38:37 +08:00
网络或者磁盘操作,这种IO密集型的任务多线程在提高效率方面会比较明显吧。如果是计算密集型的,那python的多线程就无法提高效率,甚至会降低效率,这方面可以自行搜索“python GIL锁”

另外,楼上说的用协程,在楼主所说的这种情况下,应该效率不会比多线程高,因为协程是单线程的,同时只能有一个任务在执行,考虑到爬虫还要读页面,解析页面,这里面有不少是计算任务,如果不是网络很慢的情况下,还是会造成很多网页读好了,等待解析。
jimzhong
2015-05-19 11:15:28 +08:00
请问楼主在什么平台下跑程序的。如果windows进程开销会比线程大一些,希望我没有搞错。多进程也会共享内存的,一般都是在写入时复制。

由于CPython的多进程实际上不是在多个核心上跑的。所以多线程性能并不会提升吧。
quix
2015-05-19 14:21:03 +08:00
爬虫用异步 io 就行吧.. 无须并行
chevalier
2015-05-19 14:27:53 +08:00
爬虫90%的时间都是网络等待,用异步吧
caoyue
2015-05-19 14:46:36 +08:00
上面大家说的都有道理,具体到楼主的问题,多进程消耗是会比多线程大一点,但是应该不至于大到 10 倍吧
方便的话可以贴个代码,方便大家分析
est
2015-05-19 14:52:53 +08:00
贴newrelic。
cc7756789
2015-05-19 14:53:35 +08:00
import requests
from bs4 import BeautifulSoup
import multiprocessing

n = 0
url_list = ['http://ubuntuforums.org/forumdisplay.php?f=333', ]
for x in range(1, 50):
n += 1
raw_url = 'http://ubuntuforums.org/forumdisplay.php?f=333&page=%d' % n
url_list.append(raw_url)

def running(url, q, lock):
lock.acquire()
html = requests.get(url)
if html.status_code == 200:
html_text = html.text
soup = BeautifulSoup(html_text)
with open('/home/zhg/Pictures/cao.txt', 'a+') as f:
for link in soup.find_all('a', 'title'):
s = 'http://ubuntuforums.org/' + str(link.get('href')) + ' ' + str(link.get_text().encode('utf-8'))
f.writelines(s)
f.writelines('\n')
lock.release()

if __name__ == '__main__':
manager = multiprocessing.Manager()
p = multiprocessing.Pool(len(url_list))
q = manager.Queue()
lock = manager.Lock()
for x in url_list:
p.apply_async(running, args=(x, q, lock))
p.close()
p.join()
print "process ended"
Valyrian
2015-05-19 14:58:23 +08:00
多进程比多线程费资源这是基础知识吧
JackeyGao
2015-05-19 14:59:16 +08:00
计算密集采取多进程充分利用CPU多核心优势, I/O密集等待时间过多采取多线程。

如果是python 2.7 或者 python 3.2+的话, 推荐使用concurrent.futures 做异步并发
WKPlus
2015-05-19 17:22:58 +08:00
你的running函数一把锁从头加到尾,怎么并行执行啊?
hitsmaxft
2015-05-19 17:31:47 +08:00
这点小任务那还用得着讲究到这个地步, 一般多核多线程效率够了, io 密集型大不了上协程或者 reactor 之类的。

多进程为的是资源隔离,或者弥补那些多核支持不好的语言
kingname
2015-05-19 18:37:12 +08:00
多线程使用map会比使用threading好用。
请戳http://jikexueyuan.com/course/902.html
matrix67
2015-05-19 18:56:38 +08:00
dummy呀
cc7756789
2015-05-19 18:58:08 +08:00
@WKPlus 额,确实是加锁的关系,我理解较浅,锁一般用在什么地方?
WKPlus
2015-05-19 19:09:31 +08:00
@cc7756789 锁用来防止不能并发执行的代码被并发执行
你的running函数里面不能并发执行的地方应该是写文件那块,你可以把结果返回最后统一写文件

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

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

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

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

© 2021 V2EX