英文案例网站企业信用公示信息网
🧠 什么是 OpenMP?
OpenMP(Open Multi-Processing) 是一种基于 共享内存多线程并行编程 的标准接口,主要用于 C/C++ 和 Fortran。
 它通过编译器指令(#pragma)和少量函数调用,实现程序的多线程并行执行,广泛用于多核 CPU 的并行加速。
✅ 关键词:简单、快速接入、共享内存模型、线程级并行
📚 基本原理
-  
OpenMP 利用多线程模型,多个线程访问同一块共享内存。
 -  
主线程启动并分配工作到多个子线程。
 -  
子线程完成任务后回收,继续主线程的流程。
 
🚀 使用步骤(C++ 示例)
1. 头文件引入
#include <omp.h>
 
2. 编译器支持
使用 -fopenmp(GCC/Clang) 或 /openmp(MSVC):
g++ -fopenmp main.cpp -o my_app
 
🔧 常用指令详解
1. 并行执行块
#pragma omp parallel
{// 这里的代码由多个线程并行执行
}
 
2. 并行 for 循环
#pragma omp parallel for
for (int i = 0; i < N; ++i) {// 多线程并行执行每一次迭代
}
 
3. 指定共享与私有变量
#pragma omp parallel for shared(shared_var) private(i)
 
-  
shared(x):所有线程共享变量 -  
private(x):每个线程有自己的副本 
4. critical(临界区)
保证某段代码只被一个线程执行:
#pragma omp critical
{// 通常用于修改共享变量(如 push_back、计数等)
}
 
5. reduction(规约)
并行执行中对变量进行“聚合”:
int sum = 0;
#pragma omp parallel for reduction(+:sum)
for (int i = 0; i < N; ++i)sum += i; // 各线程加和后统一聚合
 
6. atomic(原子操作)
原子性地更新变量,比 critical 粒度更小:
#pragma omp atomic
sum += i;
 
7. schedule(任务划分策略)
控制任务在线程间如何分配:
#pragma omp parallel for schedule(static)   // 固定分配
#pragma omp parallel for schedule(dynamic)  // 动态分配
 
🧮 运行时函数
int omp_get_num_threads();    // 获取当前线程数
int omp_get_thread_num();     // 获取当前线程 ID(从 0 开始)
int omp_get_max_threads();    // 系统支持的最大线程数
 
🧪 示例:并行求数组和
#include <omp.h>
#include <iostream>
int main() {const int N = 1000;int a[N];for (int i = 0; i < N; ++i) a[i] = i;long long sum = 0;#pragma omp parallel for reduction(+:sum)for (int i = 0; i < N; ++i) {sum += a[i];}std::cout << "Sum = " << sum << std::endl;return 0;
}
 
⚠️ 使用注意事项
| 问题 | 描述 | 
|---|---|
| ❌ 数据竞争 | 多线程读写同一变量未加锁或同步,可能崩溃 | 
| ❌ 非线程安全容器 | std::vector、deque 等 STL 容器需手动保护 | 
| ❌ 非结构化编程 | 不当的 #pragma 结构容易导致 bug | 
| ❌ 嵌套并行 | 默认为关闭,需手动打开 omp_set_nested(1) | 
✅ 适合的使用场景
| 场景 | 说明 | 
|---|---|
| CPU 密集型计算 | 大量循环计算、矩阵乘法、图像处理 | 
| 数据并行 | 处理同一类型的大量数据 | 
| 图像 Patch 并行处理 | 图像分块 + #pragma omp parallel for | 
| 替代多线程 | 简洁替代 pthread/C++ std::thread 等 | 
🧰 优缺点总结
| 优点 | 缺点 | 
|---|---|
| ✅ 易上手 | ❌ 仅支持共享内存系统 | 
| ✅ 与现有代码融合简单 | ❌ 控制粒度较粗,不适合复杂任务分配 | 
| ✅ 开销小(无需线程池) | ❌ 对线程安全性要求高,容易出错 | 
📦 补充工具
-  
GOMP(GNU OpenMP Runtime):你遇到的
libgomp.so就是它,OpenMP 的运行时。 -  
Intel TBB / C++20 并行算法:适合更复杂的并行场景。
 -  
OpenCL / CUDA:适合跨设备(GPU)并行。
 
执行例子
#include <iostream>
#include <omp.h>int main() {#pragma omp parallel{int tid = omp_get_thread_num();std::cout << "Thread %d says hello\n" << tid << std::endl;int num_threads = omp_get_num_threads();std::cout << "Number of threads: " << num_threads << std::endl;}std::cout << " ------------------------- " << std::endl;#pragma omp parallel forfor (int i = 0; i < 8; ++i) {printf("Thread %d handles i = %d\n", omp_get_thread_num(), i);int tid = omp_get_thread_num();std::cout << "the threads is: " << tid << std::endl;std::cout << std::endl;}std::cout << " ------------------------- " << std::endl;int public_val = 0;for(int i=0; i<10; i++){public_val += 1;}std::cout << "the public_val is: " << public_val << std::endl;public_val = 0;#pragma omp parallel forfor(int i=0; i<10; i++){   #pragma omp criticalpublic_val += 1;}std::cout << "the public_val is: " << public_val << std::endl;public_val = 0;#pragma omp parallel forfor(int i=0; i<10; i++){   public_val += 1;}std::cout << "the public_val is: " << public_val << std::endl;return 0;
}// g++ main.cpp -fopenmp -o hello 
