使用 python 3.6 将多个文件并行加载到内存中的最佳方法是什么?
What is the best way to load multiple files into memory in parallel using python 3.6?
我有 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))
如果您的代码主要受 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
根本帮不了你,因为它本身不支持异步文件系统访问(流行的 OS 也不支持)。虽然可以emulate it with threads,但是效果和上面的代码一样,只是多了点仪式感。
这两个选项都不会将这六个文件的加载速度提高六倍。考虑到至少有 一些 的时间用于创建字典,这些字典将由 GIL 序列化。如果你想真正加快启动速度,更好的方法是不要预先创建整个字典并切换到 in-file database,可能使用字典来缓存对其内容的访问。
我有 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))
如果您的代码主要受 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
根本帮不了你,因为它本身不支持异步文件系统访问(流行的 OS 也不支持)。虽然可以emulate it with threads,但是效果和上面的代码一样,只是多了点仪式感。这两个选项都不会将这六个文件的加载速度提高六倍。考虑到至少有 一些 的时间用于创建字典,这些字典将由 GIL 序列化。如果你想真正加快启动速度,更好的方法是不要预先创建整个字典并切换到 in-file database,可能使用字典来缓存对其内容的访问。