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

使用mpi4py散射pandas dataframe并对大数组执行数学计算的问题

核心问题分析

  • 你错误地尝试读取chunks变量拿当前进程的任务,而非scatter返回的data变量,非0进程的chunks本身就是None,必然报错
  • scatter给每个进程的是列对列表(不是单个列对),需要遍历列表逐个计算
  • 不需要单独发送列对应的数据,只要保证所有进程持有相同的df即可,测试场景下固定随机种子就能实现,真实场景可以让所有进程读取共享存储的同一份数据,远高效于广播大数据
  • 你第二个逐次Send列对的思路效率极低,scatter批量分发任务的原思路是正确的,不需要改

可运行的正确实现

import pandas as pd
import numpy as np
import itertools
import time
from mpi4py import MPI

comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()

# 固定随机种子,保证所有进程生成的df完全一致,不需要传输整个df
np.random.seed(42)
start_time = time.time()

# 计算函数示例,你可以替换成自己的相干计算逻辑
def myFunc(X,Y):
    return np.corrcoef(X, Y)[0,1]

# 所有进程生成相同的测试df,真实场景替换为读取共享存储文件即可
df = pd.DataFrame(data=np.random.random((500, 34)), columns=[f'Col_{i:03}' for i in range(1, 35)])
columns = df.columns.to_list()

if rank == 0:
    # 生成所有列对
    all_col_pairs = list(itertools.combinations(columns, 2))
    # 均分任务到各个进程
    chunks = [[] for _ in range(size)]
    for idx, pair in enumerate(all_col_pairs):
        chunks[idx % size].append(pair)
else:
    chunks = None

# 分发任务:每个进程拿到自己要计算的列对列表
local_pairs = comm.scatter(chunks, root=0)
print(f'进程{rank}分到{len(local_pairs)}个列对计算任务')

# 本地计算
local_res = {}
for col_a, col_b in local_pairs:
    x = df[col_a].to_numpy()
    y = df[col_b].to_numpy()
    local_res[f"{col_a}_&_{col_b}"] = myFunc(x, y)

# 汇总所有进程的结果到主进程
all_res_list = comm.gather(local_res, root=0)

if rank == 0:
    # 合并所有结果
    total_res = {}
    for res_dict in all_res_list:
        total_res.update(res_dict)
    # 排序输出
    result_df = pd.DataFrame.from_dict(total_res, orient='index', columns=['real_coh'])
    result_sorted = result_df.sort_index()
    print("并行计算完成,结果维度:", result_sorted.shape)
    print("总耗时:", time.time() - start_time)
    # 后续可以加result_sorted.to_csv()等保存逻辑

补充说明

如果你的实际场景中df过大,且无法让所有进程各自加载,你可以用广播numpy数组的方式传输数据:

if rank == 0:
    df_np = df.to_numpy()
else:
    df_np = np.empty((500,34), dtype=np.float64)
# 广播整个数组,比传输pandas对象高效很多
comm.Bcast(df_np, root=0)
# 所有进程都可以通过列名对应索引取数据,列名可以提前单独广播一次

执行命令还是你用的mpirun -np 4 python3 file_name.py即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:54:02