我知道使用多处理模块时会有开销,但这似乎是一个很大的数额,IPC的水平应该是我可以收集的相当低。
假设我在1-1000之间生成一个大的随机数列表,并且想要获得仅有素数的列表。此代码仅用于测试CPU密集型任务的多处理。忽略素性测试的整体效率低下。
大部分代码可能如下所示:
from random import SystemRandom
from math import sqrt
from timeit import default_timer as time
from multiprocessing import Pool, Process, Manager, cpu_count
rdev = SystemRandom()
NUM_CNT = 0x5000
nums = [rdev.randint(0, 1000) for _ in range(NUM_CNT)]
primes = []
def chunk(l, n):
i = int(len(l)/float(n))
for j in range(0, n-1):
yield l[j*i:j*i+i]
yield l[n*i-i:]
def is_prime(n):
if n <= 2: return True
if not n % 2: return False
for i in range(3, int(sqrt(n)) + 1, 2):
if n % i == 0:
return False
return True
在我看来,我应该能够在多个进程中分割它。我有8个逻辑核心,所以我应该能够使用cpu_count()
作为进程数。
串行:
def serial():
global primes
primes = []
for num in nums:
if is_prime(num):
primes.append(num) # primes now contain all the values
以下尺寸的NUM_CNT对应于速度:
这是我选择进行多处理的方式。它使用chunk()
函数将nums
拆分为cpu_count()
(大致相等)部分。它将每个块传递给一个新进程,该进程遍历它们,然后将其分配给共享dict变量的条目。当我将值分配给共享变量时,应该真正发生IPC。为什么会发生呢?
def loop(ret, id, numbers):
l_primes = []
for num in numbers:
if is_prime(num):
l_primes.append(num)
ret[id] = l_primes
def parallel():
man = Manager()
ret = man.dict()
num_procs = cpu_count()
procs = []
for i, l in enumerate(chunk(nums, num_procs)):
p = Process(target=loop, args=(ret, i, l))
p.daemon = True
p.start()
procs.append(p)
[proc.join() for proc in procs]
return sum(ret.values(), [])
同样,我预计会有一些开销,但时间似乎比串行版本快得多。
是什么导致它这样做?是IPC吗?初始设置让我期待一些开销,但这只是一个疯狂的数量。
修改
以下是我如何计算函数的执行时间:
if __name__ == '__main__':
print(hex(NUM_CNT))
for func in (serial, parallel):
t1 = time()
vals = func()
t2 = time()
if vals is None: # serial has no return value
print(len(primes))
else: # but parallel does
print(len(vals))
print("Took {:.05f} sec.".format(t2 - t1))
每次都使用相同的数字列表。
示例输出:
0x5000
3442
Took 0.01828 sec.
3442
Took 0.93016 sec.
答案 0 :(得分:0)
嗯。你如何衡量时间?在我的计算机上,并行版本比串行版本快得多。
我使用time.time()
进行测试:如果我们假设tt
是time.time()
的别名。
serial()
t2 = int(round(tt() * 1000))
print(t2 - t1)
parallel()
t3 = int(round(tt() * 1000))
print(t3-t2)
我得到了0x500000
作为输入:
我相信你的错误是由并行中包含数字生成过程引起的,而不是在序列中包含。
在我的计算机上,随机数的生成需要45秒(这是一个非常缓慢的过程)。因此,它可以解释您的两个值之间的差异,因为我不认为我的计算机使用了非常不同的架构。