我正在尝试比较Python中的顺序计算和并行计算。
这是基准功能。
def benchmking_f(n=0):
import time
items = range(int(10**(6+n)))
def f2(x):return x*x
start = time.time()
sum_squared = 0
for i in items:
sum_squared += f2(i)
return time.time() - start
此顺序计算
problem_size = 2
import time
start = time.time()
tlist = []
for i in range(5):
tlist.append(benchmking_f(problem_size))
print('for loop took {}s'.format(time.time() - start))
print('each iterate took')
print(tlist)
花了大约70来完成工作;每个迭代 [14.209498167037964、13.92169737815857、13.949078798294067、13.94432258605957、14.004642486572266]
这种并行方法
problem_size = 2
import itertools
import multiprocessing
start = time.time()
pool = multiprocessing.Pool(5)
tlist = list(pool.map(benchmking_f, itertools.repeat(problem_size, 5)))
print('pool.map took {}s'.format(time.time() - start))
print('each iterate took')
print(tlist)
大约花费42.45秒;每个迭代 [41.17476940155029、41.92032074928284、41.50966739654541、41.348535776138306、41.06284761428833]
整个计算中的一部分(在本例中为benchmking_f)大约耗时14s,并行耗时42.45s
那是为什么?
注意: 我没有问总时间。我问的时间是整个计算的一部分,它在for循环中进行一次迭代,并在一个进程/线程中并行进行。
1-iter benchmking_f
需要。
答案 0 :(得分:3)
您有多少个物理(非逻辑)核心?您正在尝试同时运行该函数的5个副本,该函数在运行时会占用一个核心的100%,并且除非您拥有至少5个物理核心,否则它们将互相竞争,互为争夺
我有4个物理核心,但也想将我的机器用于其他用途,因此将Pool(5)
减少为Pool(3)
。 然后每次迭代的时机大致相同。
假设您有一个任务需要T
秒内占用100%的CPU。如果要同时运行该任务的S
个副本,则总共需要T*S
cpu-seconds。如果您有C
个完全免费的物理核心可以投入使用,那么最多min(C, S)
个核心可以同时在聚合上工作,因此初步估算所需时间为:
T*S / min(C, S)
正如另一个答复所说,当您运行的进程比内核多时,操作系统会在整个持续时间内循环运行这些进程,以使它们全部花费相同的挂钟时间(在每个进程中一定数量的时间)除了等待操作系统让它再次运行一段时间之外,什么也没做。
我猜您有2个物理核心。以您的示例为例,T
约为14秒,而S
为5,因此,如果您有C=2
个内核可以解决
14*5 / min(2, 5) = 14*5/2 = 35
秒。您实际上看到的值接近41。部分原因是开销,但是您的计算机似乎同时也在执行其他工作,因此您的测试运行没有获得2个内核的100%。
答案 1 :(得分:1)
总时间减少:70秒vs 42秒。
您的计算机可能同时以循环方式处理5件事。发生线程开销(上下文加载等),每个线程花费的时间更长。但是,由于更长的线程并行运行,因此5个线程在42秒内完成。
对于顺序操作,您的计算机将同一事物处理5次。每个线程可以运行直到完成而不会中断(因此,没有开销)。然而,所有这些都需要70秒才能完成。