281 lines
9.8 KiB
Python
Executable File
281 lines
9.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""
|
||
MPI-OpenMP矩阵乘法实验数据分析脚本
|
||
用于读取实验数据并生成性能分析图表
|
||
"""
|
||
|
||
import pandas as pd
|
||
import matplotlib.pyplot as plt
|
||
import numpy as np
|
||
import seaborn as sns
|
||
|
||
# 设置中文字体和样式
|
||
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
|
||
plt.rcParams['axes.unicode_minus'] = False
|
||
sns.set_style("whitegrid")
|
||
|
||
def load_data(filename='experiment_results.csv'):
|
||
"""加载实验数据"""
|
||
df = pd.read_csv(filename)
|
||
return df
|
||
|
||
def load_serial_data(filename='serial_results.csv'):
|
||
"""加载串行基准数据"""
|
||
df = pd.read_csv(filename)
|
||
return df
|
||
|
||
def plot_experiment1(df):
|
||
"""绘制实验一:MPI进程数扩展性"""
|
||
exp1 = df[df['Experiment'] == 'Exp1'].copy()
|
||
|
||
if exp1.empty:
|
||
print("警告:没有找到实验一的数据")
|
||
return
|
||
|
||
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
|
||
|
||
# 绘制加速比
|
||
for size in exp1['M'].unique():
|
||
data = exp1[exp1['M'] == size].sort_values('MPI_Processes')
|
||
ax1.plot(data['MPI_Processes'], data['Speedup'],
|
||
marker='o', label=f'{size}×{size}', linewidth=2)
|
||
|
||
ax1.set_xlabel('MPI进程数', fontsize=12)
|
||
ax1.set_ylabel('加速比', fontsize=12)
|
||
ax1.set_title('实验一:MPI进程数扩展性(OpenMP=1)', fontsize=14)
|
||
ax1.legend(fontsize=10)
|
||
ax1.grid(True, alpha=0.3)
|
||
ax1.plot([1, 16], [1, 16], 'k--', alpha=0.3, label='理想线性加速比')
|
||
|
||
# 绘制效率
|
||
for size in exp1['M'].unique():
|
||
data = exp1[exp1['M'] == size].sort_values('MPI_Processes')
|
||
ax2.plot(data['MPI_Processes'], data['Efficiency'] * 100,
|
||
marker='s', label=f'{size}×{size}', linewidth=2)
|
||
|
||
ax2.set_xlabel('MPI进程数', fontsize=12)
|
||
ax2.set_ylabel('效率 (%)', fontsize=12)
|
||
ax2.set_title('实验一:并行效率', fontsize=14)
|
||
ax2.legend(fontsize=10)
|
||
ax2.grid(True, alpha=0.3)
|
||
ax2.axhline(y=100, color='k', linestyle='--', alpha=0.3, label='理想效率100%')
|
||
|
||
plt.tight_layout()
|
||
plt.savefig('exp1_mpi_scaling.png', dpi=300, bbox_inches='tight')
|
||
print("已保存: exp1_mpi_scaling.png")
|
||
plt.close()
|
||
|
||
def plot_experiment2(df):
|
||
"""绘制实验二:MPI-OpenMP混合并行扩展性"""
|
||
exp2 = df[df['Experiment'] == 'Exp2'].copy()
|
||
|
||
if exp2.empty:
|
||
print("警告:没有找到实验二的数据")
|
||
return
|
||
|
||
exp2['Total_Processors'] = exp2['MPI_Processes'] * exp2['OpenMP_Threads']
|
||
|
||
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
|
||
|
||
# 绘制加速比(按OpenMP线程数分组)
|
||
for nthreads in exp2['OpenMP_Threads'].unique():
|
||
data = exp2[exp2['OpenMP_Threads'] == nthreads].copy()
|
||
# 对相同总处理器数的数据取平均
|
||
avg_data = data.groupby('Total_Processors').agg({
|
||
'Speedup': 'mean',
|
||
'Efficiency': 'mean'
|
||
}).reset_index()
|
||
|
||
ax1.plot(avg_data['Total_Processors'], avg_data['Speedup'],
|
||
marker='o', label=f'OpenMP={nthreads}', linewidth=2)
|
||
|
||
ax1.set_xlabel('总处理器数', fontsize=12)
|
||
ax1.set_ylabel('加速比', fontsize=12)
|
||
ax1.set_title('实验二:混合并行扩展性', fontsize=14)
|
||
ax1.legend(fontsize=10)
|
||
ax1.grid(True, alpha=0.3)
|
||
|
||
# 绘制效率
|
||
for nthreads in exp2['OpenMP_Threads'].unique():
|
||
data = exp2[exp2['OpenMP_Threads'] == nthreads].copy()
|
||
avg_data = data.groupby('Total_Processors').agg({
|
||
'Speedup': 'mean',
|
||
'Efficiency': 'mean'
|
||
}).reset_index()
|
||
|
||
ax2.plot(avg_data['Total_Processors'], avg_data['Efficiency'] * 100,
|
||
marker='s', label=f'OpenMP={nthreads}', linewidth=2)
|
||
|
||
ax2.set_xlabel('总处理器数', fontsize=12)
|
||
ax2.set_ylabel('效率 (%)', fontsize=12)
|
||
ax2.set_title('实验二:并行效率', fontsize=14)
|
||
ax2.legend(fontsize=10)
|
||
ax2.grid(True, alpha=0.3)
|
||
ax2.axhline(y=100, color='k', linestyle='--', alpha=0.3)
|
||
|
||
plt.tight_layout()
|
||
plt.savefig('exp2_hybrid_scaling.png', dpi=300, bbox_inches='tight')
|
||
print("已保存: exp2_hybrid_scaling.png")
|
||
plt.close()
|
||
|
||
def plot_experiment3(df):
|
||
"""绘制实验三:MPI/OpenMP组合优化"""
|
||
exp3 = df[df['Experiment'] == 'Exp3'].copy()
|
||
|
||
if exp3.empty:
|
||
print("警告:没有找到实验三的数据")
|
||
return
|
||
|
||
exp3['Total_Processors'] = exp3['MPI_Processes'] * exp3['OpenMP_Threads']
|
||
|
||
fig, ax = plt.subplots(figsize=(12, 6))
|
||
|
||
# 绘制效率热图
|
||
for size in exp3['M'].unique():
|
||
data = exp3[exp3['M'] == size]
|
||
ax.plot(data['MPI_Processes'], data['Efficiency'] * 100,
|
||
marker='o', label=f'{size}×{size}', linewidth=2, markersize=8)
|
||
|
||
ax.set_xlabel('MPI进程数', fontsize=12)
|
||
ax.set_ylabel('效率 (%)', fontsize=12)
|
||
ax.set_title('实验三:不同MPI/OpenMP组合的效率(总处理器数=16)', fontsize=14)
|
||
ax.legend(fontsize=10)
|
||
ax.grid(True, alpha=0.3)
|
||
ax.axhline(y=100, color='k', linestyle='--', alpha=0.3)
|
||
|
||
# 添加x轴标签显示OpenMP线程数
|
||
ax2 = ax.twiny()
|
||
ax2.set_xlim(ax.get_xlim())
|
||
ax2.set_xlabel('OpenMP线程数', fontsize=12)
|
||
ax2.set_xticks([1, 2, 4, 8, 16])
|
||
ax2.set_xticklabels([16, 8, 4, 2, 1])
|
||
|
||
plt.tight_layout()
|
||
plt.savefig('exp3_mpi_openmp_combo.png', dpi=300, bbox_inches='tight')
|
||
print("已保存: exp3_mpi_openmp_combo.png")
|
||
plt.close()
|
||
|
||
def plot_efficiency_heatmap(df):
|
||
"""绘制效率热图"""
|
||
exp2 = df[df['Experiment'] == 'Exp2'].copy()
|
||
|
||
if exp2.empty:
|
||
print("警告:没有找到实验二的数据")
|
||
return
|
||
|
||
# 选择一个中等规模的矩阵尺寸
|
||
sizes = sorted(exp2['M'].unique())
|
||
if len(sizes) > 2:
|
||
target_size = sizes[len(sizes)//2]
|
||
else:
|
||
target_size = sizes[0] if sizes else 1024
|
||
|
||
data = exp2[exp2['M'] == target_size].copy()
|
||
|
||
if data.empty:
|
||
print("警告:没有足够的数据绘制热图")
|
||
return
|
||
|
||
# 创建数据透视表
|
||
pivot_data = data.pivot_table(
|
||
values='Efficiency',
|
||
index='MPI_Processes',
|
||
columns='OpenMP_Threads',
|
||
aggfunc='mean'
|
||
) * 100
|
||
|
||
fig, ax = plt.subplots(figsize=(10, 8))
|
||
sns.heatmap(pivot_data, annot=True, fmt='.1f', cmap='YlOrRd',
|
||
cbar_kws={'label': '效率 (%)'}, ax=ax)
|
||
ax.set_title(f'并行效率热图(矩阵尺寸: {target_size}×{target_size})', fontsize=14)
|
||
ax.set_xlabel('OpenMP线程数', fontsize=12)
|
||
ax.set_ylabel('MPI进程数', fontsize=12)
|
||
|
||
plt.tight_layout()
|
||
plt.savefig('efficiency_heatmap.png', dpi=300, bbox_inches='tight')
|
||
print("已保存: efficiency_heatmap.png")
|
||
plt.close()
|
||
|
||
def print_summary(df):
|
||
"""打印实验结果摘要"""
|
||
print("\n" + "="*80)
|
||
print("实验结果摘要")
|
||
print("="*80)
|
||
|
||
# 实验一摘要
|
||
exp1 = df[df['Experiment'] == 'Exp1']
|
||
if not exp1.empty:
|
||
print("\n实验一:MPI进程数扩展性(OpenMP=1)")
|
||
print("-" * 80)
|
||
for size in sorted(exp1['M'].unique()):
|
||
data = exp1[exp1['M'] == size]
|
||
max_speedup = data['Speedup'].max()
|
||
max_eff = data['Efficiency'].max()
|
||
best_np = data.loc[data['Speedup'].idxmax(), 'MPI_Processes']
|
||
print(f"矩阵 {size}×{size}: 最大加速比={max_speedup:.2f} (NP={best_np}), "
|
||
f"最高效率={max_eff*100:.1f}%")
|
||
|
||
# 实验二摘要
|
||
exp2 = df[df['Experiment'] == 'Exp2']
|
||
if not exp2.empty:
|
||
exp2['Total_Processors'] = exp2['MPI_Processes'] * exp2['OpenMP_Threads']
|
||
print("\n实验二:混合并行扩展性")
|
||
print("-" * 80)
|
||
for nthreads in sorted(exp2['OpenMP_Threads'].unique()):
|
||
data = exp2[exp2['OpenMP_Threads'] == nthreads]
|
||
max_speedup = data['Speedup'].max()
|
||
max_eff = data['Efficiency'].max()
|
||
best_total = data.loc[data['Speedup'].idxmax(), 'Total_Processors']
|
||
print(f"OpenMP={nthreads}: 最大加速比={max_speedup:.2f} "
|
||
f"(总处理器={best_total}), 最高效率={max_eff*100:.1f}%")
|
||
|
||
# 实验三摘要
|
||
exp3 = df[df['Experiment'] == 'Exp3']
|
||
if not exp3.empty:
|
||
print("\n实验三:MPI/OpenMP组合优化(总处理器=16)")
|
||
print("-" * 80)
|
||
for size in sorted(exp3['M'].unique()):
|
||
data = exp3[exp3['M'] == size]
|
||
max_eff = data['Efficiency'].max()
|
||
best_config = data.loc[data['Efficiency'].idxmax()]
|
||
print(f"矩阵 {size}×{size}: 最高效率={max_eff*100:.1f}% "
|
||
f"(MPI={best_config['MPI_Processes']}, "
|
||
f"OpenMP={best_config['OpenMP_Threads']})")
|
||
|
||
print("\n" + "="*80)
|
||
|
||
def main():
|
||
"""主函数"""
|
||
import sys
|
||
|
||
filename = sys.argv[1] if len(sys.argv) > 1 else 'experiment_results.csv'
|
||
|
||
print(f"加载数据文件: {filename}")
|
||
try:
|
||
df = load_data(filename)
|
||
print(f"数据加载成功,共 {len(df)} 条记录")
|
||
except FileNotFoundError:
|
||
print(f"错误:找不到文件 {filename}")
|
||
print("请先运行 ./run_experiments.sh 生成实验数据")
|
||
return
|
||
|
||
# 打印摘要
|
||
print_summary(df)
|
||
|
||
# 生成图表
|
||
print("\n生成性能分析图表...")
|
||
plot_experiment1(df)
|
||
plot_experiment2(df)
|
||
plot_experiment3(df)
|
||
plot_efficiency_heatmap(df)
|
||
|
||
print("\n所有图表已生成完成!")
|
||
print("\n建议:")
|
||
print("1. 查看 exp1_mpi_scaling.png 了解MPI扩展性")
|
||
print("2. 查看 exp2_hybrid_scaling.png 了解混合并行性能")
|
||
print("3. 查看 exp3_mpi_openmp_combo.png 了解MPI/OpenMP组合优化")
|
||
print("4. 查看 efficiency_heatmap.png 了解不同配置的效率分布")
|
||
|
||
if __name__ == '__main__':
|
||
main()
|