|
|
1
239
简短回答Pool的chunksize算法是一种启发式算法。它为您试图填充到Pool方法中的所有可想象的问题场景提供了一个简单的解决方案。因此,它无法针对任何情况进行优化 具体的 脚本 该算法将iterable任意划分为比naive方法多大约四倍的块。更多的块意味着更多的开销,但增加了调度的灵活性。这个答案将如何显示,这将导致平均更高的工人利用率,但 “知道这一点很好,”你可能会想,“但知道这一点如何帮助我解决具体的多处理问题呢?”嗯,事实并非如此。更诚实的简短回答是,“没有简短的答案”,“多处理是复杂的”和“这取决于”。观察到的症状可能有不同的根源,即使是在类似的情况下。 这个答案试图为您提供一些基本概念,帮助您更清楚地了解池的调度黑匣子。它还试图为您提供一些基本的工具,帮助您识别和避免与块大小相关的潜在悬崖。 目录
1.定义
这里的一大块是一部分
任务在辅助进程中的数据物理表示如下图所示。
此图显示了对的调用示例
而“任务”一词的用法
整体
一个块的处理由内的代码匹配
人事军官 由Python内部开销和进程间通信(IPC)开销组成。Python中的每任务开销附带了打包和解包任务及其结果所需的代码。IPC开销伴随着线程的必要同步以及不同地址空间之间的数据复制(需要两个复制步骤:父级->队列->子级)。IPC开销的大小取决于操作系统、硬件和数据的大小,因此很难对影响进行概括。 2.并行化目标当使用多处理时,我们的总体目标(显然)是最小化所有任务的总处理时间。为了实现这一总体目标,我们的 技术目标 优化硬件资源的利用 .
首先,任务的计算量必须足够大(密集),以便 我们必须为并行化支付的PO。PO的相关性随着每个任务的绝对计算时间的增加而降低。或者,换句话说,绝对计算时间越大 佩尔塔塞尔 对于你的问题,不太相关的人需要减少采购订单。如果您的计算每个任务需要几个小时,那么IPC开销相比之下可以忽略不计。这里的主要关注点是防止在分配所有任务后使工作进程空闲。保持所有内核都加载意味着,我们正在尽可能多地并行化。 3.并行化场景
问题的主要因素是计算时间的长短 变化 变异系数 ( CV )对于每个任务的计算时间。 从这种变化的程度来看,以下两种极端情况是:
为了更好地记忆,我将这些场景称为:
在一个 最好一次分发所有TaskEL,以将必要的IPC和上下文切换保持在最低限度。这意味着我们只想创建尽可能多的块,尽可能多的工作进程。如上所述,PO的权重随着每个taskel的计算时间缩短而增加。 为了获得最大吞吐量,我们还希望所有工作进程都处于繁忙状态,直到处理完所有任务(没有空闲的工作进程)。为了实现这一目标,分布式块应该具有相同的大小或接近相同的大小。
广泛情景最典型的例子是 广泛情景 这将是一个优化问题,结果要么快速收敛,要么计算可能需要数小时,甚至数天。在这种情况下,通常无法预测任务将包含“轻任务”和“重任务”的混合,因此不建议一次在任务批中分发太多任务。一次分发的任务比可能的少,这意味着增加了调度的灵活性。这是实现所有核心的高利用率这一子目标所必需的。
如果
4.块大小的风险>1.广泛情景 -iterable,我们要将其传递到池方法中:
为了简单起见,我们假设所需的计算时间为秒,而不是实际值,仅为1分钟或1天。
我们假设该池有四个工作进程(在四个核心上),并且
因为我们有足够的工人,而且计算时间足够长,我们可以说,每个工人进程首先都会得到一块工作空间。(快速完成任务的情况不一定如此)。此外,我们可以说,整个处理过程大约需要86400+60秒,因为在这个人工场景中,这是块的最高总计算时间,我们只分配一次块。
…以及相应的块:
不幸的是,我们的iterable的排序几乎是我们总处理时间的两倍(86400+86400)!获得恶意(8640086400)块的工人正在阻止任务中的第二个重taskel分配给已经完成(60,60)块的空闲工人之一。如果我们采取行动,我们显然不会冒这样一个令人不快的结果的风险
这就是大块头的风险。使用更高的块大小,我们可以用调度灵活性换取更少的开销,在上述情况下,这是一个糟糕的交易。 我们将在第章中看到什么 6.量化算法效率 密集场景
在下面,您将在源代码中找到该算法的一个稍加修改的版本。如你所见,我切断了下半部分,并将其包装成一个函数,用于计算
为了确保我们都在同一页上,下面是
用于查看乘法的效果
上面的函数计算原始chunksize(
下面您可以看到使用此函数的输出创建的两个图形。左图仅显示了的块大小
记住块大小
该算法还包括:
现在,在一些案例中
是
余数
在下图中,您可以看到“
额外治疗
“具有这样的效果,即
真实因素
对于
最终,增加
更有趣的是,我们以后会看到,更重要的是
额外治疗
但是,可以观察到
生成的块数
(
下面,您将找到两个用于池的增强信息函数和naive chunksize算法。下一章将需要这些函数的输出。
不要被你可能意想不到的表情弄糊涂了
现在,在我们看到
如前一章所示,对于更长的iterables(更多的Taskel),Pool的chunksize算法 将iterable分为四次 更多 块比朴素的方法。更小的块意味着更多的任务,更多的任务意味着更多 并行化开销(PO) ,这一成本必须与增加调度灵活性的好处进行权衡(召回) 由于相当明显的原因,Pool的基本chunksize算法无法权衡调度灵活性和 人事军官 对我们来说。IPC开销取决于操作系统、硬件和数据大小。算法不知道我们在什么硬件上运行代码,也不知道taskel需要多长时间才能完成。它是一种启发式方法,为用户提供基本功能 全部的 可能的情况。这意味着它无法针对任何特定场景进行优化。如前所述,, 人事军官 随着每个任务计算时间的增加(负相关),问题也越来越少。 当你回忆起 并行化目标 第2章中的一个要点是:
前面提到的 某物 ,池的chunksize算法 可以 努力改进是关键 最小化空闲工作进程 ,分别为 cpu核的利用 .
6.1模型为了在这里获得更深入的见解,我们需要一种并行计算的抽象形式,它将过于复杂的现实简化到可管理的复杂程度,同时在定义的边界内保持重要性。这种抽象称为抽象 模型 并行化模型(PM) 如果要收集数据,则生成与实际计算相同的工作映射元数据(时间戳)。模型生成的元数据允许在某些约束条件下预测并行计算的度量。
此处定义的模型中的两个子模型之一 颗粒物 是 分布模型(DM) . 这个 DM ,当不考虑除相应chunksize算法以外的其他因素时,考虑工作人员数量、输入可数(任务数)及其计算持续时间。这意味着任何形式的开销都是无效的 不 包括。 颗粒物 DM 用一个 ,代表各种形式的 . 这样的模型需要针对每个节点分别进行校准(硬件依赖性、操作系统依赖性)。一个表中表示了多少种形式的开销 嗯 是开着的,所以是多个 OMs 复杂程度各不相同。实现了哪一级别的准确度 嗯 需求由产品的总重量决定 对于具体的计算。较短的Taskel会导致更高的 人事军官 ,这反过来又需要更精确的 预测 . 这个 平行时间表 是并行计算的二维表示,其中x轴表示时间,y轴表示并行工作池。工人数量和总计算时间标志着矩形的延伸,在其中绘制较小的矩形。这些较小的矩形表示原子工作单元(taskel)。 在下面,您可以看到一个 附言 使用来自 DM 池的chunksize算法的 .
组成部分的名称见下图。
完完全全 包括 嗯 这个 空转份额 不仅限于尾部,还包括任务之间甚至任务之间的空间。
需要注意的是,计算出的效率 不要 给定并行化问题的总体计算。在此上下文中,工人利用率仅区分具有已启动但未完成任务的工人和没有此类“开放”任务的工人。也就是说,可能是空转 taskel的时间跨度为 注册的。 上述所有效率基本上都是通过计算除法商得到的 判定元件 和 体育课 伴随着忙碌的分享而来 在整个平行进度计划中占据较小的一部分,用于延长开销 颗粒物 这个答案将进一步讨论一个简单的计算方法 判定元件 对于密集场景。这足以比较不同的chunksize算法,因为。。。
6.3.1绝对分配效率(ADE):
对于 密集场景
如果没有 空转份额 忙共享 将 相同的 平行时间表 因此,我们得到了一个 艾德 百分之百。在我们的简化模型中,这是一个场景,其中所有可用流程都将在处理所有任务所需的整个时间内忙碌。换句话说,整个作业有效地并行化到100%。 但我为什么一直提到 体育课 像 完全的 体育课 在这里 为了理解这一点,我们必须考虑CulkSead(CS)的一个可能的情况,它确保了最大的调度灵活性(也可以是高地人的数量。巧合?)
同样地,仍然会有一名工人在工作,有39个Taskel,如下图所示。
当你比较上
平行时间表
对于
因为开销不包含在这个模型中。这两种块大小都会不同,因此x轴实际上不具有直接可比性。开销仍然会导致更长的总计算时间,如中所示 案例2 如下图所示。
6.3.2相对分配效率(RDE)这个 艾德 较好的 较好的 这里还是指一个较小的 空转份额
得到
判定元件
为可能的最大值调整的值
判定元件
,我们必须将
艾德
通过
我们得到了
下面是代码中的外观:
这里是如何定义的,本质上是一个关于动物尾巴的故事
平行时间表
.
RDE
受尾部包含的最大有效块大小的影响。(此尾部可以是x轴长度
低 RDE ...
请参阅本答案的第二部分 here . |
|
|
2
60
7.Naive vs.Pool的Chunksize算法
在详细讨论之前,请考虑下面两个GIFS。对于一系列不同的
如第章所示“
5.池的Chunksize算法
下图与第5章中的图相似,但显示的是节数而不是块数。对于池的全chunksize算法(
对于Pool的chunksize算法,在
“足够长”的时间
朴素的chunksize算法也会收敛到100%,但收敛速度较慢。会聚效应完全取决于这样一个事实,即在有两个截面的情况下,尾部的相对部分会收缩。只有一名工作人员的尾巴限制在x轴长度内
下面是两张热图,显示了 适用于最大长度为5000的所有iterable长度的值,适用于2到100的所有工人数量。 色标从0.5到1(50%-100%)。在左侧的热图中,您会发现naive算法有更多的黑暗区域(较低的RDE值)。相比之下,Pool右侧的chunksize算法绘制了一幅更加阳光明媚的画面。
左下角暗角与右上角亮角的对角线梯度再次显示出对工人数量的依赖性,即所谓的“长可伸缩性”。
使用Pool的chunksize算法a RDE 81.25%的值是上述规定的工人范围和可承受长度的最低值:
RDE 这是50.72%。在这种情况下,几乎一半的计算时间只有一个工人在运行!所以,小心,骄傲的主人 Knights Landing . ;)
8.现实检查在前几章中,我们考虑了纯数学分布问题的简化模型,从使多重处理成为一个棘手话题的基本细节中剥离出来。更好地了解分销模式(DM)的发展程度 为了有助于解释实际观察到的工作人员利用率,我们现在将看一看由 真实的 安装程序
下面的图都处理了一个简单的、cpu绑定的伪函数的并行执行,该函数使用各种参数调用,因此我们可以观察绘制的并行计划是如何随输入值而变化的。此函数中的“功”仅由范围对象上的迭代组成。这已经足够让核心保持忙碌,因为我们传入了大量数据。可选地,该函数需要一些额外的taskel
Pool的starmap方法也被修饰为只对starmap调用本身进行计时。此调用的“开始”和“结束”确定生成的并行计划x轴上的最小值和最大值。 我们将在一台具有以下规格的机器上观察四个辅助进程上40个Taskel的计算: 将改变的输入值是for循环中的迭代次数 (30k、30M、600M)和额外发送的数据大小(每个taskel、numpy-ndarray:0 MiB、50 MiB)。
下面显示的运行是精心挑选的,具有相同的块顺序,因此您可以更好地发现与分布模型中的并行计划相比的差异,但不要忘记工作人员获取任务的顺序是不确定的。 DM预测
第一次运行:30k次迭代和;每个任务0个MiB数据
我们在这里的第一次跑步非常短,Taskel非常“轻”。整体
此外,您还可以看到,并非所有员工都能同时完成任务。这是因为所有的工人都是通过一个共享的
turbo boost 此时worker-3/4的核心不再可用,因此他们以较低的时钟频率处理任务。 整个计算过程非常简单,以至于硬件或操作系统引入的混沌因素会使计算结果产生偏差 附言 DM -即使对于理论上合适的情景,预测也没有什么意义。 第二次运行:3000万次迭代和;每个任务0个MiB数据
将for循环中的迭代次数从30000次增加到3000万次,将产生一个真正的并行计划,该计划与由 DM DM 预测。 第三次运行:3000万次迭代和;每个任务50个MiB数据
保持30M的迭代,但每个taskel来回发送50个MiB会再次扭曲图片。在这里,排队效应是显而易见的。Worker-4需要比Worker-1等待第二个任务更长的时间。现在想象一下这个有70名工人的时间表! 如果taskel在计算上很轻,但可以提供大量数据作为有效负载,那么单个共享队列的瓶颈可能会阻止向池中添加更多工作线程的任何额外好处,即使它们由物理内核支持。在这种情况下,Worker-1可以完成其第一个任务,并在Worker-40完成其第一个任务之前等待新任务。
现在应该很明显,为什么计算时间在
第四次运行:6亿次迭代和;每个任务50个MiB数据
在这里,我们再次发送50个MiB,但将迭代次数从30M增加到600M,这使总计算时间从10秒增加到152秒。拟定的平行时间表 再一次
所讨论的乘法
正如这个答案所希望显示的那样,Pool的chunksize算法与naive方法相比,平均而言能带来更好的核心利用率,至少在平均情况下是这样,并且不考虑长开销。这里的naive算法的分布效率(DE)可以低至约51%,而Pool的chunksize算法的分布效率低至约81%。 判定元件 然而,它不像IPC那样包含并行化开销(PO)。第8章表明
判定元件
与天真的方法相比,
它并没有为每个输入星座提供最优taskel分布。
虽然一个简单的静态分块算法不能优化(包括开销)并行化效率(PE),但没有内在的原因说明它不能
总是
判定元件
如同
与Pool实现的“等大小分块”算法不同,“等大小分块”算法将提供
每一次都是100%
|
|
3
9
我认为你缺少的部分是,你天真的估计假设每个工作单元花费的时间相同,在这种情况下,你的策略是最好的。但是,如果某些作业比其他作业完成得更快,则某些内核可能会闲置,等待缓慢的作业完成。 因此,通过将块分成4倍多的块,如果一个块提前完成,那么该核心可以开始下一个块(而其他核心继续处理其较慢的块)。 我不知道他们为什么选择了因子4,但这将是一种在最小化map代码开销(需要尽可能大的块)和平衡不同时间段的块(需要尽可能小的块)之间的权衡。 |
|
|
Temperosa · 多处理。水塘map不能并行工作 8 年前 |
|
|
Alex Gao · 加速或矢量化熊猫应用函数-需要有条件地应用函数 8 年前 |
|
|
Teknophilia · 多处理提前退出 8 年前 |
|
xxCodexx · 在Python中从父函数启动进程 8 年前 |
|
|
Aenaon · 分组依据/应用熊猫和多处理 8 年前 |