我逐行分析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()
谢谢!
答案 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>
这里的问题是,这会将所有结果保存在内存中,但您应该能够这样做,因为您已经在每个进程中将它们全部保存在内存中。