繁体   English   中英

多处理默认序列化非常慢

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM