この関数は受信したエントリの数を返す(ここでもバイトではなく、それぞれのdatatype が示す型でのエントリの数を数える)。datatype引数は、status変数をセットした受信関数に 渡されたデータ型と一致しなければならない(後程、3.12.5節で、MPI GET COUNTがある特 定の状況でMPIUNDEFINED値を返す場合を考察する)。
根拠 メッセージ通信ライブラリによっては、入出力のcount、tag、source引数を使用す るものがある。つまりこれらの引数を、入ってくるメッセージの選択基準の指定と、受信 メッセージの実際のエンベロープ値の返却の両方で使用する。ステータスを示す異なった 引数を使用することにより、入出力引数を用いる場合に発生することの多いエラーを回避 することができる(例えばMPIANYTAG定数を受信側のタグとして使用する場合など。)。
ライブラリによっては、暗黙的に\最後の受信メッセージ"を用いる呼び出しを使用する ものがあるが、これはスレッド・セーフではない。
性能を向上させるために、datatyp e引数がMPI GET COUNTに渡される。メッセージ中 に含まれる要素の数を勘定せずにメッセージを受信することもあり、要素数の値は必要で ないことが多い。また、こうすることにより、同じ関数をMPI PROBEの呼び出し後に使 用することができる。(根拠の終わり)
全ての送受信関数で、 buf、count、datatype、source、dest、tag、comm、status引数 が、この節で説明したブロッキング関数MPI SEND、MPI RECVと同じ様に使用される。
3.3
データ型の一致とデータ変換
3.3.1 型一致規則
メッセージ転送を、次の3つのフェーズで構成されるものと考えることができる。
1. データが送信バッファから引き出され、メッセージが組立られる。
2. メッセージが送信元から受信側へ転送される。
3. 入ってくるメッセージからデータが取りだされ、分解されて受信バッファに入れられる。
この3つのフェーズで型一致を守らなければならない。送信バッファのそれぞれの変数の型 が、送信関数でのエントリで指定された型と一致しなければならない。また送信関数で指定され た型は、受信関数で指定された型と一致しなければならない。さらに、受信バッファのそれぞれ の変数の型も、受信関数のエントリで指定された型と一致しなければならない。これらの3つの 規則が守られていないプログラムは、間違いである。
型一致をもっと正確に定義するためには、ホスト言語の型と通信動作で指定した型との一 致、および送信側と受信側の型の一致という、2つの問題を扱う必要がある。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
送信と受信の型は、両方の関数の型の名前が同一であれば一致する(フェーズ2)。つまり
MPI INTEGERは、MPI INTEGERと一致し、MPI REALはMPI REALと一致するということ である。この規則には1つだけ例外があり、3.13節で説明したMPI PACKED型は他のどんな型 とも一致させることができる。
ホスト・プログラムの変数の型は、通信関数で使用されているデータ型名が、ホスト・プロ
グラム変数の基本型と対応する場合、その関数で指定した型と一致する。たとえば、型名MPI INTEGER を持つエントリは、INTEGER型のFortran言語変数と一致する。Fortran言語とC言語におけ
るこの対応を示す表が3.2.2節にある。この規則にも例外が2つある。型名MPI BYTEやMPI PACKED は、データ記憶領域の任意のバイトと対応するために使用されるものであり(バイトによるアド
レス指定可能マシンの場合)、このバイトを含む変数のデータ型とは関係ない。3.13に示すよう
に、MPI PACKED型は、明示的にパックするデータを送信したり、明示的にアンパックされる
データを受信したりするときに使用される。MPI BYTE型は、メモリ内の任意のバイトのバイ ナリ値を変更なしに転送するときに使用される。
以上をまとめると、型一致規則は以下の3つのカテゴリに分類される。
型の指定された値の通信(すなわちMPI BYTEデータ型以外を使用する場合)では、送信 側のプログラム、送信関数、受信関数、受信側のプログラムでの対応するエントリのデー タ型は、全て一致しなければならない。
型の指定されない値の通信(すなわちMPI BYTEデータ型を使用する場合) 、すなわち送 信側と受信側の両方がMPI BYTEデータ型を使用する場合では、送信側プログラムと受 信側プログラムでの、対応するエントリの型になんらの要件もなく、それらが同じである 必要もない。
MPI PACKEDが使用されている、パックされたデータを含む通信。
以下の例で、最初の2つの場合を説明する。
例 3.1 送信側と受信側が一致した型を指定する場合
CALL MPI_COMM_RANK(comm, rank, ierr)
IF(rank.EQ.0) THEN
CALL MPI_SEND(a(1), 10, MPI_REAL, 1, tag, comm, ierr)
ELSE
CALL MPI_RECV(b(1), 15, MPI_REAL, 0, tag, comm, status, ierr)
END IF
aとbの両方が、10以上の大きさの実数型配列の場合、このプログラムは正しい。(F
or-tran言語の場合、たとえばa(1)が10個の実数要素を持つ配列に記憶領域を共有させる
(equiv-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
3.3. データ型の一致とデータ変換 31
alenceされる)ことができる場合など、aとbのいずれかのサイズが10より小さくても、この プログラムを使用することは正しい時がある。)
例 3.2 送信側と受信側の型が一致しない場合
CALL MPI_COMM_RANK(comm, rank, ierr)
IF(rank.EQ.0) THEN
CALL MPI_SEND(a(1), 10, MPI_REAL, 1, tag, comm, ierr)
ELSE
CALL MPI_RECV(b(1), 40, MPI_BYTE, 0, tag, comm, status, ierr)
END IF
このプログラムは、送信側と受信側が一致するデータ型引数を指定しないため、エラーにな る。
例 3.3 送信側と受信側が型指定されない値での通信をした場合
CALL MPI_COMM_RANK(comm, rank, ierr)
IF(rank.EQ.0) THEN
CALL MPI_SEND(a(1), 40, MPI_BYTE, 1, tag, comm, ierr)
ELSE
CALL MPI_RECV(b(1), 60, MPI_BYTE, 0, tag, comm, status, ierr)
END IF
このプログラムは、aとbの型とサイズにかかわらず正しい(この結果がメモリ・アクセ スの制限を越えない場合)。
ユーザへのアドバイス MPIBYTE型のバッファがMPI SEND関数の引数として渡された 場合、MPI はbuf引数によって示されたアドレスから始まる、連続して格納されたデー タを送る。これを行うと、通常のユーザーが期待するものとデータ・レイアウトが違って いる場合、予期しない結果になることがある。たとえば、Fortran言語コンパイラの中に
は、CHARACTER型の変数を、文字の長さと、実際の文字列に対するポインタを含む構造
体として実装するものがある。このような環境では、MPIBYTE型を使用して、Fortran
言語のCHARACTER型の変数を送受信すると、文字列を転送したときの予想結果と違う結
果になることがある。このためユーザーに対しては、可能な限り型指定の通信を使用する ように奨める。(ユーザへのアドバイスの終わり)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
MPICHARACTER型
MPI CHARACTER型は、CHARACTER型のFortran言語変数に格納された文字列全体ではなく、
その変数の中の1文字と対応する。CHARACTER型Fortran言語の変数または部分文字列は、
文字の配列であるかのように転送される。これについては以下の例で説明する。
例 3.4 Fortran言語のCHARACTERの転送
CHARACTER*10 a
CHARACTER*10 b
CALL MPI_COMM_RANK(comm, rank, ierr)
IF(rank.EQ.0) THEN
CALL MPI_SEND(a, 5, MPI_CHARACTER, 1, tag, comm, ierr)
ELSE
CALL MPI_RECV(b(6:10), 5, MPI_CHARACTER, 0, tag, comm, status, ierr)
END IF
プロセス1における文字列bの最後の5文字が、プロセス0における文字列aの最初の5文 字で置換される。
根拠 もう1つの選択肢は、MPI CHARACTERを任意の長さの文字列と一致させること である。こうした場合には問題が発生する。
Fortran言語の文字変数は、一定の長さの文字列で、特殊な終端記号がない。文字を表現
するときの決まった規則はなく、またどのようにしてその長さを格納するかに関する規則 もない。コンパイラによっては、文字引数を一対の引数としてルーチンに渡すものもある。
この場合、1つには文字列のアドレスが含まれ、もう1つには文字列の長さが含まれる。
派生データ型で定義された型(3.12節)を含む通信バッファが、あるMPI 通信関数に渡さ れる場合を想定してみよう。もし、この通信バッファにCHARACTER型が含まれている場 合、これらの文字列の長さの情報がMPI ルーチンに渡されることはない。
この問題があるために、MPI 関数では、文字列の長さに関する明示的な情報を指定しなけ ればならない。MPI CHARACTER型に長さのパラメータを追加することはできるが、こ れはあまり便利ではなく、新たなデータ型を定義することによって同じ機能を実現するこ とができる。(根拠の終わり)
実装者へのアドバイス コンパイラによっては、Fortran言語のCHARACTER引数を、長 さと実際の文字列を示すポインタを持つ構造体として渡すものもある。このような環境で は、文字列に至るために、MPI 呼び出しでポインタの参照解決をおこなう必要がある。
(実装者へのアドバイスの終わり)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
3.3. データ型の一致とデータ変換 33
3.3.2 データ変換
MPI の目標の1つは、異機種環境で並列計算をサポートすることである。異機種環境で通信を 行うときは、データ変換が必要になる場合がある。ここでは以下の用語を使用する。
型変換 値のデータ型を変更すること。例えば、REALを丸めてINTEGERに変換すること。
表現変換 値の2進表現を変更すること。例えば、16進浮動小数からIEEE浮動小数に変換する こと。
型一致規則により、MPI 通信では型変換は伴わない。それに対して、ある型の表現形式が 異なるような環境の間でこの型のデータが転送される場合には、MPI 通信での表現変換が必要 になる。MPI では表現変換の規則を規定していない。そのような変換では、整数、論理、文字 としての値を維持することと、浮動小数としての値を、相手側のシステムで表現できる最も近い 値に変換することが必要である。
浮動小数変換の場合、オーバーフローやアンダーフローの例外が発生することもある。整数 や文字の変換でも、あるシステムで表現できる値が別のシステムで表現できないとき、例外が発 生することがある。表現変換のときに発生する例外は、結果的に通信時のエラーになる。エラー は、送信操作と受信操作のいずれか、またはその両方で発生する。
メッセージで送信されるデータが、型の指定されない値の場合(つまりMPI BYTE型)、
受信側に格納されるそのバイトの2進表現は、送信側でロードされるバイトの2進表現と同一で ある。送信側と受信側が同じ環境で動作していても、あるいは違う環境で動作していても、これ は真になる。表現変換は必要ない( MPI CHARACTER型やMPI CHAR型の値が転送されると きは、表現変換が発生し得ることに注意、例えばEBCDIC符号からASCII符号への変換 )。
すべてのプロセスが同じ環境で動作するような、同機種環境でMPI プログラムが実行され るとき、変換を行う必要はない。
3.1から3.3までの3つの例題を考えてみる。aとbが10以上のサイズを持つREALの配列 である場合、最初のプログラムは正しい。送信側と受信側が異なる環境で実行する場合、送信 バッファから取り出される10個の実数値が、受信バッファに格納される前に、受信側の実数表 現に変換される。送信バッファから取り出される実数の要素の数が、受信バッファに格納される 実数の要素の数と等しくても、格納されるバイトの数はロードされるバイトの数と同じである必 要はない。例えば、送信側が実数に4バイトの表現を使用し、受信側が8バイトの表現を使用す ることもある。
2番目のプログラムはエラーになり、その動作は保証されない。
3番目のプログラムは正しい。送信側と受信側が異なる環境で動作しても、送信バッファか らロードされるのとまったく同じ40バイトの列が受信バッファに格納される。送られるメッセー ジは、受信されるメッセージとまったく同じ長さ(バイトで)と同じ2進表現を持っている。a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47