在Evolution Simulator中进行深度复制会造成内存泄漏

时间:2019-01-18 10:20:13

标签: python memory-leaks neural-network copy deep-copy

最近,我一直在尝试使用前馈神经网络在Python中创建一个进化模拟器。除复制功能外,其他所有功能均正常运行。

起初,在进行繁殖时,我简单地调用了一个函数,该函数创建了一个新动物对象,该对象具有其父母具有的相同的,稍有变异的属性。我通过编写parent.weights = child.weights来做到这一点。但是,我了解到,这仅创建了对父母体重的参考,因此,孩子并不独立于其父母。因此,例如,每当一个孩子改变体重时,所有其他具有参考体重的动物也会发生变化,从而导致整个人群的行为突然而相似的变化。

我后来发现了Python的copy库。现在要创建一个孩子动物,我使用copy.deepcopy()复制父对象的整个对象,然后更改复制的对象以创建孩子。这可以工作一段时间,但是在运行该程序约一个小时后,它是如此缓慢,以至于无法取得任何进展。我发现,当一个孩子出生并且制作了一个深拷贝时,该程序将完全停止,并一次加载几秒钟。

我不知道这是什么原因,但是我有点怀疑这可能是某种内存泄漏。我对您的问题是:

  1. 这可能是什么原因?

  2. 是否有解决方案或替代方法来创建以下内容的副本:   对象没有引用?

以下是相关副本,已简化:

调用复制功能:

#asexual reproduction
if self.energy > (((pow(self.sizeRadius, 2) * 3.14 ))):
    self.birthed_kin += 1
    self.energy -= (pow(self.sizeRadius, 2) * 3.14 ) / 2
    self.birth_timer = 0

    self.copy_animal()

复制功能:

def copy_animal(self):

    copied_animal = copy.deepcopy(self)

    copied_animal.age = 0

    copied_animal.birthed_kin = 0
    copied_animal.sizeRadius = mutate_organ(copied_animal.sizeRadius, 1)
    copied_animal.energy = (pow(copied_animal.sizeRadius, 2) * 3.14) / 2
    copied_animal.health = pow(copied_animal.sizeRadius, 2) * 3.14
    copied_animal.pain = 0

    copied_animal.weights = [ 
mutate_neuralnetwork( copied_animal, copied_animal.input_size, copied_animal.hidden_sizes[0], copied_animal.weights[0], copied_animal.mutation_rate), 
mutate_neuralnetwork( copied_animal, copied_animal.hidden_sizes[0], copied_animal.output_size, copied_animal.weights[1], copied_animal.mutation_rate), 
   ]

    living_animals_array.append(copied_animal)

请让我知道我是否应该再分享其他代码或详细信息。

1 个答案:

答案 0 :(得分:0)

我认为可能正在发生的事情是您的实现是递归的,因此,GC永远无法释放所有以前的副本! (或者也许还有其他原因导致GC无法发布这些项目)

在进化编程中,如果我没记错的话,通常只需要保留一定数量的表现最佳的“孩子”。您应该保留这些孩子的单独列表,并将新的孩子推到列表中,但还要确保删除旧的孩子!现在,还要确保您的实现不是递归的,并且不再有对旧实例的引用。如果您正确执行此操作,GC将正确释放您未使用的所有实例,并且您的问题可能会消失:)


编辑:操作员评论后:


我不确定mutate_neuralnetwork函数的作用。但是查看您的代码并考虑到复制变得越来越慢这一事实,这可能是您的数据结构是递归的。即如果copied_animal包含对先前实例的引用,而该实例又引用了甚至更早的版本,那么您可以想象在某个时刻链变得如此长,以至于复制需要很长时间。这些将是旧的参考。确保您没有递归数据结构,或者有时将变量设置为None可以帮助GC确定不再需要它们。