漢なら Docker(LXC) で InfiniBand を動かしてみたいですね!
一応すでに LXC で動いている論文がありますので [1], Docker でも実現してみましょう.
手順
環境
- ホスト側: CentOS 6.5
- コンテナ側: CentOS 6.5
と仮定して作業を進めます. もしかしたら Ubuntu12.04 or higher でもほぼ同じ手順でできるかもしれません.
ホスト OS で IB(InfiniBand)が問題なく動いているとします.
Docker で centos6 イメージを取得して IB 周りのパッケージを入れます.
$ sudo docker pull centos
$ sudo docker run -i -t centos /bin/bash
# yum update
# yum install infiniband-diags
# その他 IB パッケージをいろいろ
検証した環境の HCA は ConnectX-2(mlx4) なので libmlx4 を忘れずにインストールしておきます.
# yum install libmlx4
/etc/libibverbs.d/mlx4.driver
があるのを確認します.
HCA に対応したドライバパッケージを入れておかないと, ibv_devices などをしたときに
Warning: no userspace device-specific driver found for
/sys/class/infiniband_verbs/uverbs0
と出るので注意しましょう.
この時点でホスト側で
$ sudo docker commit XXXXXX(コンテナのID) centos6-ib
としてイメージのスナップショットを作っておきます.
ibstat を実行してホスト OS と同じ結果であるのを確認します.
# ibstat
ibv_devinfo を実行してみます
# ibv_devinfo
hca_id: mlx4_0
transport: InfiniBand (0)
fw_ver: 2.9.1000
node_guid: XXXX:XXXX:XXXX:XXXX
sys_image_guid: XXXX:XXXX:XXXX:XXXX
vendor_id: 0xXXXX
vendor_part_id: XXXX
hw_ver: 0xXX
board_id: MT_XXXXXXX
phys_port_cnt: 2
port: 1
state: PORT_DOWN (1)
max_mtu: 4096 (5)
active_mtu: 4096 (5)
sm_lid: 1
port_lid: 1
port_lmc: 0x00
link_layer: InfiniBand
port: 2
state: PORT_DOWN (1)
max_mtu: 4096 (5)
active_mtu: 4096 (5)
sm_lid: 0
port_lid: 0
port_lmc: 0x00
link_layer: InfiniBand
素敵です.
ibhosts をしてみます.
# ibhosts
src/query_smp.c:227; can't open UMAD port ((null):0)
/usr/sbin/ibnetdiscover: iberror: failed: discover failed
うむむ… strace で ibnetdiscover を追って見ます.
# strace ibnetdiscover
…
open("/dev/infiniband/umad0", O_RDWR|O_NONBLOCK) = -1 ENOENT (No such file or directory)
write(2, "src/query_smp.c:227; can't open "..., 53src/query_smp.c:227; can't open UMAD port ((null):0)
...
なんたるちや! そもそも /dev/infiniband が存在していませんでした….
/dev/infiniband の設定.
Docker 的に他に推奨の方法がありそうですが, とりあえず無理やりホストの /dev/infniband をコンテナの /dev/infiniband にバインドさせてコンテナを起動します.
$ sudo docker run -privileged -v /dev/infiniband:/dev/infiniband -i -t centos6-ib /bin/bash
# ibhosts
Ca : 0xXXXXXXXXXXXXXX ports 2 "xeon HCA-1"
Cool! 素敵です. ついに Docker(LXC) で IB にアクセスすることができました!
性能
ib_read_bw, ib_write_bw, ib_read_lat, ib_read_bw で計測しました. 一方が LXC コンテナ内と Native, もう一方が Native で動いています. ConnectX2 QDR(40Gbps) で計測.
Native(ホスト OS で直接実行)とほとんど変わりませんね! プロセスは LXC で動いているわけですがそのオーバーヘッドはまず無いと言えます. Cool.
実行ログは以下のような感じです.
Docker 内(LXC container)で実行
# ib_read_bw 192.168.11.16
…
-----------------------------------
#bytes #iterations BW peak[MB/sec] BW average[MB/sec] MsgRate[Mpps]
65536 1000 3008.83 3008.80 0.048141
----------------------------------------------------
# ib_write_bw 192.168.11.16
…
-----------------------------------
#bytes #iterations BW peak[MB/sec] BW average[MB/sec] MsgRate[Mpps]
65536 5000 3066.07 3066.05 0.049057
---------------------------------------------------------------------------------------
# ib_read_lat 192.168.11.16
…
-----------------------------------
#bytes #iterations t_min[usec] t_max[usec] t_typical[usec]
2 1000 1.66 20.13 2.65
---------------------------------------------------------------------------------------
# ib_write_lat 192.168.11.16
…
-----------------------------------
#bytes #iterations t_min[usec] t_max[usec] t_typical[usec]
2 1000 0.80 7.12 0.86
---------------------------------------------------------------------------------------
ホスト OS(Native)で実行
$ ib_read_bw 192.168.11.16
…
-----------------------------------
#bytes #iterations BW peak[MB/sec] BW average[MB/sec] MsgRate[Mpps]
65536 1000 3015.43 3011.54 0.048185
---------------------------------------------------------------------------------------
$ ib_write_bw 192.168.11.16
…
-----------------------------------
#bytes #iterations BW peak[MB/sec] BW average[MB/sec] MsgRate[Mpps]
65536 5000 3065.79 3065.63 0.049050
--------------------------------------------------------------------------------
$ ib_read_lat 192.168.11.16
…
-----------------------------------
#bytes #iterations t_min[usec] t_max[usec] t_typical[usec]
2 1000 1.68 39.48 2.67
---------------------------------------------------------------------------------------
$ ib_write_lat 192.168.11.16
…
-----------------------------------
#bytes #iterations t_min[usec] t_max[usec] t_typical[usec]
2 1000 0.80 4.70 0.86
---------------------------------------------------------------------------------------
TODO
- /dev のセキィリティはどうなるのかな? /dev/infiniband のよりうまいバインディング方法はないかな?
さらなる活用
IB HCA 以外にも, Docker で特権モード + LXC コンフィグをいじることで GPU をパススルーできるようです.
頑張れば PCIex デバイス一般が Docker で動くやもしれません.
参考文献
- [1] Performance Evaluation of Container-based Virtualization for High Performance Computing Environments http://marceloneves.org/papers/pdp2013-containers.pdfk