【问题标题】:Why is my multiprocessing slower than that shown on youtube?为什么我的多处理比 youtube 上显示的慢?
【发布时间】:2021-11-03 03:35:24
【问题描述】:
import time
import multiprocessing


def do_something():
    print("sleep 1 second")
    time.sleep(1)
    print("Done sleeping...")

if __name__ =='__main__':
    start = time.perf_counter()
    processes = []
    for _ in range(10):
        p = multiprocessing.Process(target=do_something)
        p.start()
        processes.append(p)

    for process in processes:
        process.join()
    finish = time.perf_counter()

    print(f'Finished in {round(finish-start, 2)} second(s)')

上面是我的代码,我想做的是进行多处理,问题是我的代码最终运行了 1.22 秒,而 youtube 上的人只需要 1.02 秒!我正在使用 pycharm (python 3.9) 并检查我的任务管理器,当我运行此代码时,我的 cpu 利用率没有达到最大值,我的内存也是如此。是不是因为我用的是笔记本电脑而不是台式机?我的电脑硬件会影响速度吗? 0.2 秒对我来说意义重大,因为我正在做一个项目,而一秒钟的时间很重要。

或者是因为我使用了if __name__ =='__main__':,但问题是如果我不使用这一行,我的代码将根本无法运行,但视频中的那个人能够在没有这一行的情况下运行他的代码(我检查了,我没有打开任何其他文件,我只有一个是main.py,如上所示。我个人认为这不会影响速度,但如果确实如此,请告诉我。

我正在谈论的 youtube 视频是 Corey Schafer 的“Python 多处理教程:使用多处理模块并行运行代码”

视频:Python Multiprocessing Tutorial: Run Code in Parallel Using the Multiprocessing Module

14:09可以看到他运行代码只需要1.02秒

【问题讨论】:

    标签: python performance debugging multiprocessing multiprocess


    【解决方案1】:

    if __name__ == "__main__" 是衍生操作系统(如 Windows)所必需的,而不是 fork 系统(如 linux)所必需的。 Windows 运行新进程的速度稍慢一些,因为它需要执行一个新的 python 并从调用进程中提取/分解环境,而 linux 只是分叉并为内存提供不同的视图。我不会感到惊讶,这是你额外的 0.2 秒。请注意,这是一次性的事情,所以如果您的流程有很多工作要做,没什么大不了的。

    虽然进程的数量通常很重要,但由于唯一的工作是 sleep(1),因此您需要创建许多进程才能做到这一点。

    我不知道pycharm是否与它有关。值得在您的命令行上进行测试以查看。

    我在我的 linux 笔记本电脑上运行了 1.01 秒。当我像在 Windows 上那样强制“生成”模式时,它上升到 1.11 秒。所以,对我来说,生成的开销是 0.1 秒。

    更新

    考虑到进程是串行创建的,这就是花费额外时间的地方,我尝试将这部分操作与进程内线程并行化。首先我尝试了一个线程池,但这太慢了,但是仅仅让一个线程创建进程就可以在大约一秒钟内加速代码运行,从而消除了 0.1 秒(在你的情况下是 0.2 秒)的劣势。

    import time
    import multiprocessing
    import threading
    
    def do_something():
        print("sleep 1 second")
        time.sleep(1)
        print("Done sleeping...")
    
    def run_do_something():
        p = multiprocessing.Process(target=do_something)
        p.start()
        processes.append(p)
    
    if __name__ =='__main__':
        multiprocessing.set_start_method('spawn')
        start = time.perf_counter()
        threads = []
        processes = []
        for _ in range(10):
            t = threading.Thread(target=do_something)
            t.start()
            threads.append(t)
    
        for thread in threads:
            thread.join()
    
        for process in processes:
            process.join()
        finish = time.perf_counter()
    
        print(f'Finished in {round(finish-start, 2)} second(s)')
    

    【讨论】:

    • 等一下,你甚至没有在你的程序中调用 run_do_something,如果我是对的,你只使用线程而不是多处理?如果我错了,请纠正我
    【解决方案2】:

    当然,硬件在运行时间方面很重要,尤其是在使用多道程序时。这取决于内核数量、超线程可能性、CPU 频率和内存。

    【讨论】:

    • 虽然您所说的从一般意义上来说可能是正确的,但我认为它不适用于这种情况,因为该任务只是休眠了相对较长的时间——这取消了大部分考虑,
    • @martineau 尽管代码行数较少,但它需要处理能力来调用 pvm、gc 并导入模块和所有预处理内容
    • 我认为这不足以解释差异 - 这可能是因为 OP 使用的是 Windows 而视频中的人不是(以及在操作系统中启动单独进程的方式) .
    猜你喜欢
    • 1970-01-01
    • 2020-10-14
    • 2018-09-25
    • 2014-08-14
    • 1970-01-01
    • 2015-03-22
    • 2012-03-28
    • 2016-10-29
    相关资源
    最近更新 更多