V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
cc7756789
V2EX  ›  Python

多线程 VS 多进程?

  •  1
     
  •   cc7756789 · 2015-05-19 09:39:55 +08:00 · 6664 次点击
    这是一个创建于 3511 天前的主题,其中的信息可能已经有所发展或是发生改变。
    初学,多进程使用multiprocessing, 多线程使用threading。

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

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

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

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

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

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

    由于CPython的多进程实际上不是在多个核心上跑的。所以多线程性能并不会提升吧。
    quix
        8
    quix  
       2015-05-19 14:21:03 +08:00
    爬虫用异步 io 就行吧.. 无须并行
    chevalier
        9
    chevalier  
       2015-05-19 14:27:53 +08:00
    爬虫90%的时间都是网络等待,用异步吧
    caoyue
        10
    caoyue  
       2015-05-19 14:46:36 +08:00
    上面大家说的都有道理,具体到楼主的问题,多进程消耗是会比多线程大一点,但是应该不至于大到 10 倍吧
    方便的话可以贴个代码,方便大家分析
    est
        11
    est  
       2015-05-19 14:52:53 +08:00
    贴newrelic。
    cc7756789
        12
    cc7756789  
    OP
       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
        13
    Valyrian  
       2015-05-19 14:58:23 +08:00
    多进程比多线程费资源这是基础知识吧
    JackeyGao
        14
    JackeyGao  
       2015-05-19 14:59:16 +08:00
    计算密集采取多进程充分利用CPU多核心优势, I/O密集等待时间过多采取多线程。

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

    多进程为的是资源隔离,或者弥补那些多核支持不好的语言
    kingname
        17
    kingname  
       2015-05-19 18:37:12 +08:00
    多线程使用map会比使用threading好用。
    请戳http://jikexueyuan.com/course/902.html
    matrix67
        18
    matrix67  
       2015-05-19 18:56:38 +08:00 via Android
    dummy呀
    cc7756789
        19
    cc7756789  
    OP
       2015-05-19 18:58:08 +08:00
    @WKPlus 额,确实是加锁的关系,我理解较浅,锁一般用在什么地方?
    WKPlus
        20
    WKPlus  
       2015-05-19 19:09:31 +08:00
    @cc7756789 锁用来防止不能并发执行的代码被并发执行
    你的running函数里面不能并发执行的地方应该是写文件那块,你可以把结果返回最后统一写文件
    9hills
        21
    9hills  
       2015-05-19 19:13:45 +08:00 via iPhone
    Lz 这个锁加的。
    9hills
        22
    9hills  
       2015-05-19 19:15:54 +08:00 via iPhone
    @cc7756789 把锁去了就行了。追加写在普通情况下是原子的。更何况你的锁也包的太大了
    wind3110991
        23
    wind3110991  
       2015-05-19 23:46:25 +08:00   ❤️ 1
    @cc7756789 可以用下markdown语法。。强迫症看python难受 = 。 =

    ```python
    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"

    ```
    slideclick
        24
    slideclick  
       2015-05-20 10:33:00 +08:00
    windows系统创建进程开销很大。另外IO密集型,多线程就够了。
    什么时候用多进程?CPU密集的,这时需要利用多核,python只有进程才可以分布的多个核上面,线程做不到分布。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2856 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 03:08 · PVG 11:08 · LAX 19:08 · JFK 22:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.