python - 进化模拟器中的深拷贝造成内存泄漏
问题描述
最近我一直在尝试使用前馈神经网络在 Python 中创建一个进化模拟器。除了复制功能外,一切正常。
起初,在开发繁殖时,我只是简单地调用了一个函数,该函数创建了一个新的动物对象,该对象具有与其父母所具有的相同但略有变异的属性。我通过例如写作来做到这一点parent.weights = child.weights
。然而,我了解到这只会创建对父母权重的引用,因此孩子并不独立于其父母。因此,例如,每当一个孩子改变其体重时,所有其他具有参考体重的动物也会发生变化,从而导致整个人群的行为突然发生类似的变化。
后来我发现了 Python 的copy
库。现在要创建子动物,我使用复制父级的整个对象copy.deepcopy()
,然后更改复制的对象以创建子级。这工作了一段时间,但在运行程序大约一个小时后,它太慢了,无法取得任何进展。我发现当一个孩子出生时,进行深拷贝时,程序会完全停止,并且一次加载几秒钟。
我不知道这是因为什么,但我有点怀疑这可能是某种内存泄漏。我对你的问题是:
这可能是什么原因?
是否有任何解决方案或替代方法可以在不引用的情况下创建对象副本?
这是相关的副本,简化:
调用再现函数:
#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)
如果我应该分享更多代码或详细信息,请告诉我。
解决方案
我认为可能发生的情况是您的实现是递归的,因此,GC 永远无法释放您以前的所有副本!(或者也许还有其他原因导致 GC 无法释放这些项目)
在进化编程中,如果我没记错的话,你通常只需要保留一定数量的表现最好的“孩子”。您应该保留这些孩子的单独列表并将新的推送到列表中,但也要确保删除旧的!现在,还要确保您的实现不是递归的,并且不再引用旧实例。如果您正确执行此操作,GC 将正确释放您未使用的任何实例,您的问题可能会消失 :)
编辑:在 OPs 评论之后:
我不确定该mutate_neuralnetwork
功能的作用。但是查看您的代码并考虑到复制变得越来越慢的事实可能是您的数据结构是递归的。即,如果copied_animal
包含对先前实例的引用,该实例又引用甚至更早的版本,然后您可以想象在某些时候链变得如此之长以至于复制它需要很长时间。这些将是旧的参考。确保您没有递归数据结构,或者有时将变量设置为 None 可以帮助 GC 确定不再需要它们。
推荐阅读
- powershell - 如何使用 PowerShell 将文件夹从一个位置移动到另一个位置
- javascript - 如何在 JavaScript 中处理嵌套函数中的变量
- ruby-on-rails - Does “#includes” position matter on rails?
- mysql - Sqoop import query where ID between row_numbers does not work
- vbscript - 如何使用 PCOMM VBScript 提取正在运行的脚本名称
- javascript - 彼此内部有多个 for 循环
- javascript - 不使用lookbehind重写此正则表达式 - 带有 JS 的无效正则表达式
- amazon-web-services - 带有 aws 代码管道的自定义版本标签
- image - 在图像上创建居中的高斯模糊蒙版
- sql - 我经常在 Access 上使用的联合查询中突然出现“表达式输入错误或太复杂”错误