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

Windows11下VSCode中Pandas DataFrame多进程预测异常排查

问题描述

在Windows 11系统的Visual Studio Code中运行Python代码时遇到以下问题:

  • 需要调用predict方法测试100个样本,该方法耗时较长,但样本间无依赖、变量无修改,具备并行化条件
  • predict需访问hlcs/hlcs_clean等变量,尝试通过参数传入后,调用multiprocessing.Pool.map()程序无限运行,调试界面清空;但单线程运行完全正常
  • 设备有12个物理核心,动态获取num_process返回24,当前手动设置为12,需排查问题原因
代码与输出

运行代码

import Mains.Main_deap as md
import numpy as np
import statistics as stat
import timeit
import warnings
import pandas as pd
import multiprocessing

# 设置参数
size_array_pool = 1  # 种子样本量
runs = 500  # 运行次数
num_best_individuals = 100  # 筛选最优个体数量

# 遗传算法参数
crossover_probability = 0.5  # 交叉概率
mutation_probability = 0.4  # 变异概率
population_size = 200  # 种群规模
num_generations = 100  # 进化代数

# 读取干净数据用于对比
hlcs_clean, llcs_clean = md.read_file("data/file_li.csv")

# 错误相关变量定义
number_of_errors = 1
error_types = ["value", "negiert", "index"]
selected_error_type = 1
error_type = error_types[selected_error_type]

# 定义并行处理样本的函数
def process_sample(sample):
    if md.predict(hlcs, llcs, sample) != md.predict(hlcs_clean, llcs_clean, sample):
        return {'error_found': 1, 'error_not_found': 0}
    else:
        return {'error_found': 0, 'error_not_found': 1}

# 开始计时
start = timeit.default_timer()

# 初始化结果统计字典
results_deap = {
    'error_found': 0,
    'error_not_found': 0
}

# 主循环:运行遗传算法并评估样本
for r in range(runs):
    j = 0
    hlcs, llcs = md.read_file("data/file _li.csv")
    
    # 生成错误数据
    while j < number_of_errors:
        feedback = md.create_single_error(llcs, error_type)
        if feedback is None:
            continue
        else:
            j += 1

    # 抑制性能警告
    warnings.filterwarnings("ignore", category=Warning)
    array_pool = llcs.get_n_samples_with_labels_random(size_array_pool)
    array_pool = md.convert_df_from_standard_to_01(hlcs, llcs, array_pool)
    array_population = array_pool.values
    
    # 运行遗传算法
    algorithm = md.deap_algorithm(array_population, crossover_probability, mutation_probability, num_best_individuals, population_size, num_generations, hlcs)
    best_individuals = algorithm.run_algorithm()
    
    warnings.resetwarnings()

    # 打印最优个体的信息(补充原代码缺失的check初始化)
    check = True
    if check:
        print(type(best_individuals[1]))
        print(f"best_individuals.shape: {best_individuals.shape}")
        print(type(best_individuals))
        check = False

    # 尝试并行评估样本
    pool_results = []
    num_processes = 12
    pool = multiprocessing.Pool(processes=num_processes)
    args_list = [(sample, hlcs, llcs, hlcs_clean, llcs_clean) for sample in best_individuals]
    pool_results.extend(pool.map(process_sample, args_list))
    pool.close()
    pool.join()

    # 更新结果统计
    for result in pool_results:
        results_deap["error_found"] += result['error_found']
        results_deap["error_not_found"] += result['error_not_found']

# 停止计时
stop = timeit.default_timer()

# 打印运行时长
print(f"Runtime: {(stop - start)/60} minutes")

输出信息

<class 'pandas.core.series.Series'>
best_individuals.shape: (100, 1087)
<class 'pandas.core.frame.DataFrame'>
排查与解决思路

1. 参数传递不匹配(直接导致挂起)

你定义的process_sample仅接受sample一个参数,但构建的args_list每个元素是包含5个元素的元组。pool.map()会把整个元组作为单个参数传给process_sample,导致参数不匹配,子进程抛出错误但Windows环境下不会主动暴露错误,表现为程序无限挂起。

  • 解决方法二选一:
    • 修改process_sample函数,接收元组参数并解包:
      def process_sample(args):
          sample, hlcs, llcs, hlcs_clean, llcs_clean = args
          if md.predict(hlcs, llcs, sample) != md.predict(hlcs_clean, llcs_clean, sample):
              return {'error_found': 1, 'error_not_found': 0}
          else:
              return {'error_found': 0, 'error_not_found': 1}
      
    • 使用pool.starmap()替代pool.map(),它会自动将元组拆分为多个参数传入函数:
      pool_results.extend(pool.starmap(process_sample, args_list))
      

2. 缺少Windows多进程主入口判断

Windows下multiprocessing采用spawn方式创建子进程,会重新执行整个脚本。如果没有将主程序逻辑放到if __name__ == '__main__':块中,子进程会再次创建Pool,导致死锁或无限循环。

  • 解决方法:将所有主执行代码(从start = timeit.default_timer()开始到结尾)包裹在主入口判断中:
    if __name__ == '__main__':
        # 开始计时
        start = timeit.default_timer()
        # ... 后续所有主逻辑代码 ...
    

3. 序列化兼容性问题

Windows下子进程需要通过pickle序列化传递对象,如果hlcs/llcs等是自定义类实例或无法被pickle序列化的对象,会导致子进程无法启动,表现为程序挂起。

  • 解决方法:
    • 检查hlcs/llcs的类型,确保是可序列化对象(pandas DataFrame/Series默认支持)
    • 如果涉及自定义类,确保类实现了pickle兼容的序列化逻辑,或者使用dill库替代默认pickle(需先安装dill,并在代码中配置:multiprocessing.set_start_method('spawn'))

4. 资源过载问题

虽然设置了12个进程,但如果每个predict调用占用大量内存/CPU,可能导致系统资源耗尽,进程无响应。可以先将num_processes设为较小值(如4)测试是否能正常运行,再逐步调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 04:08:12