【问题标题】:Parallelising Python code并行化 Python 代码
【发布时间】:2015-08-19 08:54:43
【问题描述】:

我编写了一个函数,它返回 Pandas 数据帧(样本作为行,描述符作为列)并将输入作为肽列表(生物序列作为字符串数据)。 "my_function(pep_list)" 将 pep_list 作为参数并返回数据帧。它从pep_list迭代每个肽序列并计算描述符并将所有数据组合为pandas数据框并返回df:

pep_list = [DAAAAEF,DAAAREF,DAAANEF,DAAADEF,DAAACEF,DAAAEEF,DAAAQEF,DAAAGEF,DAAAHEF,DAAAIEF,DAAALEF,DAAAKEF]

示例:

我想用下面给定的算法并行化这段代码:

1. get the number of processor available as .
    n = multiprocessing.cpu_count()

2. split the pep_list  as 
     sub_list_of_pep_list = pep_list/n 

     sub_list_of_pep_list = [[DAAAAEF,DAAAREF,DAAANEF],[DAAADEF,DAAACEF,DAAAEEF],[DAAAQEF,DAAAGEF,DAAAHEF],[DAAAIEF,DAAALEF,DAAAKEF]]

4. run "my_function()" for each core as (example if 4 cores )

     df0 = my_function(sub_list_of_pep_list[0])
     df1 = my_function(sub_list_of_pep_list[1])
     df2 = my_functonn(sub_list_of_pep_list[2])
     df3 = my_functonn(sub_list_of_pep_list[4])

5. join all df = concat[df0,df1,df2,df3] 

6. returns df with nX speed. 

请向我推荐最合适的库来实现此方法。

感谢和问候。

Updated 

通过一些阅读,我能够写下符合我期望的代码,例如 1. 没有并行化,10 个肽序列大约需要 10 秒 2. 两个过程需要约 6 秒 12 个肽 3. 四个过程需要约 4 秒处理 12 个肽

from multiprocessing import Process

def func1():
    structure_gen(pep_seq = ["DAAAAEF","DAAAREF","DAAANEF"])

def func2():
    structure_gen(pep_seq = ["DAAAQEF","DAAAGEF","DAAAHEF"])


def func3():
    structure_gen(pep_seq = ["DAAADEF","DAAALEF"])

def func4():
    structure_gen(pep_seq = ["DAAAIEF","DAAALEF"])

if __name__ == '__main__':
  p1 = Process(target=func1)
  p1.start()
  p2 = Process(target=func2)
  p2.start()
  p3 = Process(target=func1)
  p3.start()
  p4 = Process(target=func2)
  p4.start()
  p1.join()
  p2.join()
  p3.join()
  p4.join()

但是这段代码很容易处理 10 个肽段,但无法实现它,因为 PEP_list 包含 100 万个肽段

谢谢

【问题讨论】:

  • Process(target=my_function, args=(each_item_in_sub_list,)).start() 您可以生成比 CPU 数量更多的进程
  • 如果可以请详细说明谢谢

标签: python pandas python-multithreading python-multiprocessing


【解决方案1】:

multiprocessing.Pool.map 就是您要找的。
试试这个:

from multiprocessing import Pool

# I recommend using more partitions than processes,
# this way the work can be balanced.
# Of course this only makes sense if pep_list is bigger than
# the one you provide. If not, change this to 8 or so.
n = 50

# create indices for the partitions
ix = np.linspace(0, len(pep_list), n+1, endpoint=True, dtype=int)

# create partitions using the indices
sub_lists = [pep_list[i1:i2] for i1, i2 in zip(ix[:-1], ix[1:])]

p = Pool()
try:
    # p.map will return a list of dataframes which are to be
    # concatenated
    df = concat(p.map(my_function, sub_lists))
finally:
    p.close()

池将自动包含与可用内核一样多的进程。但是如果你愿意,你可以覆盖这个数字,看看文档。

【讨论】:

  • 停止并出现错误“TypeError: linspace() got an unexpected keyword argument 'dtype'”
  • @jax 你有哪个 numpy 版本?这个参数是 1.9 中的新参数...但是有一个解决方法,试试np.linspace(0, len(pep_list), n+1, endpoint=True).astype(int)
  • 感谢您的评论,我必须解决您的代码以针对我的情况对其进行优化,实际上它的工作速度很快,正常代码需要约 12.0 秒来计算 12 个肽序列,但您的代码需要约 10.0 秒即使我增加 "n" 的数量也要完成。您的代码很快但不是很快(或者我可能无法正确实现它)。我已经写下了一个符合我期望的代码,我在上面有更新,请查看它。
  • @jax 如果没有完整的代码,我无法真正说出问题所在。通常,如果并行化后没有大的加速,则意味着有很多共享内存访问或数据交换。我会排除前者,因为默认情况下不应该有共享内存,我认为它也会影响你的硬编码方法。后者应该通过分块来缓解,并且与您的结果相矛盾......除非......您最终是否真的收集了返回的数据帧?此外,更多的块并不总是更好,因为它会增加汇率,有时你只需要玩一下。
  • 感谢您的解释。我认为首先我应该学习并行化的基础知识和核心概念。您能否建议我任何基本参考资料,以帮助我理解并行化的基础知识,不是非常数学化或配备计算术语,但对于像我这样的生物学家来说很容易理解。谢谢
猜你喜欢
  • 1970-01-01
  • 2012-07-19
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-13
相关资源
最近更新 更多