Python多处理并按顺序保存数据

时间:2016-06-08 20:25:51

标签: python performance python-multiprocessing

我逐行分析cvs文件数据。对于每一行,我将生成一个存储分析结果的字符串。

由于文件很大,我必须进行多处理。但是因为我必须按索引访问结果,所以我必须按顺序存储它们(到本地文件)。

我尝试和工作的一种方法是使用锁,但它仍然非常慢。如果我没有锁定它,它会快速运行,但数据会被搞乱。

我想要做的是将这些结果存储到全局列表中。当所有子进程完成后,我可以写入本地文件。 任何提示如何没有锁定以及如何加快它?

以下是我的多处理部分代码:

def worker(dat,fileName,l):
    l.acquire()
    target = open(fileName,"a")
    for values in dat:
        # recursively apply different start mean2, find best solution
        model = MixGaussian(values)
        bf = model.findBestFit()
        # find the value where it's equally probable belongs to two gaussians 
        m1 = bf[0]
        m2 = bf[1]
        d1 = bf[2]
        d2 = bf[3]

        # calculate x
        k = math.log((d1+0.001)/(d2+0.001))* d1 * d2
        a = d1 -d2 
        b = 2 * (m1*d2 - m2 * d1)
        c = m2 * m2 * d1 - m1* m1 * d2 - k 
        delta = -1 * math.sqrt(b*b - 4 * a * c)
        if a == 0:
            a += 0.01
        x = (-1 * b + delta) / (2 * a)
        bf.append(x)
        print bf

        target.write(",".join(str(ele) for ele in bf))
        target.write("\n")

    target.close()
    l.release()

if __name__ == "__main__":
    # read from line 8000 to 8999
    data = readFile("unc_expr.tsv",8000,9000)
    target = open("modelstest9.csv","w")
    target.write("mean_1,mean_2,deviantion_1,deviation_2,cross_value")
    target.write("\n")
    target.close()

    numPrcs = 16
    d = []
    for i in range(numPrcs-1):
        d.append(data[i*len(data)/numPrcs:(i+1) *len(data)/numPrcs])
    d.append(data[(numPrcs-1)*len(data)/numPrcs:])

    start_time = time.time()
    lock = Lock()
    print("start time: %s"%start_time)

    for i in range(numPrcs):    
        Process(target=worker,args=(d[i],"modelstest9.csv",lock)).start()

谢谢!

2 个答案:

答案 0 :(得分:2)

我建议使用multiprocessing.Pool并使用其imap方法来完成工作。拥有worker return值而不是直接编写它们,主进程执行所有I / O. imap保证您按照调度任务的顺序获得结果,并且只有主进程执行I / O,冲突是不可能的。

它也是一项改进,因为您可以将工作分成固定的块,而不是仔细划分工作以匹配您希望启动的进程数。默认情况下,multiprocessing.Pool会产生一些与您的CPU核心相等的工作人员(因此无需手动指定工作人员数量,风险太少,浪费核心或太多,浪费时间在上下文切换上)。 map / imap和公司将在N个工人之间无缝拆分X工作项,而无需确保工作项数等于工作项数。

答案 1 :(得分:1)

ThreadPoolExecuter非常适合与不同数据集并行运行相同的方法,以及重新组合每个线程的结果。

当结果从每个线程返回时,将它们放入类似[(index1, result1), (index2, result2),...]的列表中,当它们返回时,在所有线程完成后按索引对列表进行排序,然后将排序列表写入文件。 / p>

这里的问题是,这会将所有结果保存在内存中,但您应该能够这样做,因为您已经在每个进程中将它们全部保存在内存中。