LoginSignup
1
1

More than 3 years have passed since last update.

C言語+MPIのtips(MPI_Scatterv)

Last updated at Posted at 2020-12-19

MPI_Scattervは「あるプロセスが持つデータを,任意に分割して,各々のプロセスに配分する関数」。
※MPI_Scatterは「あるプロセスが持つデータを,等分して,各々のプロセスに配分する関数」であったことに注意。

【目的】
あるプロセスに存在する一次元配列 send から適当な数(eachsz)の要素だけ取り出して、各々のプロセスにある一次元配列 recv に代入することでMPI_Scatterv の機能を知る。

【使用するもの】
open-mpi

【環境】

$ mpicc —version

Apple clang version 11.0.3 (clang-1103.0.32.29) 

Target: x86_64-apple-darwin19.6.0 

Thread model: posix 

InstalledDir: /Library/Developer/CommandLineTools/usr/bin

【方法】

Scatterv.c
#include<stdio.h>
#include<mpi.h>

int main(int argc, char **argv){
  int i;
  int my_rank, num_proc;
  int send[20];
  int recv[10];
  int eachsz[2] = {3,8};
  int place[2];

  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &num_proc);
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

  for(i=0;i<10;i++) recv[i] = -1;

  if(my_rank == 1){
        for(i=0;i<20;i++) send[i] = i;
        for(i=0;i<2;i++) place[i] = 10*i;
  }

  MPI_Scatterv(send, eachsz, place, MPI_INT, recv, eachsz[my_rank], MPI_INT, 1,MPI_COMM_WORLD);

  printf("myrank %d:", my_rank);
  for(i=0;i<10;i++) printf(" %2d",recv[i]);
  printf("\n");

MPI_Finalize();
return 0;
}

【結果】
mpicc コマンドでコンパイル、mpirun コマンドでプロセス数を2にして実行。

$ mpicc Scatterv.c
$ mpirun -np 2 ./a.out
myrank 0:  0  1  2 -1 -1 -1 -1 -1 -1 -1
myrank 1: 10 11 12 13 14 15 16 17 -1 -1

【考察(何が起きたのか)】
まずプロセス0と1でそれぞれ send[0]、send[1]、…、send[19] が生成される。
プロセス0と1でそれぞれ recv[0]、recv[1]、…、recv[9] が生成される。
プロセス0と1でそれぞれ eachsz[0](=3)、eachsz[1](=8) が生成される。
プロセス0と1でそれぞれ place[0]、place[1] が生成される。

それぞれのプロセスでのfor文で値が格納される。
at プロセス0 recv[0]=-1、 recv[1]=-1、…、recv[9]=-1
at プロセス1 recv[0]=-1、 recv[1]=-1、…、recv[9]=-1

at プロセス1 send[0]=0、send[1]=1、…、send[19] =19

at プロセス1 place[0]=0、place[1]=10

MPI_Scattervによって「send」から各プロセスに個数「eachsz」のデータが送られる。各プロセスに送られるデータの場所(配列のインデックス)は「place」。つまり、place[0]=0なのでsend[0]から数えてeachsz[0]個のデータ、place[1]=10なのでsend[10]から数えてeachsz[1]個のデータが送信される。
送るデータの型は整数(int)「MPI_INT」。各プロセスの「recv」は、それぞれ「eachsz[my_rank] 」個の要素を受け取る。つまり、プロセス0は3個(eachsz[0]=3)、プロセス1は8個(eachsz[1]=8)の要素を受け取る。受け取るデータの型は整数(int)「MPI_INT」。データはプロセス「1」から送信される。
よって
at プロセス0
recv[0](= プロセス1の send[0])=0、
recv[1](= プロセス1の send[1])=1、
recv[2](= プロセス1の send[2])=2
となる。さらに
at プロセス1
recv[0](= プロセス1の send[10])=10、
recv[1](= プロセス1の send[11])=11、
…、
recv[7](= プロセス1の send[17])=17
となる。

それぞれのプロセスで recv が表示されて終了。

【参考】

「mpi 並列プログラミング」と検索すると、より正確でより情報量の多い資料が見つかります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1