mpi について
mpiは、MPIプログラミングを扱うエージェント向けスキルです。通信パターン、ハイブリッド並列、ジョブ起動、デバッグを解説し、ノードやソケットをまたぐHPCアプリの開発・実行を支援します。
主な機能
- 01ポイントツーポイント通信と集合通信
- 02ノンブロッキング通信と処理の重畳
- 03サブコミュニケーターとMPI+OpenMP
- 04mpirunやスケジューラーによる起動
- 05MPI-IOと性能問題の調査
活用シーン
- 01ノード間の計算並列化
- 02行列分解やFFTの実装
- 03MPIプロセスとOpenMPスレッドの併用
- 04デッドロックの調査と並列ファイルI/O
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill mpiインストール後、Claude Code で/mpiを入力して読み込まれたか確認します。
詳細
MPI
目的
エージェントがMPI(メッセージパッシングインターフェース)プログラミングに取り組めるよう、ポイントツーポイント通信と集合通信、ノンブロッキング操作、サブコミュニケーター、MPI+OpenMPのハイブリッドパターン、mpirunによるプロセスの起動、デバッグ手法、MPI-IO、よくあるパフォーマンスの問題を説明します。
使用する場面
- 複数のノードまたはソケットに処理を並列化する場合
- 分散アルゴリズム(行列分解、FFT)を実装する場合
- MPIのプロセス並列化とOpenMPのスレッド並列化を組み合わせる場合
- Slurm/PBSと
mpirunを使ってHPCジョブを実行する場合 - デッドロックやメッセージの不一致をデバッグする場合
- MPI-IOで並列ファイルI/Oを行う場合
ワークフロー
1. 最小限のMPIプログラム
#include <mpi.h>
#include <stdio.h>
int main(int argc, char **argv) {
MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
printf("Hello from rank %d of %d\n", rank, size);
MPI_Finalize();
return 0;
}
mpicc -o hello hello.c
mpirun -np 4 ./hello
# or
mpiexec -n 4 ./hello
2. ポイントツーポイント通信
if (rank == 0) {
int data = 42;
MPI_Send(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
} else if (rank == 1) {
int recv;
MPI_Recv(&recv, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("rank 1 got %d\n", recv);
}
タグ付きメッセージでは、MPI_Recvのタグと送信元を一致させます。
3. 集合通信
int local = rank + 1;
int global_sum;
MPI_Allreduce(&local, &global_sum, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
// Broadcast
if (rank == 0) data = 100;
MPI_Bcast(&data, 1, MPI_INT, 0, MPI_COMM_WORLD);
// Scatter/Gather
MPI_Scatter(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Gather(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT, 0, MPI_COMM_WORLD);
| 集合通信 | 目的 |
|---|---|
MPI_Bcast | 1対全 |
MPI_Scatter | チャンクを分配する |
MPI_Gather | チャンクを集約する |
MPI_Allreduce | リデュースして結果をブロードキャストする |
MPI_Barrier | 同期 |
MPI_Alltoall | 全対全交換 |
4. ノンブロッキング通信
MPI_Request req;
MPI_Isend(buf, count, MPI_INT, dest, tag, MPI_COMM_WORLD, &req);
// overlap computation here
do_local_work();
MPI_Wait(&req, MPI_STATUS_IGNORE);
// Multiple requests
MPI_Request reqs[2];
MPI_Irecv(buf0, n, MPI_INT, 0, 0, comm, &reqs[0]);
MPI_Irecv(buf1, n, MPI_INT, 1, 0, comm, &reqs[1]);
MPI_Waitall(2, reqs, MPI_STATUSES_IGNORE);
通信と計算を重ねて、レイテンシーを隠します。
5. サブコミュニケーター
int color = rank / 4; // groups of 4
MPI_Comm subcomm;
MPI_Comm_split(MPI_COMM_WORLD, color, rank, &subcomm);
int subrank, subsize;
MPI_Comm_rank(subcomm, &subrank);
MPI_Comm_size(subcomm, &subsize);
MPI_Comm_free(&subcomm);
6. MPI + OpenMPのハイブリッド
#pragma omp parallel
{
int tid = omp_get_thread_num();
// thread-local work on rank's data partition
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Allreduce(...);
export OMP_NUM_THREADS=4
mpirun -np 8 --bind-to core ./hybrid_app
# 8 ranks × 4 threads = 32 cores
--map-by ppr:2:socketを使ってランクをソケットにバインドします。
7. ホストファイルを使った起動
# hostfile:
# node0 slots=4
# node1 slots=4
mpirun -np 8 --hostfile hosts.txt ./app
# Slurm integration
srun -n 64 ./app
# or
mpirun -np $SLURM_NTASKS ./app
# Debug: tag output by rank
mpirun -np 4 --tag-output ./app
# Sequential debug (one rank at a time)
mpirun -np 4 -gdb ./app
8. MPI-IO
#include <mpi.h>
MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, "output.dat",
MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
MPI_Offset offset = rank * chunk_size;
MPI_File_write_at(fh, offset, buf, count, MPI_DOUBLE, MPI_STATUS_IGNORE);
MPI_File_close(&fh);
パフォーマンスを向上させる集合I/O:
MPI_File_write_at_all(fh, offset, buf, count, MPI_DOUBLE, MPI_STATUS_IGNORE);
9. パフォーマンスの問題
Common bottlenecks
├── Load imbalance → dynamic scheduling (OpenMP) or redistribute MPI chunks
├── Serialization at rank 0 → tree-based reduce, parallel I/O
├── Excessive sync → replace Barrier with point-to-point where possible
├── Small messages → aggregate; use MPI_Pack or larger blocks
└── Alltoall on large process counts → consider MPI neighborhood collectives
# MPI profiling
mpiP # lightweight profiler
# or IPM, TAU MPI wrappers
よくある問題
| 症状 | 原因 | 修正方法 |
|---|---|---|
| MPI_Recvで停止する | タグまたは送信元の不一致 | Send/Recvの組み合わせを確認し、デバッグ時はMPI_ANY_TAGを使う |
| デッドロック | 循環待ち | 通信パターンの順序を変更するか、ノンブロッキング通信を使う |
| Allreduceの結果が正しくない | データ型またはカウントが誤っている | MPI_INTとMPI_DOUBLEのどちらを使うか確認する |
| スケーリングが悪い | Rank 0がボトルネックになっている | I/Oと集約を分散する |
MPI_ERR_TRUNCATE | 受信バッファーが小さすぎる | 送信数と受信数を一致させる |
| ハイブリッド実行時の過剰割り当て | スレッド数×ランク数が多すぎる | OMP_NUM_THREADS = cores/ranks |
関連スキル
skills/hpc/openmp— MPIランク内のスレッドレベルの並列化skills/hpc/rdma-verbs— MPIでの低レイテンシー相互接続skills/allocators/numa-programming— ランクをNUMAノードにバインドするskills/profilers/linux-perf— MPIランクのホットスポットをプロファイリングするskills/debuggers/gdb— 個々のMPIプロセスをデバッグするskills/compilers/gcc— MPIコンパイラーラッパーのフラグ
コメント
Markdown 対応