Open-MXを使ってみる

Open-MXとは?

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を知らないと上記の説明が何のことかさっぱりわからないと 思いますので、ちょっとだけ補足します。

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

ここまで読めば、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を比較してみましょう。

TCP/IP
良いところ
通信の標準。ほとんどのOS、hardwareで使用できる。
どのMPI libraryでもTCP/IPを使って通信可能。
良くないところ
遅い。TCP/IP over GbEで、片道遅延が25〜70usもある(NICによって結構違う)。
GAMMA
良いところ
Gigabit Ethernetではたぶん最速。GAMMA over GbEで、片道遅延が6〜10us。
良くないところ
使用環境が非常に限定される。
NICはIntel PRO/1000もしくはBroadcom NetExtream Iのみ対応。
Linux kernelの特定versionが必要。
TCP/IPとNICを共用できないので、GAMMA用とTCP/IP用にNIC 2枚必要。
MPIも専用のMPI/GAMMAが必要。 MPI/GAMMAはMPI-1.2までの実装で、残念ながらMPI-2には対応していない。
Open-MX
良いところ
TCP/IPと比べるとそこそこ速い。Open-MX over GbEは、片道遅延が10〜20us。
Linuxが対応しているNICであればどれでも使える。
TCP/IPとNICを共用できるので、NIC 1枚でも利用可能。
User空間がMyrinet Express互換なので、 MPICH2Open MPIといった主要なMPI libraryを いじらずに使うことができる。
良くないところ
GAMMAほど速くない。
OSはLinuxに限定される。(だれか移植しないかな)

こうやって比べてみると、Open-MXはTCP/IPとGAMMAの中間の性格を 持っていることが分かると思います。 GAMMAを使える環境を用意できるのであれば、GAMMAの性能は魅力的です。 でも、今あるものを使ってなるべく良い性能を出したいと思ったとき、 Open-MXの性格は非常に魅力的に見えると思います。

Open-MXのinstall

まずは、Open-MXのsiteから、 open-mx-1.2.0.tar.gz(2009年12月時点の最新)を取ってきます。

Install作業自体は簡単で、よくある"./configure; make; make install"の 3 stepでinstallできます。 ただ、ちょっとクセがあるので、何点か注意します。

configure

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

"make install"すると、あまり一般的でない場所にいくつかの fileがinstallされてしまいます。 あまり気分が良くないので、いくつかのfileについて一般的な場所に移動します。

/usr/bin/test/*
→/usr/bin/*
/usr/modules/2.6.xx/open-mx.ko
→/lib/modules/2.6.xx/kernel/net/open-mx/open-mx.ko
/usr/sbin/45-open-mx.rules
→/etc/udev/rules.d/45-open-mx.rules
/usr/sbin/omx_init
→/etc/init.d/open-mx
/usr/sbin/open-mx.conf
→/etc/open-mx/open-mx.conf

私の場合、上記のようにinstall先を変更するpatch ( open-mx-1.2.0_install.patch ) を書きました。 このpatchを使う場合は、configureする前にpatchを当ててください。

それから、たぶんbugだと思いますが、64bit環境ではlibraryが/usr/lib6464に installされます。これでは困るので、以下のようにしてください。

# make libdirsuffix= install

SRPM

上記のpatchを当てたRPMを作りました。必要な方はどうぞ。→ open-mx-1.2.0-1.src.rpm

Open-MXの設定

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=

Open-MXの動作確認

上記の設定をした後、"/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)
# 

omx_info

続いて、他の機械を認識できているか確認します。 同じ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
$

omx_pref

最後に、双方の機械で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弱出ていることが わかります。

補足 - Interrupt coalescing

使用する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にできないようなので、効果の確認はできていません。


ご意見、ご感想は、花房 真広 <webmaster@hanabusa.net>まで。メールする前にtop pageの注意書を読んでください。