受到教程多处理阶乘的启发,我尝试对一个微不足道的力计算模块进行多处理。 我主要担心的是 queue.get 功能没有按照与预期相同的顺序进行检索。例如,它不是给出 [5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5],而是基于不同的处理器给出混乱的输出。1) 如何根据进程调用顺序追加队列结果?我应该使用游泳池、地图、锁或任何类似的东西吗?2)如何避免内存同步/覆盖问题?
def mp_worker(istart, iend, x, out_q1, out_q2):
global_N = len(x)
outdict1 = []
outdict2 = []
k = 0
for i in range(istart,iend,1):
temp_FX = 0
temp_FY = 0
for j in range(global_N):
if i != j:
temp_FX = temp_FX + (x[j]-x[i])
temp_FY = temp_FY + (x[j]-x[i])
outdict1.append(temp_FX)
outdict2.append(temp_FY)
k = k + 1
out_q1.put(outdict1)
out_q2.put(outdict2)
def mp_factorizer( nprocs):
x = mem.x
FORCE = mem.FORCE
N = len(FORCE)
out_q1 = multiprocessing.Queue()
out_q2 = multiprocessing.Queue()
chunksize = int(math.ceil(N / float(nprocs)))
procs = []
for i in range(nprocs):
istart = chunksize * i
iend = chunksize * (i + 1)
p = multiprocessing.Process(
target=mp_worker,
args=(istart, iend, x, out_q1, out_q2))
procs.append(p)
p.start()
# Collect all results into a single result dict. We know how many dicts
# with results to expect.
resultdict1 = []
resultdict2 = []
for i in range(nprocs):
resultdict1 = resultdict1 + out_q1.get()
resultdict2 = resultdict2 + out_q2.get()
# Wait for all worker processes to finish
for p in procs:
p.join()
return resultdict1
项按工作进程完成的任何顺序添加到队列中。 如果你想强制下订单,你必须...强制命令;-)
Process
对此不利。 它们的执行本质上是无序的,并且顺序很可能会从一次运行更改为下一次运行。
在这种情况下,可能是最简单的:首先,完全抛弃队列。 像这样结束你的mp_worker()
:
return outdict1, outdict2
然后使用Pool
。 有几种方法可以使用一个。 最像你已经在做的事情看起来像:
pool = multiprocessing.Pool(nprocs)
for i in range(nprocs):
istart = chunksize * i
iend = chunksize * (i + 1)
p = pool.apply_async(mp_worker, (istart, iend, x))
procs.append(p)
resultdict1 = []
resultdict2 = []
for p in procs:
t1, t2 = p.get()
resultdict1.extend(t1)
resultdict2.extend(t2)
pool.close()
pool.join()
现在,结果的获取顺序与任务传递的顺序相同;顺序是强制的。
注意:从+
切换到.extend()
在逻辑上不是必需的,但会将二次时间(循环迭代次数)操作减少为摊销线性时间操作。 这与多处理无关。somelist = somelist + anotherlist
总是更好地编码为somelist.extend(anotherlist)
.
关于操作系统
以下是关于为什么"它有效"在Windows上而不是Linux上的猜测:从历史上看,Linux上的进程创建比Windows便宜(Windows在加速其线程方面投入了更多的精力)。 这使得进程更有可能以与启动相同的顺序在Windows上结束,而这些进程正在执行大约相同的工作量。 但他们当然可以在Windows上"无序"完成。 太。
无论如何,Python在这方面没有任何发言权:如果你需要一个特定的顺序,你必须强制这个顺序。