mcpField
O
openmp

openmp

github.com/mohitmishra786開発269297 回インストール18 週間前に更新
リポジトリ

openmp について

openmpは、C、C++、FortranでOpenMPの共有メモリ並列処理を扱うエージェント向けスキルです。CPUループ、タスク、GPUオフロード、調整、プロファイリング、正確性やスケーリングの問題を解説します。

主な機能

  1. 01ループ並列化とスケジューリング
  2. 02リダクションとデータ共有属性
  3. 03SIMDとタスク並列処理
  4. 04OpenMPによるGPUオフロード
  5. 05スレッド調整とプロファイリング
  6. 06競合と偽共有の診断

活用シーン

  1. 01マルチコアCPUのループ並列化
  2. 02不規則な処理をタスクで並列化
  3. 03OpenMP target指示句によるGPUオフロード
  4. 04スケーリングやスレッド設定の問題診断

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/openmpを入力して読み込まれたか確認します。

詳細

OpenMP

目的

スケジューリング句を指定した #pragma omp parallel for、リダクション、データ共有属性、SIMD ヒント、タスク並列処理、OpenMP 5.x の GPU target オフロード、よくある落とし穴(フォルスシェアリング、データ競合)、環境変数によるチューニング、Score-P または TAU を使ったプロファイリングを通じて、OpenMP の共有メモリー並列処理をエージェントに案内します。

使用する場面

  • マルチコア 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. schedule 句
#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];

コンパイラーの SIMD サポートを使用するには、-fopenmp-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 オフロード、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 を考慮したスレッドバインド

コメント