dill与cPickle的速度差异

21

我正试图序列化成千上万个对象,其中一些对象是lambda对象。

由于cPickle不适用于lambda函数,因此我尝试使用dill。然而,在反序列化(或者叫取消dill操作)时,计算速度下降了超过10倍。通过查看源代码,似乎dill在内部使用了pickle,这可能是速度降低的原因。

是否有其他选项可以将两个模块的优点结合起来?

编辑:最显着的速度下降发生在取消序列化过程中。


请查看此答案:https://dev59.com/MGQn5IYBdhLWcg3wtpBW#16626757 - MaxU - stand with Ukraine
1
正如我在问题中所述,问题在于与cPickle相比,dill速度太慢。 - Tohiko
“PiCloud序列化的对象可以使用普通的pickle / cPickle load和loads函数进行反序列化。”因此,如果您的序列化/反序列化比率<<1,我认为这可能会对您有所帮助。 - MaxU - stand with Ukraine
啊,抱歉。我在问题中澄清了,显著的速度下降是在反序列化期间发生的。 - Tohiko
1个回答

48

我是dill的作者。是的,dill通常较慢,但这是你为了更强大的序列化所付出的代价。如果你要序列化很多类和函数,那么你可能想尝试dill.settings中的dill变体。如果你使用byref=True,那么dill将通过引用来pickle多个对象(这比默认选项更快速)。其他设置则在某些对象上权衡了picklibility和速度。

In [1]: import dill

In [2]: f = lambda x:x

In [3]: %timeit dill.loads(dill.dumps(f))
1000 loops, best of 3: 286 us per loop

In [4]: dill.settings['byref'] = True

In [5]: %timeit dill.loads(dill.dumps(f))
1000 loops, best of 3: 237 us per loop

In [6]: dill.settings
Out[6]: {'byref': True, 'fmode': 0, 'protocol': 2, 'recurse': False}

In [7]: dill.settings['recurse'] = True

In [8]: %timeit dill.loads(dill.dumps(f))
1000 loops, best of 3: 408 us per loop

In [9]: class Foo(object):
   ...:     x = 1
   ...:     def bar(self, y):
   ...:         return y + self.x
   ...:     

In [10]: g = Foo()

In [11]: %timeit dill.loads(dill.dumps(g))
10000 loops, best of 3: 87.6 us per loop

In [12]: dill.settings['recurse'] = False

In [13]: %timeit dill.loads(dill.dumps(g))
10000 loops, best of 3: 87.4 us per loop

In [14]: dill.settings['byref'] = False

In [15]: %timeit dill.loads(dill.dumps(g))
1000 loops, best of 3: 499 us per loop

In [16]: 

4
嗨,@Mike McKerns,当我开始使用dill时,是为了这些我实例化的定制Python类,这些类内部有许多复杂的数据类型,而它完美地运行(在pickle无法运行时)。从那时起,我一直在使用dill,但我想知道可以使用pickle的哪些数据类型不会出问题?这可能超出了评论的范围,但我觉得您是专家,因为您为某个原因而制作了dill - O.rka
5
请看 https://github.com/uqfoundation/dill/blob/master/dill/_objects.py。这是我尽最大努力记录哪些内容可以被 dill 和/或 pickle 序列化的代码。该文件也有对应的测试。但是,将它们放在类中……那就需要进行更多未经测试的工作。 - Mike McKerns

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接