多处理和rpy2(带猿)

时间:2014-06-04 05:23:50

标签: python r multiprocessing rpy2 ape-phylo

我今天遇到了这个并且无法弄清楚原因。我有几个链接在一起的函数,它们执行一些耗时的操作,作为更大的管道的一部分。我已将这些包含在这里,尽可能地减少测试示例。问题是,当我直接调用函数时,我得到预期的输出(例如,5个不同的树)。但是,当我使用apply_async在多处理池中调用相同的函数(或者应用,并不重要)时,我得到5棵树,但它们都是相同的。

我已经在IPython笔记本中记录了这一点,可在此处查看:http://nbviewer.ipython.org/gist/cfriedline/0e275d528ff1a8d674c6

在单元格91中,我创建了5棵树(每个树有10个提示),并返回两个列表。第一个包含非多处理树,第二个包含apply_async。

在单元格92中,您可以看到在没有多处理的情况下创建树的结果,在93中可以看到多处理。

我期望在两个测试之间总共有10个不同的树,但是所有的多处理树都是相同的。对我来说没什么意义。

事物的相关版本:

  • Linux 2.6.18-238.12.1.el5 x86_64 GNU / Linux
  • Python 2.7.6 :: Anaconda 1.9.2(64位)
  • IPython 2.0.0
  • Rpy2 2.3.9

谢谢! 克里斯

2 个答案:

答案 0 :(得分:1)

我不是100%熟悉这些库,但是,在Linux上,(IIRC)multiprocessing使用os.fork。这意味着随机模块(您正在使用)的状态也将被分叉,并且您的每个进程将生成相同的随机数序列,从而导致不那么随机{ {1}}功能。

如果我是对的,并且你使游泳池小于你想要的树木数量,你应该看到你得到N个相同树木的组(其中N是游泳池的数量)。

我认为理想的解决方案可能是re-seed每个进程内部的随机数生成器。它们不太可能同时在完全运行,所以你应该得到不同的结果。

答案 1 :(得分:0)

我解决了这个,从@mgilson向正确的方向指出了一点。事实上,这是一个随机数问题,只是在python中 - 在R(叹息)中。创建池时会复制R的状态,这意味着它的随机种子也是如此。要修复,只需要一点rpy2,如下所示调用R的set.seed函数(使用一些特定于流程的东西):

def create_tree(num_tips, type):
    """
    creates the taxa tree in R
    @param num_tips: number of taxa to create
    @param type: type for naming (e.g., 'taxa')
    @return: a dendropy Tree
    @rtype: dendropy.Tree
    """
    r = rpy2.robjects.r
    set_seed = r('set.seed')
    set_seed(int((time.time()+os.getpid()*1000)))
    rpy2.robjects.globalenv['numtips'] = num_tips
    rpy2.robjects.globalenv['treetype'] = type
    name = _get_random_string(20)
    if type == "T":
        r("%s = rtree(numtips, rooted=T, tip.label=paste(treetype, seq(1:(numtips)), sep=''))" % name)
    else:
        r("%s = rtree(numtips, rooted=F, tip.label=paste(treetype, seq(1:(numtips)), sep=''))" % name)
    tree = r[name]
    return ape_to_dendropy(tree)