2026-01-21 18:02:30 +08:00
..
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00
2026-01-21 18:02:30 +08:00

MPI-OpenMP混合并行矩阵乘法实验

项目结构

gemm/
├── gemm_serial.cpp      # 串行版本实现
├── gemm_parallel.cpp    # MPI-OpenMP混合并行版本
├── xmake.lua           # 构建配置文件
├── run_experiments.sh  # 自动化测试脚本
└── README.md          # 本文件

编译说明

使用xmake编译推荐

cd /home/yly/dev/hpc-lab-code/work/gemm
xmake build

编译后的可执行文件位于:

  • build/linux/x86_64/release/gemm_serial
  • build/linux/x86_64/release/gemm_parallel

手动编译

# 串行版本
mpic++ -O3 -march=native gemm_serial.cpp -o gemm_serial

# 并行版本
mpic++ -O3 -march=native -fopenmp gemm_parallel.cpp -o gemm_parallel -lm

运行说明

串行版本

./build/linux/x86_64/release/gemm_serial M N K use-blas

参数说明:

  • M: 左矩阵行数
  • N: 左矩阵列数/右矩阵行数
  • K: 右矩阵列数
  • use-blas: 是否使用BLAS0=不使用1=使用,当前版本未实现)

示例:

./build/linux/x86_64/release/gemm_serial 1024 1024 1024 0

并行版本

mpirun -np <进程数> ./build/linux/x86_64/release/gemm_parallel M N K

参数说明:

  • 进程数: MPI进程数量
  • M, N, K: 矩阵维度

示例:

# 使用4个MPI进程矩阵大小2048x2048x2048
mpirun -np 4 ./build/linux/x86_64/release/gemm_parallel 2048 2048 2048

# 使用16个MPI进程8个OpenMP线程
export OMP_NUM_THREADS=8
mpirun -np 16 ./build/linux/x86_64/release/gemm_parallel 4096 4096 4096

自动化测试

使用提供的脚本自动运行所有实验并收集数据:

cd /home/yly/dev/hpc-lab-code/work/gemm
./run_experiments.sh

脚本会自动:

  1. 编译程序
  2. 运行串行基准测试
  3. 运行实验一固定OpenMP线程数改变MPI进程数
  4. 运行实验二同时改变MPI进程数和OpenMP线程数
  5. 运行实验三固定总处理器数改变MPI/OpenMP组合
  6. 保存所有结果到CSV文件

实验设计

实验一MPI进程数扩展性

目的研究在OpenMP线程数固定为1时不同MPI进程数的性能表现

变量

  • 固定OpenMP线程数 = 1
  • 改变MPI进程数 = 1, 2, 4, 9, 16
  • 测试:不同矩阵尺寸 512, 1024, 2048, 4096

测量指标

  • 运行时间ms
  • 加速比 = T_serial / T_parallel
  • 效率 = 加速比 / MPI进程数

实验二MPI-OpenMP混合并行扩展性

目的研究同时改变MPI进程数和OpenMP线程数时的性能表现

变量

  • OpenMP线程数1, 2, 4, 8
  • MPI进程数1, 2, 4, 9, 16
  • 总处理器数 = MPI进程数 × OpenMP线程数
  • 测试:不同矩阵尺寸 512, 1024, 2048, 4096

测量指标

  • 运行时间ms
  • 加速比 = T_serial / T_parallel
  • 效率 = 加速比 / 总处理器数

实验三MPI/OpenMP组合优化

目的在总处理器数固定的情况下研究不同MPI/OpenMP组合对性能的影响

变量

  • 固定:总处理器数 = 16
  • 改变MPI/OpenMP组合
    • 1 MPI进程 × 16 OpenMP线程
    • 2 MPI进程 × 8 OpenMP线程
    • 4 MPI进程 × 4 OpenMP线程
    • 8 MPI进程 × 2 OpenMP线程
    • 16 MPI进程 × 1 OpenMP线程
  • 测试:不同矩阵尺寸 512, 1024, 2048, 4096

测量指标

  • 运行时间ms
  • 加速比 = T_serial / T_parallel
  • 效率 = 加速比 / 总处理器数

数据处理与绘图

输出文件格式

串行结果 (serial_results.csv):

M,N,K,Time_ms
512,512,512,123.45
1024,1024,1024,987.65
...

并行结果 (experiment_results.csv):

Experiment,M,N,K,MPI_Processes,OpenMP_Threads,Time_ms,Speedup,Efficiency
Exp1,512,512,512,1,1,120.34,1.0267,1.0267
Exp1,512,512,512,2,1,65.43,1.8873,0.9437
...

绘图建议

使用Python (matplotlib)、Excel或R进行绘图

图1实验一 - MPI进程数扩展性

  • X轴MPI进程数
  • Y轴加速比左轴、效率右轴
  • 不同线条:不同矩阵尺寸
  • 预期:加速比随进程数增加,但效率可能下降

图2实验二 - 总处理器数扩展性

  • X轴总处理器数
  • Y轴加速比左轴、效率右轴
  • 不同线条不同OpenMP线程数
  • 预期混合并行可能比纯MPI或纯OpenMP更高效

图3实验三 - MPI/OpenMP组合影响

  • X轴MPI进程数
  • Y轴效率
  • 不同线条:不同矩阵尺寸
  • 预期存在最优的MPI/OpenMP组合

Python绘图示例

import pandas as pd
import matplotlib.pyplot as plt

# 读取数据
df = pd.read_csv('experiment_results.csv')

# 实验一MPI扩展性
exp1 = df[df['Experiment'] == 'Exp1']
fig, ax1 = plt.subplots(figsize=(10, 6))

for size in exp1['M'].unique():
    data = exp1[exp1['M'] == size]
    ax1.plot(data['MPI_Processes'], data['Speedup'], 
             marker='o', label=f'{size}x{size}')

ax1.set_xlabel('MPI进程数')
ax1.set_ylabel('加速比')
ax1.set_title('实验一MPI进程数扩展性OpenMP=1')
ax1.legend()
ax1.grid(True)
plt.savefig('exp1_speedup.png')
plt.show()

性能分析与优化

预期性能瓶颈

  1. 通信开销MPI通信在大规模并行时可能成为瓶颈
  2. 负载不均衡:带状分块可能导致某些进程工作量较大
  3. 内存带宽:矩阵乘法是内存密集型操作
  4. 缓存利用率:小矩阵可能无法充分利用缓存

可能的优化方向

  1. 优化分块策略

    • 使用二维块循环分块代替带状分块
    • 考虑缓存友好的分块大小
  2. 优化通信

    • 使用非阻塞通信重叠计算和通信
    • 减少通信次数,增加每次通信的数据量
  3. 优化计算

    • 使用SIMD指令向量化
    • 优化循环顺序以提高缓存命中率
    • 考虑使用Strassen算法等快速矩阵乘法
  4. 混合并行优化

    • 找到最优的MPI/OpenMP组合
    • 考虑NUMA架构的亲和性

实验报告要点

  1. 实验环境

    • 硬件配置CPU核心数、内存大小
    • 软件环境MPI版本、编译器版本
  2. 实验结果

    • 三个实验的数据表格
    • 性能曲线图
    • 加速比和效率分析
  3. 结果分析

    • 不同并行策略的性能比较
    • MPI进程数和OpenMP线程数的最优组合
    • 矩阵规模对并行效率的影响
  4. 优化方案

    • 识别性能瓶颈
    • 提出优化策略
    • 实施优化并对比效果
  5. 结论

    • MPI-OpenMP混合并行的优势
    • 最佳实践建议
    • 进一步改进方向

故障排除

编译错误

如果遇到MPI相关错误

# 检查MPI是否安装
which mpic++
mpic++ --version

# 检查OpenMP支持
echo | clang++ -x c++ - -fopenmp -E - > /dev/null

运行时错误

如果遇到MPI运行错误

# 检查MPI进程数是否合理
# 确保系统有足够的资源

# 检查OpenMP线程数设置
echo $OMP_NUM_THREADS

性能异常

如果性能不如预期:

  1. 检查CPU频率是否正常是否降频
  2. 关闭其他占用资源的程序
  3. 检查系统负载
  4. 确认编译优化选项已启用(-O3

参考资料