基本概念
OpenMP(Open Multi-Processing)是一种基于编译器指令的并行编程接口,通过简单添加代码(如#pragma
),自动将任务拆分为多线程并行执行,直接利用多核CPU性能。本文介绍三种最常用的指令,保证一看就会。
使用示例
1) #pragma omp parallel for
简单来说就是自动多线程执行循环,线程数由系统决定。
通俗解释:
- 老板(系统)根据工作量自动分配工人数量(线程数)。
- 默认行为(无需手动指定),适合“懒人”。
适合快速实现并行,不关心线程数细节,任务独立且不需要统计结果。
使用示例:
#pragma omp parallel for
for (int i = 0; i < 100; ++i) {
process_data(i); // 自动分配线程处理数据
}
2) #pragma omp parallel for num_threads(2)
简单来说就是多线程执行循环,且指定用 2 个线程。
通俗解释:
- 明确雇两个工人(线程)搬砖(执行循环任务)。
- 工人之间不共享数据,各自独立工作。
适合明确固定线程数,任务完全独立且不需要汇总结果。
使用示例:
#pragma omp parallel for num_threads(2)
for (int i = 0; i < 100; ++i) {
printf("%d ", i); // 2个线程独立输出,顺序不确定
}
3) #pragma omp parallel for reduction(+:sum) num_threads(2)
简单来说就是多线程累加,且指定用 2 个线程, 结果绝对正确。
通俗解释:
- 想象两个工人(线程)数同一堆苹果(数据)。
- 每人拿一个本子(私有变量
sum
)记录自己数的数量,最后把两人的结果相加。 - 关键点:避免两人同时写同一张纸(数据竞争),结果绝对正确。
适合需要规约操作(线程安全),明确要求线程数。
使用示例:
int sum = 0;
#pragma omp parallel for reduction(+:sum) num_threads(2)
for (int i = 0; i < 100; ++i) {
sum += i; // 2个线程各自累加,最后合并结果
}
reduction(+:sum)
的作用
- 归约(Reduction):将多个线程的局部计算结果合并到全局变量中。
+
:归约运算符(加法),其他常见运算符包括*
(乘法)、max
(最大值)、min
(最小值)等。sum
:需要归约的全局变量。底层工作原理:
1)每个线程会创建自己的私有
sum
副本,初始值为归约运算符的初始值(加法为 0)。2)每个线程在自己的私有副本上执行循环内的计算操作。
3)所有线程结束后,将各线程的私有副本通过运算符(
+
)合并到主线程的全局变量(sum
)中。