You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多进程性能优化及数据存储相关技术问询

项目流程
  • 将Python自定义类保存为pickle文件
  • 在多进程中加载pickle文件
  • 将加载后的文件输入至机器学习模型
代码实现
def get_learning_data(file):
    print(file)
    picklefile = open(file, 'rb')
    processed_data = pickle.load(picklefile)
    picklefile.close()
    print(f'end with file {file}')
    
    
if __name__ == '__main__':
    # files 
    file_list = [r'sample{0}.pickle'.format(i) for i in range(100)]
    _start = time()
    file_count = len(file_list)
    print(multiprocessing.cpu_count())
    MAX_PROCESS = 12
    d = file_count // MAX_PROCESS if file_count % MAX_PROCESS == 0 else file_count // MAX_PROCESS +1
    file_batch = [file_list[i * MAX_PROCESS : (i + 1) * MAX_PROCESS] for i in range(d)]
    
    with multiprocessing.Pool(MAX_PROCESS) as pool:
        for files in file_batch:
            pool.map(
                get_learning_data,
                files
            )
    print(f'multi done time : {time() - _start}')

    _start = time()
    for f in file_list:
        get_learning_data(f)
    print(f'single done time : {time() - _start}')
问题咨询
  1. multiprocessing.cpu_count()返回值为20,与处理器数量一致而非核心数,请问最优进程数设为12还是20?
  2. 因Python GIL问题采用多进程,是否有其他替代方案?
  3. 测试100个文件时,10进程耗时67秒,单进程耗时183秒,性能提升幅度低于预期;同事用30核CPU测试时多进程耗时反而更长,原因是什么?
  4. 除XML、pickle、JSON外,是否有其他方式保存Python dataclass?
问题解答

1. 最优进程数选择

优先实际测试20进程的表现,你的任务属于IO密集型(加载文件),理论上IO密集型任务可以开比逻辑核心数更多的进程,但实际受限于磁盘IO带宽:

  • 如果是SSD磁盘,并行读写能力强,20进程可能比12进程更快;如果是机械硬盘,多进程同时读会触发大量随机IO,反而因为等待IO导致上下文切换开销增加,此时12进程可能更稳定。
  • 另外multiprocessing.cpu_count()返回的是逻辑核心数(含超线程),不是物理处理器数量,你看到的“20”应该是逻辑核心数。建议直接跑20进程的测试,对比12进程的耗时,选实际更快的配置。

2. GIL问题的替代方案

针对你的IO密集型场景,有这些更合适的替代方案:

  • 线程池:用concurrent.futures.ThreadPoolExecutor,IO等待时GIL会自动释放,线程的创建和调度开销远低于进程,对IO密集型任务效率更高。
  • 异步IO:用asyncio配合aiofiles异步读取文件,适合高并发IO场景,能在单线程内处理大量IO任务。
  • 其他Python实现:比如PyPy(对IO和数值计算都有优化)、Cython(编译核心代码绕开GIL),如果后续有计算密集型任务可以考虑。

3. 性能提升不达预期/多进程变慢的原因

核心问题出在磁盘IO瓶颈和进程开销:

  • 磁盘IO竞争:当多个进程同时读取文件,磁盘的读写带宽被占满,所有进程都进入等待状态,尤其是机械硬盘,随机读写性能差,多进程并行反而不如单进程顺序读高效。同事的30核CPU如果搭配的磁盘性能一般,30进程同时读会让IO竞争更激烈,耗时自然更长。
  • 进程调度开销:如果单个pickle文件很小,加载耗时短,那么进程的启动、调度开销占比会变大,抵消并行带来的收益。
  • 手动分批的问题:你代码里手动把文件分成批次,可能导致任务分配不均,部分进程提前结束,浪费资源,直接用pool.map处理整个file_list即可,让进程池自动调度任务。

4. Python dataclass的其他保存方式

除了XML、pickle、JSON,还有这些实用选项:

  • MsgPack:二进制序列化格式,体积比JSON小,速度快,支持大部分Python数据类型,把dataclass转成字典后就能直接序列化。
  • YAML:可读性极强,支持复杂嵌套结构,适合配置类dataclass,用pyyaml库即可实现序列化/反序列化。
  • SQLite/关系型数据库:如果需要持久化查询,用sqlalchemy或dataclasses-sqlalchemy把dataclass映射到数据库表,方便数据管理。
  • HDF5:适合大数据量的数值型dataclass,用h5py库,支持高效读写和压缩,适合机器学习场景的批量数据存储。
  • Protocol Buffers:谷歌的二进制序列化格式,需要定义.proto文件,适合跨语言交互,能和dataclass快速互转。
  • Toml:简洁的配置格式,Python 3.11+内置tomllib库,适合小型配置类dataclass。

内容的提问来源于stack exchange,提问作者ding lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 18:35:27