SystemError: NULL result Multiprocessing Python

SystemError: NULL result Multiprocessing Python

我正在使用多处理池来训练机器学习器。

每个 LearnerRun 对象都有一个学习者、一个超参数字典、一个名称、其他选项字典中的更多选项、要写入结果的目录的名称、一组要训练的示例 ID(a切片或 numpy 数组),以及一组要测试的示例 ID(也是切片或 numpy 数组)。重要的是,训练和测试数据还没有被读取:ID 集相对较小并且指导后面函数的数据库读取行为。

我调用了 self.pool.apply_async(learner_run.run),它以前运行良好。现在池似乎已加载,但从未打印 运行() 函数顶部的打印语句,因此进程实际上并未获得 运行.

我已经追踪了一些关于此的其他 线程 ,发现我可以通过 handler = self.pool.apply_async(learner_run.run)handler.get() 更详细地看到问题。这会打印 "SystemError: NULL result without error in PyObject_Call".

太好了,我可以做到 Google。但是我在 Multiprocessing 的这个问题上所能找到的是,它可能是在将太大而无法 pickle 的参数传递给子进程时引起的。 但是,我显然没有向我的子进程传递任何参数。那么给出了什么?

除了超出分配的内存大小的参数——我有理由相信这不是这里的问题——还有什么可以导致 apply_async 给出空结果?

同样,这在我去度假之前有效并且没有改变。 对其他代码进行哪些类型的更改可能会导致此功能停止工作?

如果我不尝试从处理程序 get() 因此执行不会因错误而停止,内存使用将遵循这种奇怪的模式。

好的,我找到问题了。事实上,我的 LearnerRun 对 Multiprocessing 来说太大了 无法处理。但是它的方式非常微妙,所以我会描述一下。

显然,需要 pickle 的不仅仅是参数;该函数也被腌制,包括其执行将依赖的 LearnerRun 对象(self)。

LearnerRun 的构造函数获取传递给它的选项字典中的所有内容,并使用 setattr 将所有键和值转换为具有值的成员变量。这本身就很好,但我的同事意识到这留下了几个字符串,需要作为数据库引用并设置 self.trainDatabase = LarData(self.trainDatabase)self.coverageDatabase = LarData(self.coverageDatabase),这通常没问题。

Except 这意味着要 pickle class 你必须 pickle 整个数据库!我在健全性检查中发现了这一点,其中只是序列化 LearnerRun 本身以查看 pickle.dumps(learner_run) 会发生什么。我的记忆被淹没了,交换区开始以惊人的速度填满,直到 Whosebug.

那么酸洗到磁盘呢? pickle.dump(learner_run, filename)也炸了。在我终止之前它达到了 14.3 GiB!

删除这些引用并稍后在需要时调用 LarData 构造函数怎么样?砰。固定的。一切正常。多处理不再给出神秘的 SystemError。

这是second time最近让我很痛苦的泡菜。