Python多处理性能仅随使用的核心数的平方根而提高

KPM*_*KPM 10 python windows performance multiprocessing parallelism-amdahl

我试图在Python(Windows Server 2012)中实现多处理,并且无法实现我期望的性能提升程度.特别是,对于几乎完全独立的一组任务,我希望通过额外的内核进行线性改进.


我理解 - 尤其是在Windows上 - 开启新流程涉及开销[1],底层代码的许多怪癖可能会妨碍干净的趋势.但理论上,对于完全并行化的任务,趋势最终仍应接近线性[2] ; 如果我正在处理部分连续任务[3],或者可能是后勤.

但是,当我在主要检查测试函数(下面的代码)上运行multiprocessing.Pool N_cores=36时,在我进入预期性能之前,我得到了一个近乎完美的平方根关系(我服务器上的物理核心数)额外的逻辑核心.


是我的性能测试结果图: 在此输入图像描述
(" 归一化性能 "是[具有1个 CPU核心的运行时间]除以[具有N个 CPU核心的运行时间]).

通过多重处理使收益大幅减少是否正常?或者我错过了实施的内容?


import numpy as np
from multiprocessing import Pool, cpu_count, Manager
import math as m
from functools import partial
from time import time

def check_prime(num):

    #Assert positive integer value
    if num!=m.floor(num) or num<1:
        print("Input must be a positive integer")
        return None

    #Check divisibility for all possible factors
    prime = True
    for i in range(2,num):
        if num%i==0: prime=False
    return prime

def cp_worker(num, L):
    prime = check_prime(num)
    L.append((num, prime))


def mp_primes(omag, mp=cpu_count()):
    with Manager() as manager:
        np.random.seed(0)
        numlist = np.random.randint(10**omag, 10**(omag+1), 100)

        L = manager.list()
        cp_worker_ptl = partial(cp_worker, L=L)

        try:
            pool = Pool(processes=mp)   
            list(pool.imap(cp_worker_ptl, numlist))
        except Exception as e:
            print(e)
        finally:
            pool.close() # no more tasks
            pool.join()

        return L


if __name__ == '__main__':
    rt = []
    for i in range(cpu_count()):
        t0 = time()
        mp_result = mp_primes(6, mp=i+1)
        t1 = time()
        rt.append(t1-t0)
        print("Using %i core(s), run time is %.2fs" % (i+1, rt[-1]))
Run Code Online (Sandbox Code Playgroud)

注意:我知道对于这个任务来说,实现多线程可能更有效,但是由于GIL,这个简化模拟的实际脚本与Python多线程不兼容.

use*_*197 8

@KellanM值得 进行定量性能监测[+1]

我错过了实施的内容吗?

是的,您从流程管理的所有附加成本中抽象出来.

虽然你已经表达了对" 额外核心的线性改进 "的期望,但由于几个原因(甚至共产主义的炒作未能免费提供任何东西),这在实践中几乎不会出现.

Gene AMDAHL制定了收益递减初始法则. 在此输入图像描述
一个更新的,重新制定的版本,还考虑了流程管理{setup | terminate}的影响 - 附加开销成本,并试图处理原子性处理(给定大型工作包有效载荷不能轻易地重新位于/重新分布在大多数常见编程系统中的可用CPU核心池上(除了一些确实具体的微调度技术,如语义设计的PARLANSE或LLNL的SISAL中所展示的那些在过去已经如此丰富多彩).


最好的下一步?

如果确实对这个领域感兴趣,可以总是通过实验来衡量和比较流程管理的实际成本(加上数据流成本,加上内存分配成本,......直到流程终止和结果重新组装为主过程)以便定量公平地记录和评估使用更多CPU核心的附加成本/效益比(这将获得python,重新实现整个python-interpreter状态,包括其所有的内存状态,之前第一个有用的操作将在第一个生成和设置过程中执行.

表现不佳(低于前一种情况)
,如果不是灾难性的影响(从下面的后一种情况下),
任生病工程资源映射的政策,是它
的" 下预约 "从池中-resources CPU -cores

一个此处讨论了 " 过度预订 " - 来自RAM空间池的资源

上面重新制定的阿姆达尔定律的链接将帮助您评估收益递减点,而不是支付超过收到的金额.

Hoefinger et Haunschmid实验可以作为一个很好的实际证据,越来越多的处理节点(无论是本地O/S管理的CPU核心,还是NUMA分布式架构节点)将如何开始降低最终性能,
其中一个点收益递减(在开销不可知的阿姆达尔定律中证明)
实际上将开始成为一个点,之后你支付的金额超过收到.:

在此输入图像描述 祝你好运! 在此输入图像描述


最后但并非最不重要的,

NUMA /非地方性问题得到了他们的意见,进入了关于HPC级调整(缓存/内存计算策略)的扩展的讨论,并且可能 - 作为副作用 - 帮助检测缺陷(如@所报告的)eryksun上面).有人可以通过使用lstopo工具来查看一个人的平台实际NUMA拓扑,看一下操作系统正在尝试使用的抽象,一旦调度"正常" - [CONCURRENT]在这样的NUMA资源拓扑上执行任务:

在此输入图像描述