上一篇【高级程序设计 实验报告10】CPU并行计算目录一、 实验目的二、实验环境实验步骤代码实验心得一、 实验目的1、用 OpenMP 实现最基本的数值算法“矩阵乘法”2、掌握 for 编译制导语句3、对并行程序进行简单的性能调优二、实验环境Visual Studio2017Windows10实验步骤1创建 win32 控制台项目2通过输入的矩阵的行列数、线程数和矩阵乘法运行次数来控制计算量3观察不同线程数的CPU 运行的时间代码#include iostream #include omp.h #include cstdlib // 用于malloc和free using namespace std; // 声明矩阵生成函数 float* generate_matrix(int m, int n); // 声明矩阵乘法函数注意原代码中martix拼写错误已修正为matrix void multi_matrix(float* arr1, float* arr2, int m, int n, int result_size); // 声明矩阵显示函数原代码参数类型有误改为float* void show_matrix(float* arr, int m, int n); int main() { int row, column; // 矩阵行、列 // 输入矩阵行列数 cout 请输入矩阵的行数(m) endl; cin row; cout 请输入矩阵的列数(n) endl; cin column; // 确保矩阵可相乘第一个矩阵的列数需等于第二个矩阵的行数 if (column 0) { cerr 错误列数不能为0或负数 endl; return 1; } int matrix_size column; // 第二个矩阵的行数等于第一个矩阵的列数 // 生成矩阵 float* matrix1 generate_matrix(row, column); float* matrix2 generate_matrix(column, row); // 第二个矩阵为column行×row列 int compute_scale; // 矩阵乘法计算次数 cout 请输入矩阵乘法计算次数 endl; cin compute_scale; // 定义不同线程数的数组可根据需求扩展 const int thread_counts[] { 1, 2, 4, 8, 16 }; const int thread_count_num sizeof(thread_counts) / sizeof(int); // 遍历不同线程数进行测试 for (int i 0; i thread_count_num; i) { int thread_num thread_counts[i]; omp_set_num_threads(thread_num); // 设置线程数 // 记录开始时间使用omp_get_wtime()获取高精度时间 double start_time omp_get_wtime(); // 使用OpenMP并行执行计算循环 #pragma omp parallel for for (int iter 0; iter compute_scale; iter) { multi_matrix(matrix1, matrix2, row, column, matrix_size); } // 计算耗时毫秒 double elapsed_time (omp_get_wtime() - start_time) * 1000.0; cout 线程数 thread_num 时耗时 elapsed_time ms endl; } // 释放内存 free(matrix1); free(matrix2); system(pause); return 0; } // 矩阵生成函数生成m行n列的矩阵元素按规则i*(j1)1填充 float* generate_matrix(int m, int n) { float* tmp (float*)malloc(sizeof(float) * m * n); if (!tmp) { cerr 内存分配失败 endl; exit(1); } for (int i 0; i m; i) { for (int j 0; j n; j) { tmp[i * n j] i * (j 1) 1; // 生成规则数据 } } return tmp; } // 矩阵乘法函数计算m×n矩阵与n×result_size矩阵的乘积 void multi_matrix(float* arr1, float* arr2, int m, int n, int result_size) { float* result (float*)malloc(sizeof(float) * m * result_size); // 临时存储结果矩阵 if (!result) { cerr 内存分配失败 endl; exit(1); } // 初始化结果矩阵 for (int i 0; i m * result_size; i) { result[i] 0.0f; } // 标准矩阵乘法i行×k列 与 k行×j列 相乘得到i行×j列矩阵 for (int i 0; i m; i) { for (int j 0; j result_size; j) { for (int k 0; k n; k) { result[i * result_size j] arr1[i * n k] * arr2[k * result_size j]; } } } // 释放临时内存若不需要显示结果 free(result); } // 矩阵显示函数可选用于调试 void show_matrix(float* arr, int m, int n) { for (int i 0; i m; i) { for (int j 0; j n; j) { cout arr[i * n j] \t; } cout endl; } }实验心得在信息学院计算机科学与技术专业的学习历程中本次矩阵并行计算实验为我搭建起理论与实践深度融合的桥梁让我对并行计算技术有了从认知到应用的全方位探索也深化了对计算机性能优化核心逻辑的理解。实验的核心目标是运用 OpenMP 实现矩阵乘法这一基础数值算法同时掌握 for 编译制导语句的使用方法最终完成并行程序的性能调优。这一目标贯穿实验全程也让我清晰感受到并行计算并非单纯的代码编写而是对算法逻辑、硬件特性与编程技巧的综合考量。在实验准备阶段我重新梳理了矩阵乘法的底层原理。传统串行矩阵乘法通过三重循环逐层计算元素乘积和当矩阵维度较大或计算次数增多时单线程执行效率极低。而并行计算的核心思想是将任务拆解为多个子任务由不同线程并行处理从而充分利用 CPU 的多核资源。OpenMP 作为共享存储并行编程的重要标准其简洁的编译制导语句让并行化实现变得高效这也让我体会到高性能计算技术在工程实践中的便捷性与实用性。实验过程中代码编写与调试环节让我收获颇丰。在实现矩阵生成、乘法运算及结果展示等基础功能时我注重代码的规范性与严谨性例如合理使用动态内存分配确保程序稳定性通过输入校验避免无效参数带来的运行错误。在引入 OpenMP 并行化时#pragma omp parallel for 制导语句的应用成为关键我将矩阵乘法的多次计算循环拆解为并行任务让不同线程独立执行计算子任务。同时通过设置不同线程数1、2、4、8、16进行测试我直观观察到线程数与运行效率之间的关联。性能测试环节是实验的核心价值所在。随着线程数从 1 增加到 16程序运行耗时呈现出明显的变化趋势线程数较少时耗时下降幅度较大当线程数超过一定阈值后耗时下降趋势逐渐放缓甚至出现细微波动。这一现象让我深入理解了并行计算的性能瓶颈 —— 线程创建与调度的开销、CPU 核心数量的物理限制以及数据共享与通信的成本。例如当线程数超过 CPU 实际核心数时额外线程会增加上下文切换的资源消耗反而无法持续提升运行效率。这一发现打破了我此前 “线程数越多效率越高” 的片面认知让我明白并行程序优化需结合硬件实际情况合理规划线程数量。此外实验中也暴露出我在编程细节上的不足。例如在矩阵乘法函数中临时结果矩阵的内存分配与释放时机需精准把控若处理不当易造成内存泄漏并行区域的划分需避免过度细化否则会因线程调度开销抵消并行带来的性能提升。通过反复调试与优化我逐步掌握了并行程序的调优技巧也培养了严谨的程序设计思维。本次矩阵并行计算实验不仅让我熟练掌握了 OpenMP 的基础使用方法更让我对并行计算的核心逻辑、性能优化原理有了深刻理解。计算机科学是一门注重实践的学科只有将理论知识转化为实际代码才能真正掌握其精髓。未来我将把本次实验的收获运用到更多高性能计算相关的学习与实践中不断探索并行计算、人工智能等领域的技术应用持续提升自身的专业素养与工程实践能力。同时我也认识到计算机技术的发展日新月异唯有保持持续学习的态度不断突破自身认知边界才能在这个领域不断前行。
【高级程序设计 实验报告11】矩阵并行计算
上一篇【高级程序设计 实验报告10】CPU并行计算目录一、 实验目的二、实验环境实验步骤代码实验心得一、 实验目的1、用 OpenMP 实现最基本的数值算法“矩阵乘法”2、掌握 for 编译制导语句3、对并行程序进行简单的性能调优二、实验环境Visual Studio2017Windows10实验步骤1创建 win32 控制台项目2通过输入的矩阵的行列数、线程数和矩阵乘法运行次数来控制计算量3观察不同线程数的CPU 运行的时间代码#include iostream #include omp.h #include cstdlib // 用于malloc和free using namespace std; // 声明矩阵生成函数 float* generate_matrix(int m, int n); // 声明矩阵乘法函数注意原代码中martix拼写错误已修正为matrix void multi_matrix(float* arr1, float* arr2, int m, int n, int result_size); // 声明矩阵显示函数原代码参数类型有误改为float* void show_matrix(float* arr, int m, int n); int main() { int row, column; // 矩阵行、列 // 输入矩阵行列数 cout 请输入矩阵的行数(m) endl; cin row; cout 请输入矩阵的列数(n) endl; cin column; // 确保矩阵可相乘第一个矩阵的列数需等于第二个矩阵的行数 if (column 0) { cerr 错误列数不能为0或负数 endl; return 1; } int matrix_size column; // 第二个矩阵的行数等于第一个矩阵的列数 // 生成矩阵 float* matrix1 generate_matrix(row, column); float* matrix2 generate_matrix(column, row); // 第二个矩阵为column行×row列 int compute_scale; // 矩阵乘法计算次数 cout 请输入矩阵乘法计算次数 endl; cin compute_scale; // 定义不同线程数的数组可根据需求扩展 const int thread_counts[] { 1, 2, 4, 8, 16 }; const int thread_count_num sizeof(thread_counts) / sizeof(int); // 遍历不同线程数进行测试 for (int i 0; i thread_count_num; i) { int thread_num thread_counts[i]; omp_set_num_threads(thread_num); // 设置线程数 // 记录开始时间使用omp_get_wtime()获取高精度时间 double start_time omp_get_wtime(); // 使用OpenMP并行执行计算循环 #pragma omp parallel for for (int iter 0; iter compute_scale; iter) { multi_matrix(matrix1, matrix2, row, column, matrix_size); } // 计算耗时毫秒 double elapsed_time (omp_get_wtime() - start_time) * 1000.0; cout 线程数 thread_num 时耗时 elapsed_time ms endl; } // 释放内存 free(matrix1); free(matrix2); system(pause); return 0; } // 矩阵生成函数生成m行n列的矩阵元素按规则i*(j1)1填充 float* generate_matrix(int m, int n) { float* tmp (float*)malloc(sizeof(float) * m * n); if (!tmp) { cerr 内存分配失败 endl; exit(1); } for (int i 0; i m; i) { for (int j 0; j n; j) { tmp[i * n j] i * (j 1) 1; // 生成规则数据 } } return tmp; } // 矩阵乘法函数计算m×n矩阵与n×result_size矩阵的乘积 void multi_matrix(float* arr1, float* arr2, int m, int n, int result_size) { float* result (float*)malloc(sizeof(float) * m * result_size); // 临时存储结果矩阵 if (!result) { cerr 内存分配失败 endl; exit(1); } // 初始化结果矩阵 for (int i 0; i m * result_size; i) { result[i] 0.0f; } // 标准矩阵乘法i行×k列 与 k行×j列 相乘得到i行×j列矩阵 for (int i 0; i m; i) { for (int j 0; j result_size; j) { for (int k 0; k n; k) { result[i * result_size j] arr1[i * n k] * arr2[k * result_size j]; } } } // 释放临时内存若不需要显示结果 free(result); } // 矩阵显示函数可选用于调试 void show_matrix(float* arr, int m, int n) { for (int i 0; i m; i) { for (int j 0; j n; j) { cout arr[i * n j] \t; } cout endl; } }实验心得在信息学院计算机科学与技术专业的学习历程中本次矩阵并行计算实验为我搭建起理论与实践深度融合的桥梁让我对并行计算技术有了从认知到应用的全方位探索也深化了对计算机性能优化核心逻辑的理解。实验的核心目标是运用 OpenMP 实现矩阵乘法这一基础数值算法同时掌握 for 编译制导语句的使用方法最终完成并行程序的性能调优。这一目标贯穿实验全程也让我清晰感受到并行计算并非单纯的代码编写而是对算法逻辑、硬件特性与编程技巧的综合考量。在实验准备阶段我重新梳理了矩阵乘法的底层原理。传统串行矩阵乘法通过三重循环逐层计算元素乘积和当矩阵维度较大或计算次数增多时单线程执行效率极低。而并行计算的核心思想是将任务拆解为多个子任务由不同线程并行处理从而充分利用 CPU 的多核资源。OpenMP 作为共享存储并行编程的重要标准其简洁的编译制导语句让并行化实现变得高效这也让我体会到高性能计算技术在工程实践中的便捷性与实用性。实验过程中代码编写与调试环节让我收获颇丰。在实现矩阵生成、乘法运算及结果展示等基础功能时我注重代码的规范性与严谨性例如合理使用动态内存分配确保程序稳定性通过输入校验避免无效参数带来的运行错误。在引入 OpenMP 并行化时#pragma omp parallel for 制导语句的应用成为关键我将矩阵乘法的多次计算循环拆解为并行任务让不同线程独立执行计算子任务。同时通过设置不同线程数1、2、4、8、16进行测试我直观观察到线程数与运行效率之间的关联。性能测试环节是实验的核心价值所在。随着线程数从 1 增加到 16程序运行耗时呈现出明显的变化趋势线程数较少时耗时下降幅度较大当线程数超过一定阈值后耗时下降趋势逐渐放缓甚至出现细微波动。这一现象让我深入理解了并行计算的性能瓶颈 —— 线程创建与调度的开销、CPU 核心数量的物理限制以及数据共享与通信的成本。例如当线程数超过 CPU 实际核心数时额外线程会增加上下文切换的资源消耗反而无法持续提升运行效率。这一发现打破了我此前 “线程数越多效率越高” 的片面认知让我明白并行程序优化需结合硬件实际情况合理规划线程数量。此外实验中也暴露出我在编程细节上的不足。例如在矩阵乘法函数中临时结果矩阵的内存分配与释放时机需精准把控若处理不当易造成内存泄漏并行区域的划分需避免过度细化否则会因线程调度开销抵消并行带来的性能提升。通过反复调试与优化我逐步掌握了并行程序的调优技巧也培养了严谨的程序设计思维。本次矩阵并行计算实验不仅让我熟练掌握了 OpenMP 的基础使用方法更让我对并行计算的核心逻辑、性能优化原理有了深刻理解。计算机科学是一门注重实践的学科只有将理论知识转化为实际代码才能真正掌握其精髓。未来我将把本次实验的收获运用到更多高性能计算相关的学习与实践中不断探索并行计算、人工智能等领域的技术应用持续提升自身的专业素养与工程实践能力。同时我也认识到计算机技术的发展日新月异唯有保持持续学习的态度不断突破自身认知边界才能在这个领域不断前行。