2002/4/8 MPI test
既に GbE NIC (Planex GE1000TC) がついて Linux で普通に動いているので、 別に何も問題はなかろうと思って前に書いた MPI send/receive でピンポンす るプログラムを動かしてみる。
と、、、なんとピークで 8MB/s しかでない。で、前に元平木研の下見淳一郎様(どうもありがとうございます)からいただいた TCP/IP ソケットを生に使うプログラムで測ると 40 MB/s でる。
なにが悪いのかと NIC を Netgear GA620T に換えると、 TCP/IP 78MB/s, MPI 43 MB/s という素晴らしい性能(しかし MPI の性能低下が大きい、、、)がで る。台坂君が FreeBSD で MPICH を動かした時には GN1000T で30MB/s くらい はでているので、 software の問題であることは間違いない。
2002/4/9 TCP library
問題は対応をどうするかである。
ぱっと思いつくのは
というわけで、ソケットで通信というのをやってみることにする。といっても
そんなことはやったことがないので、とりあえず下見様のプログラムを見て何
をすればいいのか考える、というか単にやってることをコピーする。
どうも、 TCP/IP での通信には「クライアント」と「サーバー」があるらしい
ということがわかる。これは一度繋がれば別になにか非対称性があるわけではなく、つながるまでの操作の違いらしい。
クライアントの側がすることは
サーバ側は
原理は、サーバ側は名前(ホスト名とポート番号)によって指定された名前で手
を開いて接続要求があるのを待つ。で、クライアント側はその名前で connect
を要求する。両方がうまく手をつなげると、 connect と accept のそれぞれ
が抜けて戻ってくるということらしい。
複数の相手とつなぐのはどうすればいいかというと、クライアント側はもちろ
ん上の処理を繰り返すだけである。サーバ側は listen までやったところで待
ち状態にははいっていて、ここで複数の要求を受付られる。 accept を何回か
よべばそれが適当な順にでてくるらしい。
データのやりとりは MPI を使うより実は簡単で、送るほうは send, 受け取る
ほうは recv system call を使うだけ。どちらも、転送途中で勝手に帰ってく
ることがあるみたいなので残りをちゃんと転送するループを書く必要があるけ
ど、まあそれだけ。
MPI で既につながっているもの同士の接続を考える。
接続するルーチンと通信するルーチンは分離する。これは、接続についてはちょっ
とややこしい問題があるから。プロセッサ 0, 1 が同時にプロセッサ 2 に接
続要求して、 2 は 0 からくるのを待つといった状況が起きると処理が面倒な
ので、そういう競合は起きないということをアプリケーション側で保証するこ
とにする。 具体的には MPI_barrier とかでなんとかする。
API としては、以下の2つの関数を準備することにする。
と、とりあえずこんなところか。これで実装してみよう。
というわけで実装してみた。一応3ノードとかでも通信はできる。速度は、 GN1000TC の場合に
まあ、とにかく GbE のカードでは上ので動くみたいなので、とりあえずこれを使うことにしよう。
2002/4/24 TCP library/GAMMA 再び?
NS83820 ベースの GbE NIC はこれまでの GbE NIC と違って非インテリジェン
トである、つまり、ボード上に CPU をもたない。 DMA チェイニングをする単
純なハードウェアシーケンサがあるだけである。これはもちろんメインの CPU を
オフロードして複雑なパケットが飛び交う時のトータルのスループットを上げ
るという観点からはマイナスだが、MPI とかで point-to-point の通信さえ速
くなればいいとかオーバーヘッドを小さくしたいとかいう観点からすればむし
ろありがたい。実際、 GAMMA のページをみると GA620に比べて 621 ではレイ
テンシが 32us から 8.5us (!!!) へと 1/4 近く短縮されている。この 8.5us
という数字は、 PCI バスのアクセスレイテンシだけでも 1 us 程度あること
を考えれば真に驚異的な数字である。
GAMMA がまともに動くならこっち使うのが正解だよな。かなり驚異というよりは脅威的な速度がでるし、、、(というわけでまたはまるのである)
それはいいんだが負荷を思い切りかけて計算すると g6host12 が落ちる、、、これは GA7DXR に 1.5GB メモリを積んだ怖い機械なので、とりあえず K7S6A 1GB に交換。
2002/4/25 TCP library/GAMMA 再びだめ
Planex のカードをいきなり GA621 であると認識したので、テスト用の2台に
のせてみる。手順は上と全然変わらない。動かしてみると例によって動かない。
USE_JUMBO_FRAME を消すと動く。で、速度は大変素晴らしい。レイテンシ
30us、スループット 80MB/s くらいでる。
ということで、0号クラスタに入れることにする。まず2台入れる。 GAMMA は
基本的には専用の NIC を必要とするので、100BT のカードを別に付ける。こ
れはその辺に転がっいた Tulip 互換を付ける。で、2枚で動かしてみると特に
文句はいわないで動く。で、4台にしてみる。これも OK。
ここで全部にいれた。すると、、、、動かない。というか、全部に設定しても
一度に4台以上でジョブを起動すると死んでしまう。これはちょっと原因が分
からない。考えられる一つは、スイッチをカスケードしていると動かないので
はないかということ。割合豪快な作りみたいなのでまあそういうこともあるか
も。
ということで、あんまり考えてもしょうがないので元に戻す。といっても
100BT のカードは折角つけたのでそのままにしておく。
まあ、 TCP/IP でもレイテンシは長いとはいえスループットでは最高で
60MB/s くらいでるので、満足するべきとはいえる。 32bit/33MHz の PCI バ
スでこれだけでれば立派なものである。なお、 RTL8139 のカードは依然とし
てたたっていて、2.4.17 についてくるこれ用のドライバは余計なことに
NS83820 も認識したがる。この動きもなんか不思議で、 RTL8139 なチップが
のった NIC と NS83820 がのった NIC が両方あるとついでに 83820 も認識
してしまうみたい。認識されてしまうと gigabit にならないので(なってたか
もしれない。そういえばチェックしてないや)、ドライバをはずしてカーネル再構築した。
2002/8/16 メモ
まあ、とりあえず半年くらいほぼ安定運用できてるから、ケースなしでも十分使えるということですわね。
といったところであろう。時間的なことを考えるとおそらく最後の選択枝が一番速い。とにかく MPICH を使うとどんなカードでもかなり遅くなるので、代替案があること自体は悪くないしね。
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror_and_exit ("socket");
}
if (connect (sock, (struct sockaddr*) &sai, sizeof (sai)) < 0) {
perror_and_exit ("connect");
}
return sock;
}
みたいに、まず socket を呼んで、次に connect を呼ぶ。
s = socket (AF_INET, SOCK_STREAM, 0);
setsockopt (s, SOL_SOCKET, SO_REUSEADDR,
(void*) &val, sizeof (val));
bind (s, (struct sockaddr*) &sai, sizeof (sai));
listen (s, SOMAXCONN);
cs = accept (s, (struct sockaddr*) &csai, &len);
という具合になんだか難しいことをする。
int tcp_request_connection_by_MPIname(int othermpiid,
int direction)
direction は 0 ならサーバ、1なら(非 0 なら) クライアント。
リターンコードは 0 なら成功、 それ以外なら失敗。
int tcp_transfer_data_by_MPIname(int othermpiid,
int direction,
int length,
void* message_buffer)
direction は 0 なら受け取り、1なら(非 0 なら)送り出し。
received size = 1 count = 2000
size, count = 1 2000 wall clock time = 0.848137 0.037730 MB/s
size, count = 1 2000 wall clock time = 0.800074 0.039996 MB/s
received size = 2 count = 2000
size, count = 2 2000 wall clock time = 0.863618 0.074107 MB/s
size, count = 2 2000 wall clock time = 0.799940 0.080006 MB/s
received size = 4 count = 2000
size, count = 4 2000 wall clock time = 0.882713 0.145007 MB/s
size, count = 4 2000 wall clock time = 0.800093 0.159981 MB/s
received size = 8 count = 2000
size, count = 8 2000 wall clock time = 0.844426 0.303165 MB/s
size, count = 8 2000 wall clock time = 0.800074 0.319970 MB/s
received size = 16 count = 2000
size, count = 16 2000 wall clock time = 1.176345 0.435246 MB/s
size, count = 16 2000 wall clock time = 0.799951 0.640039 MB/s
received size = 32 count = 2000
size, count = 32 2000 wall clock time = 1.417380 0.722460 MB/s
size, count = 32 2000 wall clock time = 0.799979 1.280034 MB/s
received size = 64 count = 2000
size, count = 64 2000 wall clock time = 1.562601 1.310635 MB/s
size, count = 64 2000 wall clock time = 0.799963 2.560118 MB/s
received size = 128 count = 2000
size, count = 128 2000 wall clock time = 1.288446 3.179023 MB/s
size, count = 128 2000 wall clock time = 0.800653 5.115824 MB/s
received size = 256 count = 2000
size, count = 256 2000 wall clock time = 1.633381 5.015364 MB/s
size, count = 256 2000 wall clock time = 1.512344 5.416757 MB/s
received size = 512 count = 1953
size, count = 512 1953 wall clock time = 1.897617 8.431088 MB/s
size, count = 512 1953 wall clock time = 1.566108 10.215755 MB/s
received size = 1024 count = 976
size, count = 1024 976 wall clock time = 3.064925 5.217349 MB/s
size, count = 1024 976 wall clock time = 0.783628 20.406091 MB/s
received size = 2048 count = 488
size, count = 2048 488 wall clock time = 2.794157 5.722937 MB/s
size, count = 2048 488 wall clock time = 0.407762 39.215974 MB/s
received size = 4096 count = 244
size, count = 4096 244 wall clock time = 2.972820 5.378995 MB/s
size, count = 4096 244 wall clock time = 0.439282 36.402093 MB/s
received size = 8192 count = 122
size, count = 8192 122 wall clock time = 3.212721 4.977334 MB/s
size, count = 8192 122 wall clock time = 0.441824 36.192656 MB/s
received size = 16384 count = 61
size, count = 16384 61 wall clock time = 3.148252 5.079258 MB/s
size, count = 16384 61 wall clock time = 0.475721 33.613786 MB/s
received size = 32768 count = 30
size, count = 32768 30 wall clock time = 3.008371 5.228291 MB/s
size, count = 32768 30 wall clock time = 0.461200 34.103729 MB/s
received size = 65536 count = 15
size, count = 65536 15 wall clock time = 2.847520 5.523628 MB/s
size, count = 65536 15 wall clock time = 0.423700 37.122115 MB/s
メッセージサイズが同じので上の数値が MPICH、下が TCP/IPを使ったもの。
なかなかお話にならないほどの速度差があることがわかる。Netgear GA620Tだと
received size = 1 count = 2000
size, count = 1 2000 wall clock time = 0.588689 0.054358 MB/s
size, count = 1 2000 wall clock time = 0.472337 0.067748 MB/s
received size = 2 count = 2000
size, count = 2 2000 wall clock time = 0.566266 0.113021 MB/s
size, count = 2 2000 wall clock time = 0.472180 0.135542 MB/s
received size = 4 count = 2000
size, count = 4 2000 wall clock time = 0.584678 0.218924 MB/s
size, count = 4 2000 wall clock time = 0.469380 0.272700 MB/s
received size = 8 count = 2000
size, count = 8 2000 wall clock time = 0.591749 0.432616 MB/s
size, count = 8 2000 wall clock time = 0.418707 0.611406 MB/s
received size = 16 count = 2000
size, count = 16 2000 wall clock time = 0.631375 0.810929 MB/s
size, count = 16 2000 wall clock time = 0.471669 1.085507 MB/s
received size = 32 count = 2000
size, count = 32 2000 wall clock time = 0.722451 1.417397 MB/s
size, count = 32 2000 wall clock time = 0.503575 2.033461 MB/s
received size = 64 count = 2000
size, count = 64 2000 wall clock time = 0.538864 3.800588 MB/s
size, count = 64 2000 wall clock time = 0.566205 3.617064 MB/s
received size = 128 count = 2000
size, count = 128 2000 wall clock time = 0.715044 5.728319 MB/s
size, count = 128 2000 wall clock time = 0.470771 8.700621 MB/s
received size = 256 count = 2000
size, count = 256 2000 wall clock time = 0.767253 10.677052 MB/s
size, count = 256 2000 wall clock time = 0.707802 11.573858 MB/s
received size = 512 count = 1953
size, count = 512 1953 wall clock time = 0.953578 16.777837 MB/s
size, count = 512 1953 wall clock time = 0.739233 21.642670 MB/s
received size = 1024 count = 976
size, count = 1024 976 wall clock time = 0.580449 27.548991 MB/s
size, count = 1024 976 wall clock time = 0.563545 28.375345 MB/s
received size = 2048 count = 488
size, count = 2048 488 wall clock time = 0.445633 35.883303 MB/s
size, count = 2048 488 wall clock time = 0.364249 43.900694 MB/s
received size = 4096 count = 244
size, count = 4096 244 wall clock time = 0.403437 39.636384 MB/s
size, count = 4096 244 wall clock time = 0.299399 53.409611 MB/s
received size = 8192 count = 122
size, count = 8192 122 wall clock time = 0.378661 42.229815 MB/s
size, count = 8192 122 wall clock time = 0.273780 58.407422 MB/s
received size = 16384 count = 61
size, count = 16384 61 wall clock time = 0.398546 40.122806 MB/s
size, count = 16384 61 wall clock time = 0.238212 67.128373 MB/s
received size = 32768 count = 30
size, count = 32768 30 wall clock time = 0.377368 41.679846 MB/s
size, count = 32768 30 wall clock time = 0.217963 72.161972 MB/s
received size = 65536 count = 15
size, count = 65536 15 wall clock time = 0.366703 42.892041 MB/s
size, count = 65536 15 wall clock time = 0.211039 74.529542 MB/s
なお、 fast ether のカードをつけた機械では size=256 辺りでハングした。なんか変なことをしているのかも。
と、それはいいんだけど、久しぶりにGAMMA(どんなものかについては牧野が昔書いたメモを参照)をみてみると、いつのまにか Linux Kernel 2.4.16 対応になっている上、Netgear GA621 対応になっているではないか。 GA621 はありがちな NS 83820 を使ったボードで、 83820 はシングルチップで PCI と MIIが実現されていて後は物理層だけで GbE NIC を実現できるしろものなので 83820 を使ったボードであれば (device vendor ID とかの認識を調整すれば)うごきそうなものである。