为啥我的多处理比 youtube 上显示的慢?

Posted

技术标签:

【中文标题】为啥我的多处理比 youtube 上显示的慢?【英文标题】: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秒

【问题讨论】:

【参考方案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 而视频中的人不是(以及在操作系统中启动单独进程的方式) .

以上是关于为啥我的多处理比 youtube 上显示的慢?的主要内容,如果未能解决你的问题,请参考以下文章

对为啥我的算法运行速度比它应该的慢感到困惑

为啥在像 STB 这样的嵌入式系统上,钴在 Youtube 中的性能比铬好得多?

为啥我在 Sklearn 管道中的 OneHotEncoding 后得到的列比预期的多?

为啥编译器分配的内存比需要的多? [复制]

为啥 Python 的多处理模块在 Windows 上启动新进程时会导入 __main__?

为啥我的 UIWebView 不显示 Javascript YouTube 播放器 iFrame?