Open-MXは一言でいえば TCP/IPの代わりに使う通信protocolです。 主に MPI (Message Passing Interface) という、並列計算用の通信libraryで利用します。
Open-MX FAQから "What is Open-MX?"を引用してみます。
What is Open-MX?
Open-MX is a software implementation of Myricom's Myrinet Express protocol. It aims at providing high-performance message passing over any generic Ethernet hardware.
Open-MX implements the capabilities of the MX firmware (running in Myri-10G NICs) as a driver in the Linux kernel. A user-space library exposes the MX interface to legacy applications.Open-MXは、Myricom社の Myrinet Express protocol(MX protocol)をsoftwareで実装したもので、 Myricom製でない一般のethernetでも高性能な通信を行えるようにすることを 目的としています。
Myricom社がMyri-10G NICに firmwareとして実装しているものを、Open-MXでは代わりに Linux kernel driverとして実装しています。 また、user空間でもMyricom MX互換を提供するので、これまでMyrinet MX用として 書かれたMPICHなどのapplicationをそのまま使うことができます。
(一部補足しながら意訳してみた)
Myrinetを知らないと上記の説明が何のことかさっぱりわからないと 思いますので、ちょっとだけ補足します。
MyrinetはPC clusterを組む際の通信手段として割とよく使われているもので、
並列計算をするという目的に合わせて、低遅延で通信できることを
大きな特徴としています。
Myrinetは、Myrinet →Myrinet 2000→Myrinet XP→
Myrinet 2XP→Myri-10Gと数世代に渡って進化してきました(たぶん)。
Myri-10G以前は、Myrinet専用の物理層を用いていたため、専用の光ファイバや
switchを必要としましたが、Miri-10Gから物理層が10Gbit Ethernet
と互換になりました。
ただし、Ethernet互換と言っても通信protocolとしてTCP/IPを使うと、
PC clusterで要求される低遅延を満足できないため、Myri-10Gでは
TCP/IPだけでなく、専用のMX procotolをEthernetで使えるようにしています。
ここまで読めば、Open-MXが何をしたいかわかるでしょうか。
Myri-10GがEthernetの物理層で低遅延通信できるなら、
Myricom以外のNICでもTCP/IPの代わりにMX protocolで通信すれば
そこそこ低遅延になるだろう、ということです。
ただ、勘違いしてほしくないのですが、TCP/IPの代わりにOpen-MXを使うことで
遅延は改善されますが、Myrinet並の遅延にまでは改善されません。
専用品はやっぱり速いのです。
はっきり言って、Gigabit Ethernet(10Gbitじゃなくて1Gbitね)で PC Clusterを組んでいる人向けでしょう。 10GbEを買える人はあえてOpen-MXを使わなくても、Myrinetとか InfinibandとかQsNetを買えば良いのです。 (2009年夏時点。10GbEが安くなれば10GbE+Open-MXも良いでしょう)
Open-MXのうれしいところは、安価なGbEでPC Clusterを組む際に、 TCP/IPの代わりにOpen-MXを使うだけで遅延をかなり改善できることです。
Ethernetで使える低遅延通信というと、Open-MX以外に GAMMAが有名です。 TCP/IP、GAMMA、Open-MXを比較してみましょう。
こうやって比べてみると、Open-MXはTCP/IPとGAMMAの中間の性格を 持っていることが分かると思います。 GAMMAを使える環境を用意できるのであれば、GAMMAの性能は魅力的です。 でも、今あるものを使ってなるべく良い性能を出したいと思ったとき、 Open-MXの性格は非常に魅力的に見えると思います。
まずは、Open-MXのsiteから、 open-mx-1.2.0.tar.gz(2009年12月時点の最新)を取ってきます。
Install作業自体は簡単で、よくある"./configure; make; make install"の 3 stepでinstallできます。 ただ、ちょっとクセがあるので、何点か注意します。
configureは特に気にせず"./configure"だけでも良いのですが、
1つ注意すべきは標準でMTUが9000byteになっている点です。
9000byteのJumbo-frameが使える環境であればそのままで構いません。
しかし、次のような場合にはMTUを手動で指定する必要があります。
こういった場合は、"--with-mtu=1500"などを指定します。
また、Myri-10Gと接続することがなければ(大抵の人は接続しないと思う)、
"--disable-mx-wire"を指定しておきましょう。
さらに、Big-endianとLittle-endianの混在がなければ
"--disable-endian"も指定しましょう。
(代表的なところでは、IntelやAMDのCPUがLittle-endian、IBMのPowerが
Big-endianです。PPC-LinuxやPlaystation3 LinuxとIntel PC
で通信することがあるなら、--enable-endianにしてください。)
これらの2つのoptionを指定するとわずかに性能が上がるようです。
私は、以下のように./configureしています。
# ./configure --prefix=/usr --disable-mx-wire --disable-endian --with-mtu=1500
configureできたら、"make"します。makeは特に問題なくできると思います。
"make install"すると、あまり一般的でない場所にいくつかの fileがinstallされてしまいます。 あまり気分が良くないので、いくつかのfileについて一般的な場所に移動します。
私の場合、上記のようにinstall先を変更するpatch ( open-mx-1.2.0_install.patch ) を書きました。 このpatchを使う場合は、configureする前にpatchを当ててください。
それから、たぶんbugだと思いますが、64bit環境ではlibraryが/usr/lib6464に installされます。これでは困るので、以下のようにしてください。
# make libdirsuffix= install
上記のpatchを当てたRPMを作りました。必要な方はどうぞ。→ open-mx-1.2.0-1.src.rpm
Open-MXの設定は非常に単純で、使うNICを指定するだけです。 上記のinstall先変更patchを当てていれば、/etc/open-mx/open-mx.confに雛形が あるので、次のように1箇所だけ書き加えます。
# Open-MX configuration # This file is sourced by the omx_init startup script # (or by /etc/init.d/open-mx once installed with omx_local_install) # The following variables may be overwritten by passing them # in the environment when running the omx_init startup script. # If unset or null, they will be overwritten by default values. # Which interface to acquire for Open-MX at startup? # "all" loads all available interfaces (default) # "eth1,eth3" loads eth1 and eth3 # " " loads none of them OMX_IFACES=eth0 # (used to be IFACES prior to Open-MX 1.1) # Additional open-mx module parameters OMX_MODULE_PARAMS= # Additional open-mx module dependencies (useful if modinfo is missing) OMX_MODULE_DEPENDS= # Additional fma command-line parameters (-D for debug, ...) OMX_FMA_PARAMS= # Additional fma startup timeout in seconds (5 by default) OMX_FMA_START_TIMEOUT=
上記の設定をした後、"/etc/inet.d/open-mx start" を走らせてみてください。 MTUは、configureするときに指定したMTUと合わせます。 正しくinstallできていれば、以下のような表示が出るはずです。
# ifconfig eth0 up mtu 1500 # /etc/init.d/open-mx start Loading Open-MX driver (with ifnames=eth0 ) Creating device node files if necessary... udev rules found (UDEV_RULES_FILE=/etc/udev/rules.d//45-open-mx.rules), assuming udev manages device files, unless a file is missing. crw-rw-rw- 1 root root 10, 59 Jul 29 00:01 /dev/open-mx crw-rw---- 1 root root 10, 60 Jul 29 00:01 /dev/open-mx-raw Starting the dynamic peer discovery (omxoed ) Now managing 1 NICs... Started as pid=10840 Found 1 boards (32 max) supporting 32 endpoints each: pc1:0 (board #0 name eth0 addr 00:11:22:33:44:55) #
続いて、他の機械を認識できているか確認します。
同じEthernet switchに繋がった(直結でもいいけど)2台の機械で、上記のように
"open-mx start"を走らせておいてください。
ここでは、2台の機械をpc1とpc2とします。
準備ができたら、双方の機械で"omx_info"を走らせてみてください。
以下のように2台の機械が表示されれば正常に動いています。
$ omx_info Open-MX version 1.1.903 build: root@emu:/usr/src/rpm/BUILD/open-mx-1.2.0 Thu Dec 24 01:47:48 JST 2009 Found 1 boards (32 max) supporting 32 endpoints each: pc1:0 (board #0 name eth0 addr 00:11:22:33:44:55) managed by driver 'e1000e' Peer table is ready, mapper is 00:11:22:33:44:55 ================================================ 0) 00:11:22:33:44:55 pc1:0 1) 00:12:34:56:78:9a pc2:0 $
最後に、双方の機械でpacketを送り合ってみます。簡単なbenchmark も兼ねることができるので、"omx_perf"を走らせてみましょう。
pc2で
$ omx_perf Successfully open endpoint 0 for hostname 'pc2:0' iface 'eth0' Starting receiver... $
pc1で
$ omx_perf -d pc2:0 Successfully open any endpoint for hostname 'pc1:0' iface 'eth0' Starting sender to 'pc2:0'... length 0: 16.605 us 0.00 MB/s 0.00 MiB/s length 1: 14.964 us 0.07 MB/s 0.06 MiB/s length 2: 15.013 us 0.13 MB/s 0.13 MiB/s length 4: 14.908 us 0.27 MB/s 0.26 MiB/s length 8: 15.015 us 0.53 MB/s 0.51 MiB/s length 16: 14.992 us 1.07 MB/s 1.02 MiB/s length 32: 14.907 us 2.15 MB/s 2.05 MiB/s length 64: 15.354 us 4.17 MB/s 3.98 MiB/s length 128: 19.442 us 6.58 MB/s 6.28 MiB/s length 256: 27.648 us 9.26 MB/s 8.83 MiB/s length 512: 34.147 us 14.99 MB/s 14.30 MiB/s length 1024: 53.699 us 19.07 MB/s 18.19 MiB/s length 2048: 64.598 us 31.70 MB/s 30.24 MiB/s length 4096: 73.013 us 56.10 MB/s 53.50 MiB/s length 8192: 115.309 us 71.04 MB/s 67.75 MiB/s length 16384: 286.719 us 57.14 MB/s 54.50 MiB/s length 32768: 429.863 us 76.23 MB/s 72.70 MiB/s length 65536: 788.480 us 83.12 MB/s 79.27 MiB/s length 131072: 1347.512 us 97.27 MB/s 92.76 MiB/s length 262144: 2365.584 us 110.82 MB/s 105.68 MiB/s length 524288: 4636.836 us 113.07 MB/s 107.83 MiB/s length 1048576: 8981.217 us 116.75 MB/s 111.34 MiB/s length 2097152: 17810.544 us 117.75 MB/s 112.29 MiB/s length 4194304: 35517.940 us 118.09 MB/s 112.62 MiB/s $
上記のように、遅延が15usぐらい、throughputが120MB/s弱出ていることが わかります。
使用するNICによっては、interrupt coalescingという機能が
有効になっている場合があります。
どちらかと言うと高価な、高性能NICについている機能で、
CPUへの割り込み回数を減らしてCPU負荷を軽減させるための機能です。
NICにpacketが届いた際、packet 1つ毎に割り込みをかける代わりに
packetをNIC内に蓄えておいて、複数packetをまとめて1回の割り込みで
処理させます。
File serverなどでは、CPU負荷が下がって実効転送速度も出るようになるので ありがたい機能ですが、並列計算の場合はちょっと事情が異なります。 並列計算の場合、極力低遅延であって欲しく、NICにpacketが届いたらすぐに 割り込みを出してCPUが処理出きるようにして欲しいわけです。 Interrupt coalescingが有効になっていると、届いたpacketを しばらくNIC内のに溜めてしまうので、結果として遅延が大きくなってしまいます。
Interrupt coalescingが有効になっているかの確認は、 ethtoolで行うことができます。
# ethtool -c eth0 Coalesce parameters for eth0: Adaptive RX: off TX: off stats-block-usecs: 0 sample-interval: 0 pkt-rate-low: 0 pkt-rate-high: 0 rx-usecs: 3 rx-frames: 0 rx-usecs-irq: 0 rx-frames-irq: 0 tx-usecs: 0 tx-frames: 0 tx-usecs-irq: 0 tx-frames-irq: 0 rx-usecs-low: 0 rx-frame-low: 0 tx-usecs-low: 0 tx-frame-low: 0 rx-usecs-high: 0 rx-frame-high: 0 #
Interrupt coalescingが有効なNICであれば、上記のような出力が表示されます。 Interrupt coalescing機能の無いNICなら、 単に"Operation not supported"の1行だけです。
ここで、"rx-usecs: 3"となっているところが受信後NIC内に packetを溜めておく時間です。 この値を小さくしてやると、大抵の場合遅延が改善されます。 変更は、以下の様にethtoolで行います。
# ethtool -C eth0 rx-usecs 1 #
このように設定変更を行った後、omx_perfを走らせてみると、 遅延が改善しているのがわかると思います。 手元のe1000eだと、 rx-usecs 3 → 1で8usほど遅延が少なくなりました。
また、Adaptive interrupt coalescingを使えるならonにすると良いようです (ethtool -cの出力、1行目)。 低負荷ではpacket毎に割り込み、高負荷ではpacketをまとめて割り込みの動作が できるようです。e1000eではonにできないようなので、効果の確認はできていません。