mcpField
O
openmp

openmp

github.com/mohitmishra786开发269297 次安装18 周前更新
代码仓库

关于 openmp

openmp 是一项指导 Agent 使用 OpenMP 进行共享内存并行编程的技能,面向 C、C++ 和 Fortran 开发者。内容涵盖 CPU 循环并行、任务、GPU 卸载、性能调优与常见错误排查。

主要功能

  1. 01循环并行与调度策略
  2. 02归约和数据共享属性
  3. 03SIMD 与任务并行
  4. 04OpenMP GPU 卸载
  5. 05线程环境调优与性能分析
  6. 06数据竞争和伪共享排查

适用场景

  1. 01并行化多核 CPU 上的循环
  2. 02为不规则任务实现并行处理
  3. 03通过 OpenMP target 指令卸载到 GPU
  4. 04排查扩展性差或线程配置问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill openmp

安装后在 Claude Code 中输入/openmp确认已加载。

详细介绍

OpenMP

用途

指导 Agent 使用 OpenMP 共享内存并行:#pragma omp parallel for 与调度子句、归约、数据共享属性、SIMD 提示、任务并行、OpenMP 5.x GPU target 卸载、常见陷阱(伪共享、数据竞争)、环境调优,以及使用 Score-P 或 TAU 进行性能分析。

适用场景

  • 在多核 CPU 上并行化 C/C++/Fortran 循环
  • 实现归约(求和、最大值、自定义操作)
  • 为不规则工作负载实现任务并行
  • 使用 OpenMP target 指令将计算卸载到 GPU
  • 诊断扩展性问题(伪共享、负载不均衡)
  • 调优线程数和自旋行为

工作流

1. 基本的 parallel for
#include <omp.h>
#include <stdio.h>

int main(void) {
    const int n = 1000000;
    double sum = 0.0;

    #pragma omp parallel for reduction(+:sum)
    for (int i = 0; i < n; i++)
        sum += i * 0.001;

    printf("sum = %f, threads = %d\n", sum, omp_get_max_threads());
    return 0;
}
gcc -fopenmp -O3 -o omp_sum omp_sum.c
export OMP_NUM_THREADS=8
./omp_sum
2. 调度子句
#pragma omp parallel for schedule(static)          // equal chunks, low overhead
#pragma omp parallel for schedule(dynamic, 64)     // dynamic chunks of 64
#pragma omp parallel for schedule(guided)          // decreasing chunk size
#pragma omp parallel for schedule(auto)            // compiler/runtime decides
调度方式适用场景
static每次迭代的工作量均匀
dynamic每次迭代的耗时不同
guided每次迭代的耗时递减
static,1使用交错分块进行缓存分块
3. 数据共享属性
int shared_var = 0;
#pragma omp parallel private(i) shared(shared_var)
{
    int i = omp_get_thread_num();
    #pragma omp atomic
    shared_var += i;
}

// firstprivate — copy in; lastprivate — copy out after loop
#pragma omp parallel for firstprivate(offset) lastprivate(result)
for (int i = 0; i < n; i++) { ... }
子句含义
private每个线程拥有未初始化的副本
shared一个变量,由所有线程共享
reduction(op:var)在结束时合并(+、*、max、&&、||)
firstprivate使用主线程的值初始化
lastprivate主线程获取最后一次迭代的值
4. SIMD 向量化提示
#pragma omp simd
for (int i = 0; i < n; i++)
    c[i] = a[i] + b[i];

// SIMD + parallel
#pragma omp parallel for simd
for (int i = 0; i < n; i++)
    c[i] = a[i] * b[i];

需要 -fopenmp-simd,或需要编译器支持 SIMD 的 -fopenmp。使用 -fopt-info-vec 检查。

5. 任务并行
#pragma omp parallel
{
    #pragma omp single
    {
        for (int i = 0; i < 10; i++) {
            #pragma omp task firstprivate(i)
            process_subtree(i);
        }
        #pragma omp taskwait
    }
}

任务适用于递归算法(快速排序、树遍历),这类算法不适合使用循环并行。

6. 计时
double start = omp_get_wtime();
#pragma omp parallel for
for (int i = 0; i < n; i++) work(i);
double elapsed = omp_get_wtime() - start;
printf("elapsed: %f s\n", elapsed);
7. GPU target 卸载(OpenMP 5.x)
#pragma omp target teams distribute parallel for map(to:a[0:n]) map(from:c[0:n])
for (int i = 0; i < n; i++)
    c[i] = a[i] * 2.0f;
# NVIDIA offload
gcc -fopenmp -foffload=-march=sm_80 -o offload offload.c

# Check device
export OMP_DEFAULT_TARGET_DEVICE=1

需要编译器支持卸载(GCC offload、Clang/OpenMP、NVIDIA HPC SDK)。

8. 环境变量
export OMP_NUM_THREADS=16
export OMP_PROC_BIND=close        # bind threads to nearby cores
export OMP_PLACES=cores
export GOMP_SPINCOUNT=2000        # spin before sleep
export OMP_WAIT_POLICY=active     # active vs passive waiting
export OMP_DISPLAY_ENV=true       # print config at startup
9. 性能分析
# Score-P (compile with wrapper)
scorep gcc -fopenmp -o app app.c
export SCOREP_METRIC_MANAGER=1
scorep ./app
scorep-score -f scorep_*/profile.cubex

# TAU
tau_cc.sh -fopenmp -o app app.c
export TAU_TRACE=1
./app
pprof app profile.*
10. 陷阱

伪共享:线程修改相邻的缓存行。

// Bad: sum_array[tid] on same cache line
#pragma omp parallel
{
    int tid = omp_get_thread_num();
    sum_array[tid] += local_sum;  // pad to 64 bytes between elements
}

// Fix: padding
double sum_padded[MAX_THREADS][8];  // 8 doubles = 64 bytes

嵌套并行:

export OMP_MAX_ACTIVE_LEVELS=2
export OMP_NESTED=true   # deprecated; use MAX_ACTIVE_LEVELS

常见问题

症状原因修复方法
没有加速循环规模太小增加工作量;检查 if 子句阈值
归约结果错误非归约变量存在竞争使用 reduction 或 atomic
线程越多速度越慢伪共享对每线程数组进行填充
GPU 卸载失败没有目标设备检查 -foffload;运行 nvidia-smi
线程未绑定默认采用分散策略OMP_PROC_BIND=close
嵌套死锁过度订阅限制每个层级的 OMP_NUM_THREADS

相关技能

  • skills/hpc/mpi — 分布式内存的互补方案
  • skills/low-level-programming/cpu-cache-opt — 深入了解伪共享
  • skills/gpu/cuda — 替代 target 卸载的 GPU 编程方案
  • skills/profilers/intel-vtune-amd-uprof — 在 VTune 中分析 OpenMP 区域
  • skills/compilers/gcc — -fopenmp 标志
  • skills/allocators/numa-programming — NUMA 感知的线程绑定

评论

支持 Markdown