Docker コンテナで InfiniBand を動かす(性能も測定しました)

  • 20
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

漢なら 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) で計測.

ib-lxc-performance.gif

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 をパススルーできるようです.

https://github.com/dotcloud/docker/issues/682

頑張れば PCIex デバイス一般が Docker で動くやもしれません.

参考文献