Ehs*_*adr 3 python parallel-processing python-3.x python-asyncio python-multiprocessing
我有 6 个大文件,每个文件都包含一个我使用 pickle 函数保存在硬盘中的字典对象。按顺序加载所有这些大约需要 600 秒。我想同时开始加载所有这些文件以加快进程。假设它们都具有相同的大小,我希望在 100 秒内加载它们。我使用 multiprocessing 和 apply_async 分别加载它们中的每一个,但它像顺序一样运行。这是我使用的代码,它不起作用。该代码适用于其中 3 个文件,但其中 6 个文件的代码相同。我将第三个文件放在另一个硬盘中以确保 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))
Run Code Online (Sandbox Code Playgroud)
如果您的代码主要受 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]
Run Code Online (Sandbox Code Playgroud)
该GIL不会强迫IO操作运行序列化,因为这样做的Python IO时,始终将其释放。
关于替代品的几点说明:
multiprocessing 不太可能有帮助,因为虽然它保证在多个进程中完成其工作(因此没有 GIL),但它也需要在子进程和主进程之间传输内容,这需要额外的时间。
asyncio根本不会帮助你,因为它本身不支持异步文件系统访问(流行的操作系统也不支持)。虽然它可以用threads来模拟,但效果和上面的代码一样,只是多了些仪式感。
这两个选项都不会将六个文件的加载速度提高六倍。考虑到至少有一些时间用于创建字典,这些字典将由 GIL 序列化。如果您想真正加快启动速度,更好的方法是不要预先创建整个字典并切换到文件内数据库,可能使用字典来缓存对其内容的访问。