【问题标题】:Nested loops output to dict in parallel嵌套循环并行输出到 dict
【发布时间】:2017-07-07 09:14:45
【问题描述】:

我有两组数据:

aDict = {'barcode1': [('barcode1', 184), ('barcode1_mut', 2)], 'barcode2': [('barcode2', 138)], 'barcode3': [('barcode3', 375)]}
bList = [(('barcode1', 'mut1'), 184), (('barcode1_mut', 'mut2'), 2), (('barcode2', 'mut3'), 136), (('barcode2', 'mut4'), 1), (('barcode2', 'mut5'), 1), (('barcode3', 'mut6'), 373), (('barcode3', 'mut7'), 2)]

我正在匹配字典 aDict 中的每个键与列表 bList 中的条形码和结果:

>>>print(result)
{'barcode1': {'barcode1': [('mut1', 184)], 'barcode1_mut': [('mut2', 2)]},
'barcode2': {'barcode2': [('mut3', 136), ('mut4', 1), ('mut5', 1)]},
'barcode3': {'barcode3': [('mut6', 373), ('mut7', 2)]}}

但这对我来说太慢了。我尝试将代码与处理行数的信息输出并行。但在我的实现中,每一行都是由所有工作人员同时处理的。

现在,我的实现如下:

from collections import defaultdict
import multiprocessing as mp

def f(uniqueBarcode):
    mutBarcodeList = [x[0] for x in aDict[uniqueBarcode]]
    a = filter(lambda x: x[0][0] in mutBarcodeList, bList.items())
    d = defaultdict(tuple)
    b = [(x[0][0], (x[0][1], x[1])) for x in a]
    for tup in b: d[tup[0]] += (tup[1],)
    result = {i[0]:[y for y in i[1]] for i in d.items()}
    return result

seqDict={}

if __name__=='__main__':
    cpus = mp.cpu_count()
    pool = mp.Pool(cpus)
    for barcode in aDict.keys():
        seqDict[barcode] = pool.map(f, [barcode])
        if len(seqDict) % 100 == 0:
            print("Processed {} barcodes".format(len(seqDict)))
    pool.close()
    pool.join()

输出:

Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
...

而dict seqDict是空的,但一定不能这样——第一行是第一个进程处理的,第二行是第二个……第八个是第八个进程,第九行又是第一个进程等等。

如何正确并行?

Upd0:我已将 Flomp 的代码改编为我自己

res={}
for key in aDict:
    if len(aDict[key]) == 1:
        res[key] = {key:[(a[1],b) for a,b in bList if a[0] == key]}
    elif len(aDict[key]) > 1:
        res[key] = {x[0]:[(a[1],b) for a,b in bList if a[0] == x[0]] for x in aDict[key]}

但它的工作时间很长

【问题讨论】:

标签: python multiprocessing pool concurrent.futures


【解决方案1】:

我在您的代码中看到了很多 for 循环。这会减慢您的程序。下面是一些运行时更好的代码:

bcDict = {'TTCTCTTACCGGGTAC':1,'ACCTCTCGAGAATTCA':2,'TGCAGTTCTGTGCATC':3}

bcMutCount = [(('TTCTCTTACCGGGTAC', 'ATTCAACA'), 184), 
(('ACCTCTCGAGAATTCA', 'CATCCCAC'), 136), 
(('ACCTCTCGAGAATTCA', 'CATGCCAC'), 1),
(('ACCTCTCGAGAATTCA', 'CATCCCCC'), 1),
(('TGCAGTTCTGTGCATC', 'TCTACATT'), 373),
(('TGCAGTTCTGTGCATC', 'ACTGCGCA'), 2)]


for key in bcDict:
  print({key:[(a[1],b) for a,b in bcMutCount if a[0] == key]})

输出:

{'TTCTCTTACCGGGTAC': [('ATTCAACA', 184)]}
{'ACCTCTCGAGAATTCA': [('CATCCCAC', 136), ('CATGCCAC', 1), ('CATCCCCC', 1)]}
{'TGCAGTTCTGTGCATC': [('TCTACATT', 373), ('ACTGCGCA', 2)]}

如果这不是您想要的,请纠正我。上面的代码应该在 O(m*n) 中运行,其中 m 是 bcDict 中的键数,n 是 bcMutCount 的长度。 这运行速度够快吗?

【讨论】:

  • 好的,没问题。我正在将帖子编辑到最低限度
  • 感谢您的回复,但很抱歉,我没有完全代表 bcDict 变量。在这个字典中,一个键映射到一个元组列表,其中可以有多个。现在我编辑了我的问题。关于速度:现在我在 bcDict 中有 ~380 000 个键,在 bcMutCount 中有 ~10 000 000 个项目 :) 而我作为空气需要并行化。早期我使用的是 multiprocessing.pool.map(function, bcDict.keys()),但这并没有导致进程加速。我有两种并行计算的实现,但它们运行缓慢。如有必要,我可以将它们添加到我的问题中。
【解决方案2】:

首先:将bList转成dict。

bDict = {
('barcode1', 'mut1'): 184, 
('barcode1_mut', 'mut2'): 2, 
('barcode2', 'mut3'): 136, 
('barcode2', 'mut4'): 1, 
('barcode2', 'mut5'): 1, 
('barcode3', 'mut6'): 373, 
('barcode3', 'mut7'): 2}

第二:将相同条码的值组合起来。

mDict = {}
for x, y in bDict.items():
    if mDict.get(x[0]) == None:
        mDict[x[0]] = [(x[1], y)]
    else:
        mDict[x[0]].append((x[1], y))
>>>print(mDict)
{'barcode1': [('mut1', 184)],
'barcode1_mut': [('mut2', 2)],
'barcode2': [('mut3', 136), ('mut4', 1), ('mut5', 1)],
'barcode3': [('mut6', 373), ('mut7', 2)]}

第三:将结果分配给唯一的条形码。

seqDict = {x: {y[0]: mDict[y[0]] for y in aDict[x]} for x in aDict.keys()}

【讨论】:

    猜你喜欢
    • 2015-03-10
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    相关资源
    最近更新 更多