[英]Multiprocessing default serialisation very slow
我想尽可能高效地从多个 CSV 构建一个 DataFrame。 CSV 非常大。 大多数都超过 100 万行。 一共有9个文件。 合并后的总行数 > 800 万。
这是代码:
from pandas import read_csv, concat
from concurrent.futures import ProcessPoolExecutor
from glob import glob
from time import perf_counter
PATH = '/Users/fred/Downloads/*.csv'
def process(filename):
try:
return read_csv(filename, low_memory=False)
except Exception as e:
print(e)
def main():
start = perf_counter()
with ProcessPoolExecutor() as ppe:
concat(rv for rv in ppe.map(process, glob(PATH)) if rv is not None)
print(f'Duration={perf_counter()-start}s')
if __name__ == '__main__':
main()
这需要大约 2 分钟的时间来运行并产生所需的结果。
然而,在根据 CPU 和内存使用情况监视运行时行为时,我注意到一段时间后生成的进程似乎空闲了过多的时间。
所以我决定自己 pickle DataFrames 看看性能是否可以提高。 显然代码更复杂,但我认为展示它很重要:
from pandas import read_csv, concat
from concurrent.futures import ProcessPoolExecutor
from glob import glob
from tempfile import NamedTemporaryFile
from pickle import dump, load
from os import remove
from time import perf_counter
PATH = '/Users/fred/Downloads/*.csv'
def process(filename):
try:
df = read_csv(filename, low_memory=False)
with NamedTemporaryFile(delete=False) as ntf:
dump(df, ntf)
return ntf.name
except Exception as e:
print(e)
def unpickle(filename):
if filename is not None:
try:
with open(filename, 'rb') as upf:
return load(upf)
except Exception as e:
print(e)
finally:
try:
remove(filename)
except Exception as e:
print(e)
def main():
start = perf_counter()
with ProcessPoolExecutor() as ppe:
concat(unpickle(rv) for rv in ppe.map(process, glob(PATH)) if rv is not None)
print(f'Duration={perf_counter()-start}s')
if __name__ == '__main__':
main()
在我看来,这个更复杂的代码(我正在接管 Python 默认应该为我做的序列化)不是必需的。
但是这种“手动”序列化方法实际上只用了一半的时间。
谁能帮我理解为什么“默认”行为比“手动”序列化方法运行得慢得多。
如果相关:
macOS 13.0.1
Python 3.11.1
32GB RAM
3 GHz 10-Core Intel Xeon W
性能差异的主要原因可能是由于使用的序列化技术。 Python 使用的默认序列化技术是 pickle,它通常比 JSON 等其他序列化格式慢。 因此,使用 pickle 的手动方法可能比默认方法更快。 此外,手动方法在内存使用方面更高效,因为它只需要将序列化数据存储在内存中,而默认方法需要将序列化和反序列化数据都存储在内存中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.