代码之家  ›  专栏  ›  技术社区  ›  Brad Solomon

使用的辅助进程数超过了核心数

  •  3
  • Brad Solomon  · 技术社区  · 7 年前

    This PYMOTW中的示例给出了使用 multiprocessing.Pool() 在哪里 processes

    pool_size = multiprocessing.cpu_count() * 2
    

    (否则,该类将默认为 cpu_count() .)

    这有什么合法性吗?创造的员工数量超过核心员工数量会产生什么影响?是否有理由这样做,或者可能会在错误的方向上增加额外的开销?我很好奇为什么它会被包括在我认为是一个有信誉的站点的例子中。

    在最初的测试中,它实际上似乎让事情变得慢了一点:

    $ python -m timeit -n 25 -r 3 'import double_cpus; double_cpus.main()'
    25 loops, best of 3: 266 msec per loop
    $ python -m timeit -n 25 -r 3 'import default_cpus; default_cpus.main()'
    25 loops, best of 3: 226 msec per loop
    

    double_cpus.py :

    import multiprocessing
    
    def do_calculation(n):
        for i in range(n):
            i ** 2
    
    def main():
        with multiprocessing.Pool(
            processes=multiprocessing.cpu_count() * 2,
            maxtasksperchild=2,
        ) as pool:
            pool.map(do_calculation, range(1000))
    

    default_cpus.py :

    def main():
        # `processes` will default to cpu_count()
        with multiprocessing.Pool(
            maxtasksperchild=2,
        ) as pool:
            pool.map(do_calculation, range(1000))
    
    2 回复  |  直到 6 年前
        1
  •  5
  •   Darkonaut    7 年前

    纯粹地 cpu受限,但也涉及一些I/O。

    True ,发生了什么 n_sleep -时代。 那样的话,你就可以睡个好觉了 sleep_sec_total 可以注入到计算中。

    # default_cpus.py
    import time
    import multiprocessing
    
    
    def do_calculation(iterations, n_sleep, sleep_sec):
        for i in range(iterations):
            if i % (iterations / n_sleep) == 0:
                time.sleep(sleep_sec)
    
    
    def main(sleep_sec_total):
    
        iterations = int(10e6)
        n_sleep = 100
        sleep_sec = sleep_sec_total / n_sleep
        tasks = [(iterations, n_sleep, sleep_sec)] * 20
    
        with multiprocessing.Pool(
            maxtasksperchild=2,
        ) as pool:
            pool.starmap(do_calculation, tasks)
    

    # double_cpus.py
    ...
    
    def main(sleep_sec_total):
    
        iterations = int(10e6)
        n_sleep = 100
        sleep_sec = sleep_sec_total / n_sleep
        tasks = [(iterations, n_sleep, sleep_sec)] * 20
    
        with multiprocessing.Pool(
            processes=multiprocessing.cpu_count() * 2,
            maxtasksperchild=2,
        ) as pool:
            pool.starmap(do_calculation, tasks)
    

    我使用 sleep_sec_total=0 (纯cpu限制)和 sleep_sec_total=2

    结果与 睡眠秒总数=0

    $ python -m timeit -n 5 -r 3 'import default_cpus; default_cpus.main(0)'
    5 loops, best of 3: 15.2 sec per loop
    
    $ python -m timeit -n 5 -r 3 'import double_cpus; double_cpus.main(0)'
    5 loops, best of 3: 15.2 sec per loop
    

    给定一个合理的计算大小,对于一个纯cpu限制的任务,默认cpu和双cpu几乎没有区别。在这里,两个测试都有相同的最佳时间。

    睡眠秒总数=2

    $ python -m timeit -n 5 -r 3 'import default_cpus; default_cpus.main(2)'
    5 loops, best of 3: 20.5 sec per loop
    $ python -m timeit -n 5 -r 3 'import double_cpus; double_cpus.main(2)'
    5 loops, best of 3: 17.7 sec per loop
    

    现在,添加2秒睡眠作为I/0的虚拟,画面看起来就不同了。与默认值相比,使用两倍于默认值的进程可以提高大约3秒的速度。

        2
  •  2
  •   Uku Loskit    7 年前

    这是因为当线程等待I/O时,处理器实际上可以在其他线程上工作。

    如果您有一个CPU繁重的任务,那么更多的处理器实际上会减慢它。