# 实验 2.3 并行环境下 OpenMP 程序的编译和运行 ## 实验目的 1. 掌握 OpenMP 的基本功能、构成方式、句法 2. 掌握 OpenMP 体系结构、特点与组成 3. 掌握采用 OpenMP 进行多核架构下多线程编程的基本使用方法 ## 实验环境 - 操作系统: Linux - 编译器: GCC with OpenMP support - 构建工具: xmake ## 实验一:Hello World (示例) ### 源代码 文件: [src/openmp_hello_world.c](src/openmp_hello_world.c) ```c #include #include int main() { int i; #pragma omp parallel { printf("Hello World\n"); for(i=0; i<4; i++) { printf("Iter:%d\n",i); } printf("GoodBye World\n"); } return 0; } ``` ### 编译和运行 ```bash xmake build openmp_hello_world xmake run openmp_hello_world ``` ### 运行结果 程序创建了多个线程(默认为系统核心数),每个线程都执行了 parallel 区域内的代码。可以看到多个 "Hello World" 和 "GoodBye World" 输出,展示了 OpenMP 的并行执行特性。 ## 实验二:利用中值积分定理计算 Pi 值 ### 串行版本 文件: [src/pi.c](src/pi.c) ### 并行版本 文件: [src/pi_par.c](src/pi_par.c) 关键并行化技术: 1. 使用 `#pragma omp parallel private(x) reduction(+:sum)` 创建并行区域 2. 使用 `#pragma omp for` 分配循环迭代 3. 使用 `private(x)` 声明每个线程的私有变量 4. 使用 `reduction(+:sum)` 自动合并各线程的 sum 值 ### 性能对比 | 线程数 | PI 值 | 执行时间 (秒) | 加速比 | |--------|---------------|---------------|--------| | 1 (串行) | 3.141592653590 | 1.554281 | 1.00x | | 2 | 3.141592653590 | 0.831361 | 1.87x | | 4 | 3.141592653590 | 0.448621 | 3.47x | | 8 | 3.141592653590 | 0.241111 | 6.45x | ### 分析 - 并行化后结果完全一致,精度保持不变 - 随着线程数增加,执行时间显著减少 - 8 线程时达到 6.45 倍加速比,接近理想加速比 - 该算法计算密集,适合并行化 ## 实验三:PI 值蒙特卡洛算法 ### 串行版本 文件: [src/pimonte_serial.c](src/pimonte_serial.c) ### 并行版本 文件: [src/pimonte_par.c](src/pimonte_par.c) 关键并行化技术: 1. 使用 `#pragma omp parallel private(i, j, x, y, r) reduction(+:dUnderCurve)` 2. 使用 `rand_r(&seed)` 替代 `rand()` 以保证线程安全 3. 每个线程使用不同的种子:`seed = omp_get_thread_num() + 1` 4. 数组 `r` 声明为 private,每个线程拥有独立副本 ### 性能对比 | 线程数 | PI 值 | 执行时间 (秒) | 加速比 | |--------|---------------|---------------|--------| | 1 (串行) | 3.141636540 | 8.347886 | 1.00x | | 2 | 3.141610420 | 1.662027 | 5.02x | | 4 | 3.141572660 | 0.858852 | 9.72x | | 8 | 3.141683140 | 0.464995 | 17.95x | ### 分析 - 蒙特卡洛方法的并行化效果非常显著 - 8 线程时达到近 18 倍加速比,超过理想加速比 - 原因:串行版本包含随机数生成的开销,而并行版本每个线程独立生成随机数 - PI 值精度略有波动,这是蒙特卡洛方法的特性(随机算法) ## OpenMP 并行化方法总结 ### 1. 创建并行区域 ```c #pragma omp parallel { // 代码块 } ``` ### 2. 并行化 for 循环 ```c #pragma omp parallel for for(int i=0; i