並列プログラミング言語XcalableMP 実習2
Coarray機能について

中尾昌広

目次
Coarray機能について（復習）【演習1】スカラ変数のPut/Get（実行のみ）【演習2】配列のPut/Get（実行のみ）【演習3】行列積の作成（プログラミング演習+実行）Coarray機能（XMP/Fortran）
ローカルデータに対する片側通信（Get/Put）の記述

image2が持つb(3:5)のデータをimage1がa(1:3)にGetする
integer :: a(10)integer :: b(10)[*] ! b is a coarray

image 1

image 2

a(10)

a(10)

b(10)

b[10]

:
if(this_image() == 1) thena(1:3) = b(3:5)[2]! Get[]はイメージ番号を表す（Fortranは1-origin，Cは0-origin）

35

Coarray機能（XMP/C）
ローカルデータに対する片側通信（Get/Put）の記述

image1が持つb[3:3]のデータをimage0がa[0:3]にGetする

image 0image 1if(xmpc_this_image() == 0)a[0:3] = b[3:3]:[1];// Get

a[10]

a[10]

コロンの後の[]はノード番号を表す

b[10]

b[10]

int a[10];int b[10]:[*]; // b is a coarray:

配列名[開始要素：転送要素数]35Get/Put in XMP/FortranGet

image 2

image 1

integer :: a(10), b(10)[*]:if(this_image() == 1) thena(1:3) = b(3:5)[2]
! Get

a[10]
b[10]

Put（一般にGetよりも高速）

12

a[10]
b[10]

35

integer :: a(10)[*], b(10):if(this_image() == 2) thena(1:3)[1] = b(3:5)
! Put

a[10]

a[10]

b[10]

b[10]

35

Get/Put in XMP/C
Get

image 1

image 0int a[10], b[10]:[*];:
if(xmpc_this_image() == 0)a[0:3] = b[3:3]:[1];// Get

a[10]
b[10]

Put（一般にGetよりも高速）

1
2

a[10]
b[10]

35

int a[10]:[*], b[10];:if(xmpc_this_image() == 1)a[0:3]:[0] = b[3:3];// Put

a[10]

a[10]

b[10]

b[10]

35

同期：sync allXMP/Fortranimage 0image 1sync all

XMP/C
void xmp_sync_all(int *status)

Put
sync_allsync_all

今までに発行した全片側通信が終了し、かつバリア同期を行う

実習1
スカラ変数のPut/Get
xmpcc coarray̲scalar.c or xmpf90 coarray̲scalar.f90
2プロセスで実行して下さい

XMP/Fortran

XMP/C

if(this_image() == 1) thentmp = val[2] ! Getval[2] = val ! Put
end ifsync allif(xmpc_this_image() == 0){tmp = val:[1]; // Get
val:[1] = val; // Put}xmp_sync_all(NULL);

実習1（結果：XMP/Fortran）
sync allif(this_image() == 1) thentmp = val:[2]; // Get
val:[2] = val; // Put
end ifsync allimage 1val = 1
tmp = 0val = 2
tmp = 0barrierval:[2]をtmpにGet

出力結果：[START] My image is 1, val = 1 tmp = 0[START] My image is 2, val = 2 tmp = 0
[END]
[END]

image 2

My image is 1, val = 1 tmp = 2
My image is 2, val = 1 tmp = 0

tmp = 2
valをval:[2]にPutval = 1
sync_all実習1（結果：XMP/C）
xmp_sync_all(NULL);
if(xmpc_this_image() == 0){
tmp = val:[1]; // Get
val:[1] = val; // Put}xmp_sync_all(NULL);

image 0val = 1
tmp = 0val = 2
tmp = 0barrierval:[1]をtmpにGet

出力結果：[START] My image is 0, val = 1 tmp = 0[START] My image is 1, val = 2 tmp = 0
[END]
[END]

image 1

My image is 0, val = 1 tmp = 2
My image is 1, val = 1 tmp = 0

tmp = 2
valをval:[1]にPutval = 1sync_all

実習2
配列のPut/Get
xmpcc coarray̲vector.c or xmpf90 coarray̲vector.f90
2プロセスで実行して下さい
配列の初期値は下記の通り（image番号はXMP/C）

image 0image 1a[10] = {0, 1, .., 9};b[10] = {0, 1, .., 9};c[10][10] = {{0, 1, .., 9},{10, 11, .., 19},...
{90, 91, .., 99}};a[10] = {10, 11, .., 19};b[10] = {10, 11, .., 19};c[10][10] = {{100, 101, .., 109},{110, 111, .., 119},...
{190, 191, .., 199}};

実習2（結果1）
XMP/Fortranif(this_image() == 1) thena(1:3) = a(6:8)[2] ! Get
end if
XMP/C
if(xmpc_this_image() == 0){a[0:3] = a[5:3]:[1]; // Get}a[0] = 15a[1] = 16a[2] = 17a[3] = 3a[4] = 4a[5] = 5a[6] = 6a[7] = 7a[8] = 8a[9] = 9

実習2（結果2）
XMP/Fortranif(this_image() == 1) thenb(1:10:2) = b(1:10:2)[2]
end if! GetXMP/C
if(xmpc_this_image() == 0){b[0:5:2] = b[0:5:2]:[1];// Get}b[0] = 10b[1] = 1b[2] = 12b[3] = 3b[4] = 14b[5] = 5b[6] = 16b[7] = 7b[8] = 18
b[9] = 9

実習2（結果3）
XMP/Fortran

XMP/Cif(this_image() == 1) thenc(1:5,1:5)[2] = c(1:5,1:5) // Putend ifif(xmpc_this_image() == 0){c[0:5][0:5]:[2] = c[0:5][0:5]; // Put}

0 1 2 3 4 105 106 107 108 109
10 11 12 13 14 115 116 117 118 119
20 21 22 23 24 125 126 127 128 129
30 31 32 33 34 135 136 137 138 139
40 41 42 43 44 145 146 147 148 149
150 151 152 153 154 155 156 157 158 159160 161 162 163 164 165 166 167 168 169
170 171 172 173 174 175 176 177 178 179
180 181 182 183 184 185 186 187 188 189
190 191 192 193 194 195 196 197 198 199

行列積（演習）N x N の行列積
C=AxB

並列化の方針
4ノードに分割して実行する

for(i=0;i<N;i++)for(j=0;j<N;j++)for(k=0;k<N;k++)c[i][k] += a[i][j] * b[j][k];1つのimageがAとBのデータのすべてを持っている
最終的な解は1つのimageが出力する
Coarrayを用いてデータの転送を行う

発展課題（今回はしません）
Cannonとfoxのアルゴリズム• http://www.kata-lab.itc.u-tokyo.ac.jp/OpenLecture/SP20101221.pdf
第三回 XMP Challenge• http://xcalablemp.org/ja/challenge-3rd.html

行列積（演習）
部分行列に分けて計算する（行と列に2分割ずつ。Nは偶数）

C00

C01

A00

A01

=C10C11B00

B01

B10B11×A10A11XMP/CC00 = A00
C01 = A00
C10 = A10
C11 = A10× B00 + A01 × B10× B01 + A01 × B11× B00 + A11 × B10× B01 + A11 × B11

XMP/Fortranimage 0, image 1
image 1, image 2
image 2, image 3
image 3, image 4が担当する

行列積（演習）
matmul.c or matmul.f90を元に作成してください。
実装箇所は、下記の赤の部分のみです。
1. （比較のための）逐次の行列積
2. 配列の初期化（関数init̲dmat()）
3. Coarrayを用いた配列の転送（関数move̲data()）
部分配列AとBを、1つのimageから他の各imageに転送する
XMP/Cにおいてimage 1が必要なのは、A[0:N/2][0:N]とB[0:N][N/2:N/2]
XMP/Fortranにおいてimage 2が必要なのは、A(1:N,1:N/2)とB(N/2+1:N,1:N)
4. 行列積の実行（C = A x B，関数mul̲dmat()）
5. 各ノードからCの結果を集める（関数gather̲data()）
6. 妥当性の検証（関数verify()）
verifyの値が逐次版と同じ結果ならOK，計測時間を較べてみて下さい