我今天遇到了这个并且无法弄清楚原因。我有几个链接在一起的函数,它们执行一些耗时的操作,作为更大的管道的一部分。我已将这些包含在这里,尽可能地减少测试示例。问题是,当我直接调用函数时,我得到预期的输出(例如,5个不同的树)。但是,当我使用apply_async在多处理池中调用相同的函数(或者应用,并不重要)时,我得到5棵树,但它们都是相同的。
我已经在IPython笔记本中记录了这一点,可在此处查看:http://nbviewer.ipython.org/gist/cfriedline/0e275d528ff1a8d674c6
在单元格91中,我创建了5棵树(每个树有10个提示),并返回两个列表。第一个包含非多处理树,第二个包含apply_async。
在单元格92中,您可以看到在没有多处理的情况下创建树的结果,在93中可以看到多处理。
我期望在两个测试之间总共有10个不同的树,但是所有的多处理树都是相同的。对我来说没什么意义。
事物的相关版本:
谢谢! 克里斯
答案 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)