4

这是一个片段,它将成功序列化 with dill,但失败pickle. 令人惊讶的是,Tensor对象本身不是可腌制的。这是线程感知张量的基本限制,还是只是没有实现?

import dill
import pickle
import tensorflow as tf

dill.dumps(tf.zeros((1,1)))
print("Dill succeeded")
pickle.dumps(tf.zeros((1,1)))
print("Pickle succeeded")

输出:

$ python foo.py
Dill succeeded
Traceback (most recent call last):
  File "foo.py", line 7, in <module>
    pickle.dumps(tf.zeros((1,1)))
TypeError: can't pickle _thread.lock objects
4

2 回答 2

4

为什么 dill 可以序列化这些对象,而 pickle 不行呢?简单的答案是pickle无法序列化python中的大多数对象,thread.lock包括对象。如果要序列化这些对象之一,请使用高级序列化库,如dill. 至于为什么pickle不能,我认为最初它源于 GIL 的实现和frame对象呈现一些不可序列化的对象,因此没有驱动在语言中序列化所有内容。一直有人谈论源于所有 python 对象的序列化的安全问题,但我认为这是一个红鲱鱼。没有完整的语言序列化限制了在并行计算中操作的能力,因此希望pickle能从dill如何序列化更多对象中学习。

于 2017-05-06T22:45:03.590 回答
2

我发现我无法重现eqzx脚本的输出,dill并且pickle.

虽然这个问题已经有好几年了,但我认为问题不在于 pickle,而是 tensorflow 1.x 中的张量没有立即评估这一事实。相反,当他们的图表被执行时,他们会被评估。(在 tensorflow 2.0 中,默认情况下启用了急切执行,因此您实际上不必处理这种范例)。

在上下文中使用tf.enable_eager_execution()或评估张量tf.Session()

以下脚本在使用 Pickle 或 Dill 时不会引发错误:

import tensorflow as tf
tf.enable_eager_execution()
import pickle 
# import dill

n = tf.zeros((1,1))
pickle.dumps(n)
# dill.dumps(n)

print('Success')

使用 Session.run() 的相同脚本不会引发错误:

import tensorflow as tf
import pickle
# import dill

with tf.Session() as sess:
    n = sess.run(tf.zeros((1,1)))
pickle.dumps(n)
# dill.dumps(n)

print('Success')
于 2019-10-29T08:25:04.580 回答