この記事は Jsys Advent Calendar 2019 の4日目の記事です.
昨日は @epsilonoom による Nintendo Switchでコーディングしよう! でした.ゲーム機でゲームを作るのはメタ的で面白いですね.個人的には「Baba Is You」や「ヒューマンリソースマシーン」などのプログラマ向けパズルゲームもおすすめです.
明日は undefined による undefined です.
この記事は Coins Advent Calendar 2019 の4日目の記事です.
昨日は突撃隊による 自作OSでマルチタスクやったでした.以前から自作OSを作っているのは知っていましたがついにマルチタスクまで進んだようです.動作報告が楽しみです.
明日はてっつーによる「ぼくの母恵夢」です.
この記事は WORDIAN Advent Calendar 2019 の4日目の記事です.
昨日は突撃隊による 自作OSでマルチタスクやったでした.(ry
明日は segmentation fault 11(core dumped)
ところで
皆さんの家のネットワークはどのくらいの速度が出ますか? 我が家は2Gbpsでます.1
しかしそれはWAN,つまり外部との通信の話.デスクトップやサーバーはそれぞれGbEのポートしか無いので 1Gbpsしか出ません.
インターネット(WAN)に通信するときは相手方がボトルネックになることが多いので実効1Gbpsも出れば十分です2.実際今までこの回線で不満だったことは私はありません.3
しかしLANとなると話は別です.1Gbpsというと十分速いように聞こえますが bps は bits per seconds,…つまり Byte に直すと 125MB/s になります.1Gbpsだと秒間1GBくらい通信してる感じがしてくる気がしますが実際は秒間125MBしか転送できないのです.表で比較してみるとこんな感じです.
媒体 | 速度(目安) |
---|---|
GbE | 125MB/s |
HDD | 160MB/s |
SSD(SATA) | 500MB/s |
10GbE | 1250MB/s |
SSD(NVMe) | 4000MB/s |
なんと GbE は HDD よりも遅い.
このHDDの記録は自宅にあった WD Blue 5400RPM を適当に Crystal Disk Mark で計測したものです.特にハイエンドHDDというわけではありませんがHDDよりもGbEの方が遅いのです.
更に業務PCや逸般の誤家庭などで,HDDやSSD数枚でRAIDで組んだり,NASだけどNVMe SSDで構成しているような場合は 10GbE でもネットワークがボトルネックになります.
例えば映像クリエイターで動画素材をサーバーに置いた状態でレンダリングをするレンダークラスタをお持ちの方や,サーバーいじりや機械学習などで大量のデータが入ったVHDをNASに置いて運用しているなどの状況ではモロにこのGbEがボトルネックになります.
我が家の場合はサーバーに置いた動画データやVHDのコピーや,デスクトップPCのバックアップをサーバーに転送しているときなどに,ネットワークがサチっていました.
うちのサーバーのメインストレージは WD Red 7200RPM なのでそこまで高速なネットワークで組む必要はなかったのですが,予算 1.5 万円で,実効速度 20Gbps 超えのローカルネットワーク
が作れることが判明したので作っちゃった話です.
InfiniBand
InfiniBand って知っていますか? 私は知っています.4
詳しく気になった方は Wikipedia や Qiita,ArchWikiやこの辺の記事 などを読んでほしいのですが,簡単に言うと HPC5向けの高速ネットワーク規格です.
ネットワークを組む際は Ethernet を使うことが一般的だと思いますが,古典的なEthernetは意外と無駄が多く,規格として高性能化するのが難しい問題があります.そんなEthernetを克服すべく規格されたのがInfiniBandです.
IBの主な特徴としては,
高スループット
IB にもいくつかのバージョンがあるのですが,最新のHDR規格であれば4レーン接続で200Gbpsの超高スループットが出ます.
低レイテンシ
Ethernetでは通信する際にMACアドレスを使用します.しかしMACアドレスは48bitもの長さがあるので,スイッチングハブがパケットを転送する際,MACアドレスとポートの対応にはハッシュテーブルのような複雑なデータ構造が必要になります.
IB も GUID という製造時に振られる識別子がありますが,通信の際にはトポロジー内でユニークな 16bitのLID を用いて通信します.このうち ユニキャスト LID は 49,151 個しかないので,各1バイトずつポート情報を持っても 48 KB 程度と,スイッチのCPUキャッシュに配列をそのまま載せることができるので低レイテンシで通信できます.
トポロジーにLIDを振るにはサブネットマネージャ(SM)を立てます.これはSM起点で各ポートをスキャンしていき,どこにどの機器が接続されているかを検出し,ファブリック(IBのトポロジーのこと)を随時認識します.ファブリック内にSMは1つあれば良く,InfiniBandインテリジェントスイッチと呼ばれるスイッチではスイッチにSMが内蔵されています.インテリジェントスイッチが無くても,OpenSM という OSS 実装があるので使用時に常に起動しているサーバーがあればそれにインストールすれば問題ないです.
Remote Data Memory Access (RDMA)
通常のアプリケーションは通信時に,メモリに載ったアプリのデータをOSのデータバッファにコピーして転送する等,メモリ→OS→相手OS→相手メモリ と沢山のメモリコピーが発生しますが,RDMAではリモートコンピュータのメモリアドレスを指定してデータを読み書きすることができます.つまりとてもはやい.
IP over IB(IPoIB)
IB は OSI 参照モデルで言うデータ層(第2層)からトランスポート層(第4層)まで一括で提供しています.しかしHPC用途以外で使うときは,IP(第3層)やTCP/UDP(第4層)も使いたいところです.
IBではIB上にIPプロトコルを流す IPoIB を使用することができます.本来のIBの速度よりは効率が落ちてしまいますが,実家のような安心感で ping を飛ばしたり,TCP/IP 通信できます.
他にもすごい機能がいっぱい!
他にも強いフロー制御やゼロコピー,ループが存在するトポロジーも許すなど様々な機能があります.ここでは書かないので気になった方は調べてみてください.
いかがでしょうかInfiniBand.ちょっと認識が怪しい部分もあるので通りすがりのプロで間違いに気づいた方は指摘してください.
でもお高いんでしょ…
新品で HCA(Host Channel Adapter, いわゆるNIC)を買った場合,最新のHDRで200Gbpsが出る Mellanox ConnectX-6 の場合,1ポート製品(MCX653105A-HDAT)で184,580円,2ポート製品(MCX653106A-HDAT)で276,760円で買えるようです.(税込,2019年12月4日現在)
ConnectX の場合,IBモードの他にEthernetモードでも動作可能なので,IBに不慣れな方でも導入敷居は低めですが,大学生の趣味などではちょっと手が届きにくいですね.(もっともコレは最上位機種なので,より安い機種もありますが)
そこでIBの見どころとして, 手頃な中古品が ebay などの市場で安価に出回っている というポイントがあります.ArchWiki でも
巨大企業が新しいバージョンを求めることなどから InifiniBand の中古市場は飽和状態となっており、家庭や小規模オフィスの内部ネットワーク用として中古の InfiniBand デバイスが手軽な価格で入手することができます。
と紹介されています.
例えば FDR x4に対応していて 54.55Gbps出る2ポートHCA MCX354A-FCBT は1枚5000円程度から,1ポートHCAのMCX353A-FCBTも同様の価格で出品されています.
似た型番に MCX353A-QCBT
, MCX354A-QCBT
というものもありますが,これらは FDRより1つ遅い QDRx4(40Gbps)であり,Ethernetは10Gbpsまで対応の製品です.
これらはConnect-X 3シリーズというものなのですが,Connect-X 2以下のシリーズでは Windows 7 までの対応なので,最近のWindowsでも使いたい場合は注意が必要です.
今回は, MCX354A-FCBT
を2枚と MC2207130
という FDR 対応のケーブル1本を注文し,送料込みで14,984円かかりました.リーズナブルでしょ?
※今回は小規模ネットワークなのでIBスイッチは購入しませんでした.2ポートHCAなのでいざというときはデイジーチェーンさせれば良いのと,IBスイッチはファンの騒音が結構激しいので,寝室と同じ部屋に設置すると寝れなくなります.
構築編
購入したHCAは以下のマシンに取り付けました.
CPU : Intel Core i9-7900X
RAM : DDR4 3200MHz 64GB
OS : Windows 10 1903
CPU : Intel Core i3-6100
RAM : DDR3 2133MHz 16GB
OS : Windows Server 2012R2
そのまま指しただけでも,Windows標準ドライバで動作させることができます.
Windowsからは56GbpsのNICとして見えているようです.
※設定を済ませたあとのスクショなので,何バイトか通信されてるように出てます.
しかしこのままだとIB関係のツールが使えないので,この記事を参考にしつつ,ドライバーをダウンロード・インストールします.Connect-X 3 の場合は WinOF ドライバを使います.現時点での最新は 5.50.52000 でした.ドライバと一緒にHCAのFWアップデートもされるのでしましょう.
Windows Server 2012 R2にインストールしようとしたら「mofcompが見つかりません」と怒られました.調べたらC:\Windows\System32\wbem\
にあったのでパスを通したらうまく行きました.
ドライバインストールすると, C:\Program Files\Mellanox\MLNX_VPI\IB\Tools
以下に様々なツールがインストールされます.ひとまず ibstat で IB の状態を確認してみます.
C:\Program Files\Mellanox\MLNX_VPI\IB\Tools>ibstat
CA 'ibv_device0'
CA type:
Number of ports: 2
Firmware version: 2.42.5000
Hardware version: 0x0
Node GUID: 0x0002c90300a4c080
System image GUID: 0x0002c90300a4c083
Port 1:
State: Initializing
Physical state: LinkUp
Rate: 56
Base lid: 0
LMC: 0
SM lid: 0
Capability mask: 0x90580000
Port GUID: 0x0002c90300a4c081
Link layer: IB
Transport: IB
Port 2:
State: Down
Physical state: Polling
Rate: 40
Base lid: 0
LMC: 0
SM lid: 0
Capability mask: 0x90580000
Port GUID: 0x0002c90300a4c082
Link layer: IB
Transport: IB
C:\Program Files\Mellanox\MLNX_VPI\IB\Tools>ibstat
CA 'ibv_device0'
CA type:
Number of ports: 2
Firmware version: 2.42.5000
Hardware version: 0x0
Node GUID: 0x0002c90300a4bed0
System image GUID: 0x0002c90300a4bed3
Port 1:
State: Initializing
Physical state: LinkUp
Rate: 56
Base lid: 0
LMC: 0
SM lid: 0
Capability mask: 0x90580000
Port GUID: 0x0002c90300a4bed1
Link layer: IB
Transport: IB
Port 2:
State: Down
Physical state: Polling
Rate: 40
Base lid: 0
LMC: 0
SM lid: 0
Capability mask: 0x90580000
Port GUID: 0x0002c90300a4bed2
Link layer: IB
Transport: IB
どちらも Port 1 にのみ接続したので,Port 1 が LinkUp/Initializing になりました.
逆に Port 2 には接続していないので,Polling / Down になっています.
現在,直挿しでどこにもサブネットマネージャーが居ないので,State: Initializing
になっています.
sc create OpenSM binPath= "c:\Program Files\Mellanox\MLNX_VPI\IB\Tools\opensm.exe --service" start=auto
をして Windows Server 側でサービス化しておきます.
これで Server が起動している間は,IB ネットワークが使えるようになります. ibstat で Port 1 を確認してみると
Port 1:
State: Active
Physical state: LinkUp
Rate: 56
Base lid: 1
LMC: 0
SM lid: 1
Capability mask: 0x90580000
Port GUID: 0x0002c90300a4c081
Link layer: IB
Transport: IB
Port 1:
State: Active
Physical state: LinkUp
Rate: 56
Base lid: 2
LMC: 0
SM lid: 1
Capability mask: 0x90580000
Port GUID: 0x0002c90300a4bed1
Link layer: IB
Transport: IB
と両方 Active になりました!
OpenSMはデフォルトでHCAの1番ポートから順にファブリックを認識していきます.
HCAに2本ケーブルを指し,1番ポートと2番ポートが別のサブネットに居る場合は2番に永遠にLIDが振られず通信ができません.
c:\Program Files\Mellanox\MLNX_VPI\IB\Tools\opensm.exe --service -g 0x0002c90300a4c082
のように,-gで2番のGUIDを指定指定してあげることで,2番ポートからのファブリックの調査がされます.僕は過去に2番ポートに挿しているにも関わらず-g無しでOpenSMを立ち上げてて通信できない問題に直面して2週間ぐらい悩んでました.
##疎通テスト
待機側で ibping -S
コマンドを実行すると ibping の待機が開始されます.
とりあえず Server/Cliant 両方で待機させて,お互いに疎通できてるか試します.
C:\Program Files\Mellanox\MLNX_VPI\IB\Tools>ibping 1
Pong from ?hostname?.?domainname? (Lid 1): time 0.296 ms
Pong from ?hostname?.?domainname? (Lid 1): time 0.374 ms
Pong from ?hostname?.?domainname? (Lid 1): time 0.625 ms
Pong from ?hostname?.?domainname? (Lid 1): time 0.529 ms
--- ?hostname?.?domainname? (Lid 1) ibping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3130 ms
rtt min/avg/max = 0.296/0.456/0.625 ms
C:\Program Files\Mellanox\MLNX_VPI\IB\Tools>ibping 2
Pong from ?hostname?.?domainname? (Lid 2): time 0.239 ms
Pong from ?hostname?.?domainname? (Lid 2): time 0.437 ms
Pong from ?hostname?.?domainname? (Lid 2): time 0.464 ms
Pong from ?hostname?.?domainname? (Lid 2): time 0.412 ms
--- ?hostname?.?domainname? (Lid 2) ibping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3705 ms
rtt min/avg/max = 0.239/0.388/0.464 ms
IB では Macアドレスの代わりに lid で通信します.ibstat の Base lid:
と書かれていたところがそうです.
なので ibping 1
でサーバーへの ping,ibping 2
でクライアント(自分自身)への ping となります.
IPoIB
HCAにIPアドレスを振ることでIPによる通信ができます.コントロールパネルのネットワーク接続から Mellanox ConnectX-3 IPoIB Adapter
を探し,いつものように固定IPとサブネットマスクを振ります.デフォルトゲートウェイ等は必要ありません.とりあえず
NIC | IB-HCA | |
---|---|---|
Server | 192.168.1.2 | 192.168.222.2 |
Client | 192.168.1.4 | 192.168.222.4 |
と振りました.(NICは普段使っているEtherのIP)
お互いに ping を飛ばして疎通しているか試します. ibping と違いサーバー側で待機する必要はありません(それはそう,実家のような安心感).
IPによる通信ができたので,iperf3 で速度テストします.5201番ポートを開放してチェックします.まずは GbE から
iperf3.exe -s
>iperf3 -c 192.168.1.2
Connecting to host 192.168.1.2, port 5201
[ 4] local 192.168.1.4 port 1395 connected to 192.168.1.2 port 5201
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-1.00 sec 108 MBytes 905 Mbits/sec
[ 4] 1.00-2.00 sec 112 MBytes 938 Mbits/sec
[ 4] 2.00-3.00 sec 113 MBytes 948 Mbits/sec
[ 4] 3.00-4.00 sec 113 MBytes 948 Mbits/sec
[ 4] 4.00-5.00 sec 113 MBytes 949 Mbits/sec
[ 4] 5.00-6.00 sec 113 MBytes 949 Mbits/sec
[ 4] 6.00-7.00 sec 113 MBytes 948 Mbits/sec
[ 4] 7.00-8.00 sec 112 MBytes 940 Mbits/sec
[ 4] 8.00-9.00 sec 113 MBytes 945 Mbits/sec
[ 4] 9.00-10.00 sec 113 MBytes 949 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-10.00 sec 1.10 GBytes 942 Mbits/sec sender
[ 4] 0.00-10.00 sec 1.10 GBytes 942 Mbits/sec receiver
iperf Done.
通常の GbEですね.次は IPoIB
>iperf3 -c 192.168.222.2
Connecting to host 192.168.222.2, port 5201
[ 4] local 192.168.222.4 port 1397 connected to 192.168.222.2 port 5201
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-1.00 sec 411 MBytes 3.45 Gbits/sec
[ 4] 1.00-2.00 sec 444 MBytes 3.73 Gbits/sec
[ 4] 2.00-3.00 sec 457 MBytes 3.83 Gbits/sec
[ 4] 3.00-4.00 sec 466 MBytes 3.91 Gbits/sec
[ 4] 4.00-5.00 sec 429 MBytes 3.60 Gbits/sec
[ 4] 5.00-6.00 sec 410 MBytes 3.44 Gbits/sec
[ 4] 6.00-7.00 sec 451 MBytes 3.78 Gbits/sec
[ 4] 7.00-8.00 sec 450 MBytes 3.78 Gbits/sec
[ 4] 8.00-9.00 sec 455 MBytes 3.82 Gbits/sec
[ 4] 9.00-10.00 sec 469 MBytes 3.94 Gbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-10.00 sec 4.34 GBytes 3.73 Gbits/sec sender
[ 4] 0.00-10.00 sec 4.34 GBytes 3.73 Gbits/sec receiver
iperf Done.
GbE よりは速いですけど,なんかパッとしませんね.それもそのはずで,IBは複数スレッド張らないとその真価は発揮できません.もう一度試してみます.
>iperf3 -c 192.168.1.2 -P 4
~省略~
[SUM] 0.00-10.00 sec 1.09 GBytes 934 Mbits/sec sender
[SUM] 0.00-10.00 sec 1.09 GBytes 934 Mbits/sec receiver
GbEではやはり 1Gbps 程度止まりだったものが
>iperf3 -c 192.168.222.2 -P 4
[SUM] 0.00-10.00 sec 8.10 GBytes 6.96 Gbits/sec sender
[SUM] 0.00-10.00 sec 8.10 GBytes 6.96 Gbits/sec receiver
>iperf3 -c 192.168.222.2 -P 6
[SUM] 0.00-10.00 sec 17.7 GBytes 15.2 Gbits/sec sender
[SUM] 0.00-10.00 sec 17.7 GBytes 15.2 Gbits/sec receiver
>iperf3 -c 192.168.222.2 -P 8
[SUM] 0.00-10.00 sec 19.0 GBytes 16.3 Gbits/sec sender
[SUM] 0.00-10.00 sec 19.0 GBytes 16.3 Gbits/sec receiver
>iperf3 -c 192.168.222.2 -P 10
[SUM] 0.00-10.00 sec 15.4 GBytes 13.2 Gbits/sec sender
[SUM] 0.00-10.00 sec 15.4 GBytes 13.2 Gbits/sec receiver
>iperf3 -c 192.168.222.2 -P 12
[SUM] 0.00-10.00 sec 14.7 GBytes 12.6 Gbits/sec sender
[SUM] 0.00-10.00 sec 14.7 GBytes 12.6 Gbits/sec receiver
と,並列数を上げることによって 16Gbps ぐらいで通信できました!
SMB over RDMA
ファイルサーバーのボトルネック解消を目的とするならば,いちばん重要なポイントです.Windowsによるファイル共有はSMBを使って行うことができますが,RDMA を使ってファイル転送することができます.
設定は https://www.slideshare.net/detteiu/infiniband-hackathon-2-windows を参考にします.
と言ってもチェックすべき項目は全て既にOKだったので Explorer から相手に接続すればそれで完了でした.
IP直打ちやらメトリック変更やらルートを教えなくても,OSからは 56Gbps NIC として認識されているのでホスト名打てば勝手に IB を使ってくれました.
以下,検証です.ストレージは各マシンにRAMディスクを作って,RAMディスク同士でファイルコピーをしました.
RAMディスク自体の速度は以下のとおりです.
サーバーのRAMディスク
クライアントのRAMディスク
雫ちゃん可愛い!!
この状態で,CrystalDiskMark のフォルダー選択で,ネットワークドライブのフォルダを指定して,ベンチマークを行います.
結果は以下の通りです.
クライアントからサーバーのフォルダをベンチマーク
シーケンシャルReadに関して,2201 MB/s = 17.6 Gbps
の速度を達成しました.これは10GbEでも達成することはできず,高速な NVMe SSD ストレージにネットワーク越しでアクセスする場合でもニッコリの速度です.
しかしWriteに関しては375 MB/s = 3.0 Gbps
と少し速度が出ていません.
今度は逆にサーバー側からクライアントのストレージを触ってみました.
サーバーからクライアントのフォルダをベンチマーク
シーケンシャルWriteに関して,2301MB/s = 18.4 Gbps
を達成していますが,Read は 718 MB/s = 5.7 Gbps
でサチっています.
クライアントからサーバーのフォルダを触ったときよりは出てますが,それでも Client→Server方向のデータ送信が速度が出ていません.
気になったので今度は,サーバー側からクライアントのファイルをクライアントのフォルダーへコピーしました.
クライアントからサーバーのファイルをサーバーのフォルダーへコピー
このベンチマークでは,双方向 4.5 Gbps
= 562 MB/s 出ました.クライアントからサーバーのWriteをしているのにも関わらず,CrystalDiskMark よりも速度が出ているのはよく分かりません.
最後に逆にサーバーから操作した場合です.
サーバーからクライアントのファイルをクライアントのフォルダーへコピー
こちらは 8.1Gbps
= 1012 MB/s 出ました.サーバーからクライアントのファイルを操作することはあまり無いとは思いますがこの速度が出るなら,別のPCから別のPCのファイルを読み書きする場合でも,ネットワークがボトルネックになる環境は少なさそうです.
やはり CrystalDiskMark と別の傾向が出たのは理由は分かりません.
RDMA では相手のメモリを直接触れるという認識なのですが,RAMディスクでベンチマークをしている関係上,メモリ同士の処理になるのであまり良くないことが発生しているのかもしれません.
クライアント側はともかくサーバーには M.2 SSD スロットが無く高速な実ストレージ環境が今回は用意できなかったので,RAMディスクでは無い場合の調査はできませんでした.
まとめ
意外とGbEは遅いということで,今回は実効 20Gbps 以上出る高速なネットワークを予算1.5万円で作った話を紹介しました.
一応規格上は54Gbps出るはずなのですが,オーバーヘッドなどもあるのでひとまず良しとしましょう.
SMB over RDMA では一部の結果では IB にしては遅い所もありましたが,最低でも 3 Gbps 以上は出ていたので我が家の環境では問題無いのでひとまずこのまま運用したいと思います.
この構成にしてしばらくしたらクライアントPCのバックアップが始まりサーバーのNASにコピーが始まったのですが,ピークは 4 Gbps 程度まで使ってくれていたので満足です.USB-LAN2500R という 2.5G USB NIC も検討したのですが,これとほぼ同コストながら2.5G以上のネットワークが組めて本当に良かった(PCIeでは無くUSBなので持ち運びができるメリットはあるのですが,爆熱になって性能が落ちるレビューもあったので見送りました).
というわけで,自宅・職場の GbE じゃ満足できないなと感じた方はぜひ IB ネットワーク構築をしてみてはいかがでしょうか?
この記事を読んで Good と感じたらぜひ「いいね」やTweetをお願いいたします.
それでは!