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
Nick2VIPUser
V2EX  ›  Python

Python 中的多线程 vs 多进程中嵌套多线程,哪一种进行 IO 操作的性能更高?

  •  
  •   Nick2VIPUser ·
    nickliqian · 2018-03-09 10:56:32 +08:00 · 5250 次点击
    这是一个创建于 2485 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设一件任务的主要工作是处理网络 IO+读写文件 IO
    使用 python 使用下面三种不同的多任务并行处理方案:

    1. 使用 threading 实现 30 个线程:
      threadingNum=30
    2. 使用 mulitprocess 实现 3 个的进程,每个进程实现 10 个线程:
      processing=3, threadingNum=10
    3. 使用 threading 实现 10 个线程,并手动在主机开三个进程:
      threadingNum=10, executionNum=3

    问题来了:

    • 基于以上情形,那种方案效率会更高
    • 如何去分析这几种情况的执行效率快或者慢的原因
    • 或者说以上三种方案根本没有比较的意义
    • 在使用 python 处理大量 IO 操作时,各位老哥一般都使用什么解决方案呢(不限于标准和第三方库和其他灵活的处理方案)

    (另外补充一下,我特别喜欢这个社区,觉得 V 社的老哥们都是真心在讨论问题和思考问题,每次在这里讨论问题都可以学到很多东西。如果我问问题方式有不恰当的地方和提问频率较高影响到大家的话,希望大家不吝指出!)

    16 条回复    2018-03-09 16:49:12 +08:00
    zhengxiaowai
        1
    zhengxiaowai  
       2018-03-09 11:13:29 +08:00   ❤️ 1
    以下是个人见解:

    1、Socket IO 的话明显是要用 async/await 这种异步 IO,然后开多进程启动效率最好,参考 Tornado 的部署方法

    2、文件读写 IO,对于这种明显是更多的进程更有效果。但是还需要考虑的问题是 CPU 会满载、硬盘 IO 读写速度达到瓶颈,所以更好的方法是 换 CPU 和 更快硬盘。

    3、分析快慢的方法,从了从直观的时间上看出了。更多需要相关的知识,比如线程进程原理可以任何一本教科书,具体的应用手法可以看 APUE 中的部分。

    4、Python 处理网络 IO 各种异步库都有,FILE IO 的话没什么办法,只能用一些取巧的方法。

    以上。
    ioiogoo
        2
    ioiogoo  
       2018-03-09 11:17:14 +08:00   ❤️ 1
    大量网络 IO 和文件 IO 的话推荐 python >= 3.6 的 asyncio,原生支持异步操作,关键词 aiohttp
    ipwx
        3
    ipwx  
       2018-03-09 11:18:06 +08:00   ❤️ 1
    asyncio
    misaka19000
        4
    misaka19000  
       2018-03-09 12:00:55 +08:00   ❤️ 1
    大量 IO 的话线程就行了
    ai277014717
        5
    ai277014717  
       2018-03-09 12:05:51 +08:00   ❤️ 1
    这三种情况的负载应该差不多,性能损失主要应该在上下文切换。应该从 CPU 多核利用率的角度来考虑。像 nodejs 好像可以配置根 CPU 核心数量一样的进程数来提高效率。python 么没听说过类似的功能。
    sivacohan
        6
    sivacohan  
       2018-03-09 12:09:30 +08:00 via iPhone   ❤️ 1
    网络 IO 还好说一点,文件 IO 一定程度上依赖于磁盘类型,碟片的话做顺序读写,SSD 的话做随机读写。另外磁盘本身的缓存和操作系统的缓存都会严重影响测试结果。
    cloudyplain
        7
    cloudyplain  
       2018-03-09 12:40:56 +08:00   ❤️ 1
    python2: 进程+协程 gevent+uwsgi or gunicorn。
    linyinma
        8
    linyinma  
       2018-03-09 12:50:32 +08:00   ❤️ 1
    什么时候多进程多线程和 IO 读写性能有关了?

    你的需求是提高 IO 读写效率,思路应该是同步异步的问题,并行开发多进程 /多线程更多影响的进程上下文的切换带来的效率问题 /以及容错机制的考虑...
    xpresslink
        9
    xpresslink  
       2018-03-09 13:21:47 +08:00   ❤️ 1
    你要从问题瓶颈入手来解决而不是上来就拍脑袋用哪个方案。

    你的需求不太明确,我也不了解你现有系统的架构和性能参数,所以没办法给你正确的建议。现在就能拍出具体建议的都是大神,请鄙视我。

    用哪个方案和场景有关系。你要解决整体性能问题缩短运行时间,还是只是解决阻塞的问题。

    另外你充分理解三种资源的特性,网络、CPU、磁盘

    比如你的网络带宽 2M,要访问的服务器每个提供的下载带宽 1M。那你开两 2 线程要行了。开 30 线程完全没有用最多也就是 2M 了,这种情况下你优化磁盘写入性能不是扯么,除了扩容你的带宽你用什么也提高不了整体性能了。

    如果是运算密集型的任务,比如数据要解压解密再编码,就要考虑开多进程利多核心,如果 CPU 负载很轻只是因为阻塞速度慢,你写成多进程代码要增加复杂度,白浪费精力。

    磁盘是串行读写的,传统机械硬盘就一个磁头在那里寻道读写,成批量大块的连续写入方案才能提高性能,这就是为什么硬盘都有缓存。如果写入是瓶颈而你要想的不是开多个线程,而是在内存内开个更大缓存,弄个写入队列之类的。
    Nick2VIPUser
        10
    Nick2VIPUser  
    OP
       2018-03-09 14:11:02 +08:00
    @zhengxiaowai 谢谢老哥,分析很非常有条理,给我提供了很好的思路~
    Nick2VIPUser
        11
    Nick2VIPUser  
    OP
       2018-03-09 14:21:17 +08:00
    @ai277014717
    @sivacohan
    谢谢答案,想了一下应该是我钻牛角尖了,实际场景几乎不会太计较这三种情况吧~
    Nick2VIPUser
        12
    Nick2VIPUser  
    OP
       2018-03-09 15:02:19 +08:00
    @linyinma 嗯,是的,主要是考虑同步异步的问题,我是突然想到线程和进程的搭配问题钻了牛角尖,谢谢老哥~
    Nick2VIPUser
        13
    Nick2VIPUser  
    OP
       2018-03-09 15:05:03 +08:00
    @xpresslink 谢谢您,把网络、CPU、磁盘三种资源解释的很清楚,令人茅塞顿开。我想我应该从您说的这个角度去思考问题。
    qs
        14
    qs  
       2018-03-09 15:18:56 +08:00   ❤️ 1
    看了半天没看到 1-2-3 这三种情况的对比和解释
    vincenttone
        15
    vincenttone  
       2018-03-09 15:31:50 +08:00   ❤️ 1
    我不太懂 python,但是这类语言从设计上来讲,cpu 密集的话,线程可能并不是一个好的选择。
    但是如果是 IO 密集,根据你具体 IO 的使用、并发的数据使用形式、锁、生命周期等实际状况来选择进程、线程和异步 IO。
    Nick2VIPUser
        16
    Nick2VIPUser  
    OP
       2018-03-09 16:49:12 +08:00
    @qs 我也发现了,可能是这样比较意义不大吧~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3597 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 04:35 · PVG 12:35 · LAX 20:35 · JFK 23:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.