计算数字平方并存储结果的简单程序:
import time
from joblib import Parallel, delayed
import multiprocessing
array1 = [ 0 for i in range(100000) ]
def myfun(i):
return i**2
#### Simple loop ####
start_time = time.time()
for i in range(100000):
array1[i]=i**2
print( "Time for simple loop --- %s seconds ---" % ( time.time()
- start_time
)
)
#### Parallelized loop ####
start_time = time.time()
results = Parallel( n_jobs = -1,
verbose = 0,
backend = "threading"
)(
map( delayed( myfun ),
range( 100000 )
)
)
print( "Time for parallelized method --- %s seconds ---" % ( time.time()
- start_time
)
)
#### Output ####
# >>> ( executing file "Test_vr20.py" )
# Time for simple loop --- 0.015599966049194336 seconds ---
# Time for parallelized method --- 7.763299942016602 seconds ---
这两个选项的数组处理有何区别?我的实际程序会有更复杂的东西,但这是我需要尽可能简单地并行化的计算,但不是这样的结果。
System Model: HP ProBook 640 G2, Windows 7,
IDLE for Python System Type: x64-based PC Processor:
Intel(R) Core(TM) i5-6300U CPU @ 2.40GHz,
2401 MHz,
2 Core(s),
4 Logical Processor(s)
答案 0 :(得分:4)
我爱蟒蛇
我祈祷教育工作者更好地解释工具的成本,否则我们会迷失在这些希望获得的 [PARALLEL]
- 计划中。
否。 0 :通过大量简化,python有意使用 GIL 来 [SERIAL]
- 访问变量和从而避免了[CONCURRENT]
修改带来的任何潜在碰撞 - 在额外的时间内支付GIL阶梯式舞蹈的附加费用
不。 1 :[PARALLEL]
- 代码执行比"只是" - [CONCURRENT]
(read more)更难
不。 2 :[SERIAL]
- 如果尝试将工作拆分为[CONCURRENT]
,则流程必须支付额外费用 - 工人
否。 3 :如果进程进行员工间通信,则每次数据交换需要支付巨额额外费用
不。 4 :如果硬件的[CONCURRENT]
进程资源很少,则结果会进一步恶化
效率是更好地使用硅,而不是推动语法构造器进入领域,它们是合法的,但它们的性能对被测实验的端到端速度有不利影响:
您支付 8 ~ 11 [ms]
只是为了反复汇编空 array1
>>> from zmq import Stopwatch
>>> aClk = Stopwatch()
>>> aClk.start();array1 = [ 0 for i in xrange( 100000 ) ];aClk.stop()
9751L
10146L
10625L
9942L
10346L
9359L
10473L
9171L
8328L
(Stopwatch().stop()
方法从[us]
产生 .start()
)
而内存效率,可矢量化,无GIL方法可以做到相同大约+ 230x~ + 450x更快:
>>> import numpy as np
>>>
>>> aClk.start();arrayNP = np.zeros( 100000 );aClk.stop()
15L
22L
21L
23L
19L
22L
>>> aClk.start();arrayNP = np.zeros( 100000, dtype = np.int );aClk.stop()
43L
47L
42L
44L
47L
>>> def test_SERIAL_python( nLOOPs = 100000 ):
... aClk.start()
... for i in xrange( nLOOPs ): # py3 range() ~ xrange() in py27
... array1[i] = i**2 # your loop-code
... _ = aClk.stop()
... return _
虽然天真的 [SERIAL]
-iterative实施有效,但您需要支付巨额费用才能选择 ~ 70 [ms]
获取100000-D矢量:
>>> test_SERIAL_python( nLOOPs = 100000 )
70318L
69211L
77825L
70943L
74834L
73079L
>>> aClk.start();arrayNP[:] = arrayNP[:]**2;aClk.stop()
189L
171L
173L
187L
183L
188L
193L
并且另一个小故障,a.k.a。一个地方运作方式:
>>> aClk.start();arrayNP[:] *=arrayNP[:];aClk.stop()
138L
139L
136L
137L
136L
136L
137L
表现艺术并非遵循以下有关并行化 - ( at-any-cost )的营销声明,但在使用基于技术诀窍的方法,为可实现的最大加速成本支付最低成本。
对于&#34;小&#34; - 问题,分发&#34;瘦&#34; -work-packages的典型成本确实难以被任何可能实现的加速所覆盖,因此&#34;问题 - 大小&#34;实际上限制了一种方法的选择,可以达到正增益(这里经常报告加速度为0.9或甚至<&lt; 1.0),在StackOverflow上,您不需要感到丢失或单独使用惊讶)。
处理器编号计数
核心数量
但缓存大小+ NUMA不规则的数量不止于此
智能,矢量化,HPC固化,无GIL的库很重要( numpy
等等 - 非常感谢Travis OLIPHANT&amp; al ...给他的团队致敬。 ..)
As an overhead-strict Amdahl Law (re-)-formulation explains,为什么甚至很多 - N
- CPU 并行化代码执行可能(实际上经常)受到加速&LT;&LT; 1.0 强>
Amdahl法律加速 S
的严格制定包括付费[PAR]-
设置+ [PAR]-
终止开销的成本,的明确地强>:
1
S = __________________________; where s, ( 1 - s ), N were defined above
( 1 - s ) pSO:= [PAR]-Setup-Overhead add-on
s + pSO + _________ + pTO pTO:= [PAR]-Terminate-Overhead add-on
N
(这些性能限制的an interactive animated tool for 2D visualising effects被引用here)
答案 1 :(得分:3)
来自threading
的{{3}}:
如果你知道你正在调用的函数是基于编译的 发布Python全局解释器锁(GIL)的扩展 在大多数计算过程中......
问题在于,在这种情况下,你不知道。 Python本身只允许一个线程一次运行(python解释器每次执行python操作时都会锁定GIL。)
threading
仅在myfun()
大部分时间花在已编译的Python扩展程序上且该扩展程序发布GIL 时才有用。
Parallel
代码是如此令人尴尬地缓慢,因为你正在做大量的工作来创建多个线程 - 然后你只能一次执行一个线程。
如果使用multiprocessing
后端,则必须将输入数据复制到四个或八个进程(每个核心一个)中的每个进程中,在每个进程中执行处理,然后将输出数据复制回来。复制速度会很慢,但如果处理比计算正方形稍微复杂一些,那么它可能是值得的。测量并查看。