pathos:并行处理选项 - 有人可以解释其中的差异吗?
Posted
技术标签:
【中文标题】pathos:并行处理选项 - 有人可以解释其中的差异吗?【英文标题】:pathos: parallel processing options - Could someone explain the differences? 【发布时间】:2018-08-06 00:55:17 【问题描述】:我正在尝试在 python 下(在 ubuntu 上)运行并行进程。
我开始使用多处理,它适用于简单的示例。 然后出现了泡菜错误,所以我切换到悲情。我对不同的选项有点困惑,因此编写了一个非常简单的基准测试代码。
import multiprocessing as mp
from pathos.multiprocessing import Pool as Pool1
from pathos.pools import ParallelPool as Pool2
from pathos.parallel import ParallelPool as Pool3
import time
def square(x):
# calculate the square of the value of x
return x*x
if __name__ == '__main__':
dataset = range(0,10000)
start_time = time.time()
for d in dataset:
square(d)
print('test with no cores: %s seconds' %(time.time() - start_time))
nCores = 3
print('number of cores used: %s' %(nCores))
start_time = time.time()
p = mp.Pool(nCores)
p.map(square, dataset)
# Close
p.close()
p.join()
print('test with multiprocessing: %s seconds' %(time.time() - start_time))
start_time = time.time()
p = Pool1(nCores)
p.map(square, dataset)
# Close
p.close()
p.join()
print('test with pathos multiprocessing: %s seconds' %(time.time() - start_time))
start_time = time.time()
p = Pool2(nCores)
p.map(square, dataset)
# Close
p.close()
p.join()
print('test with pathos pools: %s seconds' %(time.time() - start_time))
start_time = time.time()
p = Pool3()
p.ncpus = nCores
p.map(square, dataset)
# Close
p.close()
p.join()
print('test with pathos parallel: %s seconds' %(time.time() - start_time))
我知道了
- 0.001s 使用纯序列码,没有并行,
- 0.100 秒,multiprocessing
选项,
- 0.100 秒 pathos.multiprocessing
,
- 4.470 秒 pathos.pools
,
- AssertionError
错误与 pathos.parallel
我从http://trac.mystic.cacr.caltech.edu/project/pathos/browser/pathos/examples.html复制了如何使用这些不同的选项
对于这样一个简单的示例,我知道并行处理比普通的串行代码要长。我不明白的是pathos的相对表现。
我查看了讨论,但不明白为什么 pathos.pools
会这么长,以及为什么会出现错误(不确定最后一个选项的性能如何)。
我还尝试了一个简单的平方函数,为此即使pathos.multiprocessing
也比multiprocessing
长得多
有人能解释一下这些不同选项之间的区别吗?
另外,我在远程计算机上运行pathos.multiprocessing
选项,运行centOS,性能比multiprocessing
差大约10 倍。
根据租用计算机的公司,它应该像家用计算机一样工作。我知道如果没有关于机器的更多详细信息,可能很难提供信息,但如果您对信息的来源有任何想法,那将有所帮助。
【问题讨论】:
原始 URL 似乎不可公开访问(404 Not Found / Code: NoSuchKey)。有关实现细节,可以查看源代码或询问 Mike McKearns(在 *** 上也很活跃)。 @user3666197 - 我们收到了关于您在编辑其他帖子时使用怪异格式的投诉(使用不恰当的粗体字、[SERIAL] 而非序列号等)。我在这里删除了该格式。请不要将自己的非标准风格强加在此处的其他帖子上。 @BradLarson 是的,您删除了您决定删除的任何内容。 你能帮忙消除歧义吗 - 你认为什么格式可以合理地在 (A) 纯文本与单词“parallel”(用于常见的,通常与专业无关的演讲)和 (B) 一个计算机科学术语 [PARALLEL],它确实具有唯一且非常特殊的含义,除了这个非常精确的 C/ 之外不允许任何其他含义来自系统理论的 S-context 用于一种独特的进程调度类型?我为此目的添加了交叉引用(如果你注意到的话)。 @user3666197 - 我认为在各种情况下并行和串行的含义很清楚。我认为没有必要单方面将格式应用于其他人不使用的帖子。所有这一切都会进一步分散人们对内容的注意力。在自己采取行动之前,也许您应该通过Meta 询问社区他们是否支持它。如果他们这样做,我很乐意让它留下来。然而,目前人们对你这样做很生气,并向版主投诉。 @BradLarson 如果您的观察确实在我目前所见的现实中得到满足,我将成为第一个快乐的人。许多文本实例包含“并行”一词,O/P 谈论“公正”-[CONCURRENT] 流程调度和如果两个人使用相同的词来解决主要误解,Meta 永远不会带来任何代数投票的补救。不同的东西。抱歉,这在过去十年没有奏效,所以教育落后于现实。你提到的人生气是认真的。然而,惩罚的想法从来都不是改善它的方法,正如现实所表明的那样 【参考方案1】:我是pathos
作者。对困惑感到抱歉。您正在处理新旧编程接口的混合。
“新”(建议)接口是使用pathos.pools
。旧界面链接到相同的对象,因此实际上有两种方法可以访问相同的东西。
multiprocess.Pool
是multiprocessing.Pool
的一个分支,唯一的区别是multiprocessing
使用pickle
和multiprocess
使用dill
。所以,我希望在最简单的情况下速度是一样的。
上面的游泳池也可以在pathos.pools._ProcessPool
找到。 pathos
为几种类型的池提供了一个小型包装器,具有不同的后端,提供了扩展的功能。 pathos
-wrapped 池是 pathos.pools.ProcessPool
(旧接口在 pathos.multiprocessing.Pool
提供它)。
首选接口是pathos.pools.ProcessPool
。
还有ParallelPool
,它使用不同的后端——它使用ppft
而不是multiprocess
。 ppft
是“并行 python”,它通过 subprocess
生成 python 进程并传递源代码(使用 dill.source
而不是序列化对象)——它用于分布式计算,或者当通过源代码传递时是更好的选择。
因此,pathos.pools.ParallelPool
是首选接口,而 pathos.parallel.ParallelPool
(以及 pathos
中的一些其他类似引用)由于遗留原因而存在 - 但它们在下面是同一个对象。
总结:
>>> import multiprocessing as mp
>>> mp.Pool()
<multiprocessing.pool.Pool object at 0x10fa6b6d0>
>>> import multiprocess as mp
>>> mp.Pool()
<multiprocess.pool.Pool object at 0x11000c910>
>>> import pathos as pa
>>> pa.pools._ProcessPool()
<multiprocess.pool.Pool object at 0x11008b0d0>
>>> pa.multiprocessing.Pool()
<multiprocess.pool.Pool object at 0x11008bb10>
>>> pa.pools.ProcessPool()
<pool ProcessPool(ncpus=4)>
>>> pa.pools.ParallelPool()
<pool ParallelPool(ncpus=*, servers=None)>
您可以看到ParallelPool
具有servers
...因此适用于分布式计算。
剩下的唯一问题是为什么AssertionError
?那是因为pathos
添加的包装器保留了一个可供重用的池对象。因此,当您第二次调用ParallelPool
时,您调用的是一个封闭池。您需要restart
池才能再次使用它。
>>> f = lambda x:x
>>> p = pa.pools.ParallelPool()
>>> p.map(f, [1,2,3])
[1, 2, 3]
>>> p.close()
>>> p.join()
>>> p.restart() # throws AssertionError w/o this
>>> p.map(f, [1,2,3])
[1, 2, 3]
>>> p.close()
>>> p.join()
>>> p.clear() # destroy the saved pool
ProcessPool
与ParallelPool
具有相同的接口,用于重启和清除已保存的实例。
【讨论】:
我们可以有多个使用 pathos 的服务器吗?有什么例子吗?pathos.ParallelPool
建立在ppft
之上,使用servers
的方式与ppft
相同。签入pathos/examples
文件夹,例如:github.com/uqfoundation/pathos/blob/master/examples/…。【参考方案2】:
有人能解释一下不同之处吗?
让我们从一些共同点开始。
Python 解释器使用标准的 GIL 步进代码执行。这意味着,所有基于 线程 的池仍然会等待所有代码执行路径的 GIL 步进排序,因此任何这样的构造尝试都不会享受 好处“理论上预期”。
Python 解释器可以使用其他基于进程的实例来加载多个进程,每个进程都有自己的 GIL 锁,形成多个并发代码执行路径的池。
解决了这个主要的歧义后,接下来开始出现与性能相关的问题。最负责任的方法是基准测试、基准测试、基准测试。这里也不例外。
要花这么多时间在这里(哪里)?
主要 ( constant ) 部分是流程实例化的主要 [TIME]
域成本。在这里,python 解释器的完整副本,包括所有变量、所有内存映射,实际上是调用 python 解释器的完整状态完整副本,必须首先创建并放置到操作系统进程调度程序表中,然后再进一步(工作的有用部分)可以在“内部”计算这种成功实例化的子流程。如果您的有效负载函数立即从那里返回,并创建了一个 x*x
,那么您的代码似乎已经为一些 CPU 指令消耗了所有燃料,而您所花费的远远超过了所收到的回报。 成本经济对您不利,因为所有进程实例化加上进程终止的成本远高于几个 CPU-CLOCK 滴答声。
这实际上需要多长时间?
您可以在建议的 Test-Case-A
中对此进行基准测试(如建议的 here。如果Stopwatch()
-ed [us]
决定,你开始更多地依赖事实,而不是任何形式的崇拜者或营销类型的建议。这很公平,不是吗?)。
Test-Case-A
对流程实例化成本进行基准测试 [MEASURED]。下一步是什么?
下一个最危险的(variable in size)部分主要是[SPACE]
-域成本,但也有[TIME]
-域影响,如果@ 987654333@-分配成本开始超出小规模规模。
这种附加开销成本与将“大型”参数从“主”-python 解释器传递到每个(分布式)子流程实例的任何需要相关。
这需要多长时间?
再次,基准,基准,基准。应对此进行基准测试(如建议的 here,如果扩展了建议的 Test-Case-C
并用 aNeverConsumedPAR
参数替换为一些确实“胖”数据块,无论是 numpy.ndarray()
还是其他类型,都会占用大量内存。)
通过这种方式,真正的硬件相关 + O/S 相关 + python 相关的数据流成本开始变得可见并在**[us]**
中的额外开销成本这样的基准中衡量。这对老黑客来说并不是什么新鲜事,然而,那些从未遇到过 HDD 磁盘写入时间会增长并阻塞其他处理几秒钟或几分钟的人几乎不会相信,如果不接触的话自己对数据流的实际成本进行基准测试。因此,请不要犹豫将基准 Test-Case-C
扩展到确实较大的内存占用空间以闻烟味......
最后但并非最不重要的一点是,重新制定的阿姆达尔定律会告诉我们......
考虑到并行化某些计算的尝试在计算部分和所有开销部分都得到了很好的理解,图片开始变得完整:
overhead-strict and resources-aware Amdahl's Law re-formulation 显示:
1
S = ______________________________________________ ; where s,
/ \ ( 1 - s ),
| ( 1 - s ) | pSO,
s + pSO + max| _________ , atomicP | + pTO pTO,
| N | N
\ / have been defined in
just an Overhead-strict Law
and
atomicP := is a further indivisible duration of an atomic-process-block
由此产生的加速S
将总是遭受高昂的间接成本pSO + pTO
与任何高的时候一样由于 atomicP
的值足够高,N
将不允许提供进一步帮助。
在所有这些情况下,最终的加速提升 S
可能很容易落入 << 1.0
,是的,远低于纯 -[SERIAL]
strong> 代码执行路径计划(同样,对 pSO
和 pTO
的实际成本进行了基准测试(其中 Test-Case-A + Test-Case -C ( extended ) 被示意性地提出) 有机会得出所需的最小合理计算有效负载,以保持在加速的神秘水平之上>= 1.0
【讨论】:
感谢@user3666197 提供一般信息和基准测试提示。我的问题更多是关于multiprocessing
和 pathos
函数之间的性能差异。
看来我不明白你在这个评论中的意思。答案中没有一般信息,而是说明如何衡量上述性能差异的组成部分。因此,如果您在您的平台上对您的代码运行建议的 A/B 测试,定量结果将向您解释这种性能差异的规模和来源。知道为什么总是比被动地观察它碰巧这么慢(但不知道为什么)更重要。祝parallel-processing 使用正确的技术好运
谢谢,我会这样做来为我的代码选择最佳流程。其目的是试图理解 pathos.multiprocessing
、pathos.pools
和 pathos.parallel
背后的意图。这些不同的选项必须在设计时考虑到不同的用例?我找不到任何相关信息。
基准测试将为您提供答案。设置 + 终止间接费用基准测试用例会告诉您何时(不)使用它们中的每一个。类似地,受 CPU 限制的有效负载基准 Test-Case-D + 一些繁重的磁盘/网络活动基于 IO 限制的有效负载的 Test-Case-X 将揭开每个测试台设置的实际工作负载/性能环境的神秘面纱,这就是您所需要的想得到,对吧?所以,继续测试,你就会触及真相——没有营销,没有教条的口号,没有歪曲的“最佳实践”,关于事情如何运作的赤裸裸的事实 + 你在做好这件事上学到了很多东西。以上是关于pathos:并行处理选项 - 有人可以解释其中的差异吗?的主要内容,如果未能解决你的问题,请参考以下文章
使用 pathos ProcessingPool 的地图时如何设置块大小?