使用python 3.6将多个文件并行加载到内存中的最佳方法是什么?

时间:2018-05-23 03:46:07

标签: python python-3.x parallel-processing python-multiprocessing python-asyncio

我有6个大文件,每个文件都包含一个使用pickle函数保存在硬盘中的字典对象。按顺序加载所有这些大约需要600秒。我想开始同时加载它们以加快进程。假设它们都具有相同的大小,我希望在100秒内加载它们。我使用multiprocessing和apply_async分别加载它们,但它像顺序一样运行。这是我使用的代码,但它不起作用。 代码适用于其中3个文件,但其中6个文件的代码相同。我将第3个文件放在另一个硬盘上,以确保IO不受限制。

def loadMaps():    
    start = timeit.default_timer()
    procs = []
    pool = Pool(3)
    pool.apply_async(load1(),)
    pool.apply_async(load2(),)
    pool.apply_async(load3(),)
    pool.close()
    pool.join()
    stop = timeit.default_timer()
    print('loadFiles takes in %.1f seconds' % (stop - start))

1 个答案:

答案 0 :(得分:3)

如果您的代码主要受IO限制且文件位于多个磁盘上,则可能能够使用线程加快速度:

import concurrent.futures
import pickle

def read_one(fname):
    with open(fname, 'rb') as f:
        return pickle.load(f)

def read_parallel(file_names):
    with concurrent.futures.ThreadPoolExecutor() as executor:
        futures = [executor.submit(read_one, f) for f in file_names]
        return [fut.result() for fut in futures]

GIL不会强制IO操作序列化运行,因为Python在执行IO时会持续释放它。

关于替代品的几点评论:

  • multiprocessing不太可能有所帮助,因为虽然它保证在多个进程中完成其工作(因此没有GIL),但它还要求在子进程和主进程之间传输内容过程需要额外的时间。

  • asyncio根本不会帮助你,因为它本身不支持异步文件系统访问(流行的操作系统也不支持)。虽然它可以emulate it with threads,但效果与上面的代码相同,只有更多的仪式。

  • 这两个选项都不会加速将六个文件加载六倍。考虑到至少一些时间用于创建字典,这些字典将由GIL序列化。如果你想真正加速启动,更好的方法不是提前创建整个字典并切换到in-file database,可能使用字典来缓存对其内容的访问。