我正在尝试比较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(连续大约需要 14 秒,并行需要 42.45 秒
为什么?
注意:我不是在问总时间。我问的是整个计算的一部分,它承担一个迭代的 for 循环和一个并行的进程/线程。
1-iterbenchmking_f
需要。
你有多少个物理(非逻辑(内核? 您尝试同时运行该函数的 5 个副本,只要函数运行,它就会占用一个内核的 100%,除非您至少有 5 个物理内核,否则它们将在周期内相互争斗。
我有 4 个物理内核,但也想将我的机器用于其他事情,因此减少了Pool(3)
Pool(5)
.然后,无论哪种方式,每次迭代的时间都大致相同。
信封背面
假设您有一个任务,该任务将 100% 的 CPU 固定T
秒。 如果要同时运行该任务的S
个副本,则总共需要T*S
个 CPU 秒。 如果你有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的东西。 开销占其中的一部分,但似乎您的机器也可能同时在执行其他工作,因此您的测试运行没有得到 100% 的 2 个内核。
总时间减少:70 秒与 42 秒。
您的计算机正在同时处理 5 件事,可能是以循环方式。发生线程开销(上下文负载等(,每个线程花费的时间更长。但是,由于较长的线程是并行运行的,因此 5 个线程在 42 秒内完成。
对于顺序,您的计算机正在处理相同的内容 5 次。每个线程都可以运行,直到它完成而不会中断(因此,没有开销(。然而,所有这些都需要 70 秒才能完成。