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

Python 如何优化简单代码的多进程速度

  •  
  •   JustBecause · 285 天前 · 1294 次点击
    这是一个创建于 285 天前的主题,其中的信息可能已经有所发展或是发生改变。

    写了一个程序,使用 PySide6 带有 GUI ,用来处理字幕的文本内容

    因为要用到 CPU 处理,多线程和异步效果不佳,所以想做成多进程的形式处理,用的进程池来操作

    pool = multiprocessing.Pool()
    results = pool.map(analysisSubtitles, subtitles_list)
    pool.close()
    pool.join()
    

    analysisSubtitles 是识别每个字幕每行内容并做替换。每个字幕文件处理时间 30-300ms 左右,但使用了多进程以后,无论拖入一个还是十个文件,都要至少 1.5s 起步才能处理完成

    这是什么原因导致的,有没有办法优化?

    百度谷歌必应和 GPT 都问过了,实在找不到问题原因

    ===

    macOS 上我加了 multiprocessing.set_start_method("fork") 解决,基本在 0.5s 内就可以完成

    但我也有在 windows 使用的需求,请问 windows 下如何优化才能减少执行时间?

    感谢各位

    6 条回复    2023-07-19 16:55:20 +08:00
    sordidclown
        1
    sordidclown  
       284 天前
    Python 新手,猜一下可能是任务太轻量了? Windows 上没有 `fork`,默认是 `spawn` 这种重量级的构建方式。鉴于 MacOS 上使用 `fork` 能降低执行时间。所以可能任务执行的时间还没有构建新进程的时间长,也就是“构建新进程”所占时间的比重较大。
    我觉得如果要减少执行时间,又要多进程,你可以试着限制进程池的大小。或者说任务比较多的时候再开多进程,这样能有效减少构建新进程占用的时间。
    PS:网上搜了点资料猜的,大佬们轻喷。
    sordidclown
        2
    sordidclown  
       284 天前
    我再提供一个思路,比如说将“读写文件”和“实际处理处理”分离成两个函数,一个作为 IO 密集函数,一个作为 CPU 密集函数。IO 密集的部分使用线程或者协程处理,CPU 密集的部分采用多线程处理。这两部分可以使用管道或者队列通信。
    JustBecause
        3
    JustBecause  
    OP
       284 天前
    @sordidclown #2
    任务确实非常轻量,可以理解成 time.sleep(0.3)这样子,主要是执行的数量多
    实际上拖放文件进窗口就开始执行了,这部分没有太多的操作
    时间主要在 pool.map 这一步上,所以读写文件和实际处理分开大概没效果
    试过把多进程执行的函数改成 time.sleep(0.3),但也要花 1.5s 以上处理
    wuwukai007
        4
    wuwukai007  
       284 天前
    开多个进程启动很慢的,做一个常驻进程池
    JustBecause
        5
    JustBecause  
    OP
       283 天前
    @wuwukai007 #4
    感谢 常驻进程池真能行
    之前每次执行都执行一遍 pool = multiprocessing.Pool(),现在放到软件启动时创建,速度就正常了
    runstone
        6
    runstone  
       283 天前
    concurrent.futures.ProcessPoolExecutor 作为进程池应该好一些吧。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1002 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 19:02 · PVG 03:02 · LAX 12:02 · JFK 15:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.