在Python中同步多处理问题,双循环

时间:2017-04-12 21:47:31

标签: python parallel-processing multiprocessing python-multithreading

受到教程multiprocessing factorial的启发,我试图对一个简单的力计算模块进行多处理。 我主要担心的是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

1 个答案:

答案 0 :(得分:1)

项目以工作进程完成的任何顺序添加到队列中。如果你想强制订单,你必须......强制订单; - )

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在任何一个方面都没有发言权:如果您需要特定订单,则必须强制执行该订单。