OpenMP多线程编程库

使用OpenMP,轻松实现多线程加速计算

Posted by YuCong on February 7, 2021

OpenMP是一个多线程程序的框架,使用OpenMP,可以轻松实现多线程加速计算。


Created 2022.02.22 by William Yu; Last modified: 2022.02.22-v1.0.1

Contact: windmillyucong@163.com

Copyleft! 2022 William Yu. Some rights reserved.


OpenMP

References

1. OpenMP简介

OpenMP (Open Multi-Processing) 是一个支持跨平台共享内存多线程并发的API,使用C、C++和Fortran语言。它由一组编译器指令、库例程和环境变量组成,这些共同定义了并行执行的规则。

1.1 主要特点

  • 简单易用:只需添加编译指令即可实现并行
  • 可移植性:支持多种平台和编译器
  • 可扩展性:支持从单核到多核的扩展
  • 灵活性:支持增量并行化

2. 基本用法

2.1 编译和链接

使用gcc/g++编译时,需要添加-fopenmp选项:

1
g++ -fopenmp program.cpp -o program

2.2 基本指令

最常用的OpenMP指令包括:

1
2
3
4
5
#pragma omp parallel  // 创建并行区域
#pragma omp for       // 并行化for循环
#pragma omp sections  // 并行化代码段
#pragma omp critical  // 临界区
#pragma omp atomic    // 原子操作

2.3 环境变量

常用的环境变量:

1
2
export OMP_NUM_THREADS=4  # 设置线程数
export OMP_SCHEDULE="dynamic"  # 设置调度策略

3. 示例代码

3.1 基本并行区域

1
2
3
4
5
6
7
8
9
10
11
#include <omp.h>
#include <iostream>

int main() {
    #pragma omp parallel
    {
        int thread_id = omp_get_thread_num();
        std::cout << "Hello from thread " << thread_id << std::endl;
    }
    return 0;
}

3.2 并行化for循环

将要进行多线程处理的for循环一定是独立的(independent)

1
2
3
4
5
6
7
8
9
10
11
12
#include <omp.h>
#include <vector>

int main() {
    std::vector<int> data(1000);
    
    #pragma omp parallel for
    for(int i = 0; i < 1000; i++) {
        data[i] = i * i;
    }
    return 0;
}

3.3 使用reduction

1
2
3
4
5
6
7
8
9
10
11
#include <omp.h>

int main() {
    int sum = 0;
    
    #pragma omp parallel for reduction(+:sum)
    for(int i = 0; i < 1000; i++) {
        sum += i;
    }
    return 0;
}

4. 性能优化建议

  1. 避免在并行区域中创建和销毁线程
  2. 合理设置线程数量
  3. 注意数据竞争和同步开销
  4. 使用适当的调度策略
  5. 避免false sharing

5. 常见问题

5.1 数据竞争

当多个线程同时访问共享数据时可能发生数据竞争。使用以下方法避免:

  • 使用critical区域
  • 使用atomic操作
  • 使用private子句
  • 使用reduction子句

5.2 负载均衡

使用不同的调度策略来优化负载均衡:

  • static:静态分配
  • dynamic:动态分配
  • guided:引导式分配
  • auto:由系统决定

Contact

Feel free to contact me windmillyucong@163.com anytime for anything.


License

CC0