加快读取多个pickle文件

use*_*414 16 python python-multithreading python-multiprocessing

我有很多泡菜文件。目前我循环阅读它们,但这需要很多时间。我想加快速度,但不知道如何做到这一点。

多处理不起作用,因为为了将数据从子进程传输到主进程数据需要序列化(腌制)和反序列化。

由于 GIL,使用线程也无济于事。

我认为解决方案是一些用 C 编写的库,它需要读取文件列表,然后运行多个线程(没有 GIL)。周围有这样的东西吗?

更新 回答您的问题:

  • 文件是用于机器学习的数据处理的部分产品
  • pandas.Series对象,但预先不知道 dtype
  • 我想要很多文件,因为我们想轻松选择任何子集
  • 我想要许多较小的文件而不是一个大文件,因为一个大文件的反序列​​化需要更多的内存(在某个时间点我们已经序列化了字符串和反序列化对象)
  • 文件的大小可能会有很大差异
  • 我使用 python 3.7 所以我相信它实际上是 cPickle
  • 使用pickle非常灵活,因为我不必担心底层类型——我可以保存任何东西

hro*_*okr 5

我同意评论中指出的内容,即由于 python 本身的限制(主要是 GIL 锁,正如您所指出的),并且可能根本没有比您现在正在做的更快的加载信息的速度。或者,如果有办法的话,它可能技术含量很高,但最终只能略微提高速度。

也就是说,根据您拥有的数据类型,使用QuicklePyrobuf可能会更快。


Aar*_*ron 5

我认为解决方案是一些用 C 编写的库,它需要读取文件列表,然后运行多个线程(没有 GIL)。周围有这样的东西吗?

简而言之:不。 pickle显然对于足够多的人来说已经足够好了,以至于没有与 pickle 协议完全兼容的主要替代实现。在 python 3 中的某个时候,cPickle已与 合并pickle,并且无论如何都不会释放 GIL,这就是线程无法帮助您的原因(Py_BEGIN_ALLOW_THREADS_pickle.c中搜索,您将找不到任何内容)。

如果您的数据可以重新构造为更简单的数据格式(例如 csv)或二进制格式(例如numpynpy),那么读取数据时的 CPU 开销将会更少。Pickle 的构建首先是为了灵活性,而不是速度或紧凑性。更复杂、速度更低的规则的一个可能的例外是使用 HDF5 格式h5py,它可能相当复杂,我已经用来最大化SATA SSD的带宽。

最后,您提到您有很多泡菜文件,这本身可能会造成不小的开销。每次打开新文件时,操作系统都会产生一些开销。您只需将 pickle 文件附加在一起即可方便地组合它们。然后您可以调用Unpickler.load(),直到到达文件末尾。这是使用以下命令将两个 pickle 文件组合在一起的快速示例shutil

import pickle, shutil, os

#some dummy data
d1 = {'a': 1, 'b': 2, 1: 'a', 2: 'b'}
d2 = {'c': 3, 'd': 4, 3: 'c', 4: 'd'}

#create two pickles
with open('test1.pickle', 'wb') as f:
    pickle.Pickler(f).dump(d1)
with open('test2.pickle', 'wb') as f:
    pickle.Pickler(f).dump(d2)
    
#combine list of pickle files
with open('test3.pickle', 'wb') as dst:
    for pickle_file in ['test1.pickle', 'test2.pickle']:
        with open(pickle_file, 'rb') as src:
            shutil.copyfileobj(src, dst)
            
#unpack the data
with open('test3.pickle', 'rb') as f:
    p = pickle.Unpickler(f)
    while True:
        try:
            print(p.load())
        except EOFError:
            break
        
#cleanup
os.remove('test1.pickle')
os.remove('test2.pickle')
os.remove('test3.pickle')
Run Code Online (Sandbox Code Playgroud)