前回、NUMAアーキテクチャがネットワーク性能に与える影響についての技術的な背景を説明した。
本稿では、実際にLinux環境でネットワーク性能を測定し、NUMAが与える影響についての事例とノウハウを紹介したい。
本稿では、最終的には下記測定例をまとめている。NUMA構成が異なる場合、性能が全く異なってしまう。極端な話、40GbE NICなのに4-5Gbpsしか出ないことになってしまう。実際には性能出ます。注意。
- NUMA構成上遠い構成でのiperf性能:1プロセス(1コア) 2.00Gbps、12プロセス(6コア) 4.84Gbps
- NUMA構成上近い構成でのiperf性能:1プロセス(1コア) 14.7Gbps、12プロセス(6コア) 37.9Gbps
※現在のサーバアーキテクチャ上の仕様であるため、NICとかドライバの話ではないことに注意。チューニングを自動化して使いやすくするという話はあり、実際に自動チューニングソリューションが存在する(本稿最後に記載)。
NUMA構成の確認方法
理想的にはNUMA構成上、NICが接続されているPCI Expressバスが直結されているCPUでアプリケーションを実行する必要がある。
NICが接続されているNUMAノードの確認方法
下記の例のように確認できる。
確認例:eth2の場合
# cat /sys/class/net/eth2/device/numa_node
1
本実行例では、eth2というNICは、NUMAノード1に接続されている。
NUMAノードに所属するCPUコア番号の確認方法
下記の例のように確認できる。
# cat /sys/devices/system/node/node1/cpulist
6-11
本実行例では、NUMAノード1に所属するCPUコア番号(6~11)が得られている。
参考:同一環境でnode0のCPUコア番号を求めた例は下記である。
# cat /sys/devices/system/node/node0/cpulist
0-5
実行CPU指定方法
# taskset -c [CPU番号(複数指定する場合、カンマ(,)区切りまたはハイフン(-)指定)] [実行コマンド]
例1:# taskset -c 0,1,2 iperf -s
例2:# taskset -c 0-5 iperf -s
ネットワーク性能測定方法
上記により、本実行例では、eth2に関するネットワーク性能測定では、eth2が接続されているNUMAノード1に所属するCPUコア6~11でベンチマークソフトウェアを動作させる必要があることになる。
- eth2が所属するNUMAノード=1
- NUMAノード=1に所属するCPUコア番号=6~11
実機測定例
今回性能測定に使用したNICと測定環境
- Mellanox ConnectX-3Pro Dual Port(40GbE) [FW:2.31.5050]
- OS : Ubuntu 14.04 Server
- ドライバ:MLNX OFED 2.2-1.0.1
- 接続構成:Mellanox SX1012(12ポート40GbEスイッチ)経由で2台の同一サーバを接続
- 送信側サーバIPアドレス:12.0.0.1
- 受信側サーバIPアドレス:12.0.0.2
- MTU : Default (1500 byte)
$ ifconfig eth2
eth2 Link encap:Ethernet HWaddr (-----snip----)
inet addr:12.0.0.1 Bcast:12.0.0.255 Mask:255.255.255.0
inet6 addr: fe80::f452:1400:17a:5532/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3519272 errors:0 dropped:1 overruns:0 frame:0
TX packets:113091827 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:226370515 (226.3 MB) TX bytes:171670950196 (171.6 GB)
# ethtool -i eth2
driver: mlx4_en
version: 2.2-1.0.0 (May 11 2014)
firmware-version: 2.31.5050
bus-info: 0000:82:00.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: yes
# ethtool eth2
Settings for eth2:
Supported ports: [ TP ]
Supported link modes: 1000baseT/Full
1000baseKX/Full
10000baseT/Full
10000baseKX4/Full
10000baseKR/Full
40000baseKR4/Full
40000baseCR4/Full
40000baseSR4/Full
40000baseLR4/Full
Supported pause frame use: No
Supports auto-negotiation: No
Advertised link modes: 1000baseT/Full
1000baseKX/Full
10000baseT/Full
10000baseKX4/Full
10000baseKR/Full
40000baseKR4/Full
40000baseCR4/Full
40000baseSR4/Full
40000baseLR4/Full
Advertised pause frame use: No
Advertised auto-negotiation: No
Speed: 40000Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: off
MDI-X: Unknown
Supports Wake-on: d
Wake-on: d
Current message level: 0x00000014 (20)
link ifdown
Link detected: yes
# ibstat
CA 'mlx4_0'
CA type: MT4103
Number of ports: 2
Firmware version: 2.31.5050
Hardware version: 0
Node GUID: 0xf4521403xxxxxx
System image GUID: 0xf452140300xxxxxx
Port 1:
State: Down
Physical state: Disabled
Rate: 10
Base lid: 0
LMC: 0
SM lid: 0
Capability mask: 0x00010000
Port GUID: 0xf65214fffexxxxxx
Link layer: Ethernet
Port 2:
State: Active
Physical state: LinkUp
Rate: 40
Base lid: 0
LMC: 0
SM lid: 0
Capability mask: 0x00010000
Port GUID: 0xf452140001xxxxxx
Link layer: Ethernet
$ iperf -v
iperf version 2.0.5 (08 Jul 2010) pthreads
測定結果(1プロセス、1CPUコア使用)
NICから遠いNUMAノードであるNUMA=0に所属するCPUコア=0で1プロセスを実行
iperf server(受信側) :
# taskset -c 0 iperf -s // CPU=0はNUMA=0に所属(eth2から遠いNUMAノード)
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42358
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 2.33 GBytes 2.00 Gbits/sec
iperf client(送信側):
# taskset -c 0 iperf -c 12.0.0.2 -P 1 // CPU=0はNUMA=0に所属(eth2から遠いNUMAノード)
------------------------------------------------------------
Client connecting to 12.0.0.2, TCP port 5001
TCP window size: 1.06 MByte (default)
------------------------------------------------------------
[ 3] local 12.0.0.1 port 42358 connected with 12.0.0.2 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 2.33 GBytes 2.00 Gbits/sec
NICから近いNUMAノードであるNUMA=1に所属するCPUコア=6で1プロセスを実行
iperf server(受信側) :
# taskset -c 6 iperf -s // CPU=6はNUMA=1に所属(eth2から近いNUMAノード)
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42362
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 17.1 GBytes 14.7 Gbits/sec
iperf client(送信側):
# taskset -c 6 iperf -c 12.0.0.2 -P 1 // CPU=6はNUMA=1に所属(eth2から近いNUMAノード)
------------------------------------------------------------
Client connecting to 12.0.0.2, TCP port 5001
TCP window size: 1.06 MByte (default)
------------------------------------------------------------
[ 3] local 12.0.0.1 port 42362 connected with 12.0.0.2 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 17.1 GBytes 14.7 Gbits/sec
測定結果(12プロセス、6CPUコア使用)
NICから遠いNUMAノードであるNUMA=0に所属するCPUコア=0~5で12プロセスを実行
iperf server(受信側) :
# taskset -c 0-5 iperf -s // CPU=0~5はNUMA=0に所属(eth2から遠いNUMAノード)
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 16] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42446
[ 4] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42447
[ 5] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42448
[ 6] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42450
[ 7] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42449
[ 8] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42451
[ 9] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42452
[ 10] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42453
[ 11] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42454
[ 12] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42455
[ 13] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42456
[ 14] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42457
[ ID] Interval Transfer Bandwidth
[ 10] 0.0-10.0 sec 378 MBytes 316 Mbits/sec
[ 6] 0.0-10.0 sec 297 MBytes 249 Mbits/sec
[ 7] 0.0-10.0 sec 564 MBytes 472 Mbits/sec
[ 8] 0.0-10.0 sec 457 MBytes 383 Mbits/sec
[ 12] 0.0-10.0 sec 418 MBytes 350 Mbits/sec
[ 9] 0.0-10.1 sec 451 MBytes 375 Mbits/sec
[ 16] 0.0-10.1 sec 348 MBytes 289 Mbits/sec
[ 11] 0.0-10.1 sec 872 MBytes 722 Mbits/sec
[ 14] 0.0-10.1 sec 492 MBytes 407 Mbits/sec
[ 5] 0.0-10.2 sec 384 MBytes 316 Mbits/sec
[ 4] 0.0-10.2 sec 480 MBytes 393 Mbits/sec
[ 13] 0.0-10.2 sec 772 MBytes 632 Mbits/sec
[SUM] 0.0-10.2 sec 5.78 GBytes 4.84 Gbits/sec
iperf client(送信側):
# taskset -c 0-5 iperf -c 12.0.0.2 -P 12 // CPU=0~5はNUMA=0に所属(eth2から遠いNUMAノード)
------------------------------------------------------------
Client connecting to 12.0.0.2, TCP port 5001
TCP window size: 1.06 MByte (default)
------------------------------------------------------------
[ 14] local 12.0.0.1 port 42457 connected with 12.0.0.2 port 5001
[ 4] local 12.0.0.1 port 42447 connected with 12.0.0.2 port 5001
[ 3] local 12.0.0.1 port 42446 connected with 12.0.0.2 port 5001
[ 5] local 12.0.0.1 port 42448 connected with 12.0.0.2 port 5001
[ 6] local 12.0.0.1 port 42449 connected with 12.0.0.2 port 5001
[ 7] local 12.0.0.1 port 42450 connected with 12.0.0.2 port 5001
[ 8] local 12.0.0.1 port 42451 connected with 12.0.0.2 port 5001
[ 9] local 12.0.0.1 port 42452 connected with 12.0.0.2 port 5001
[ 10] local 12.0.0.1 port 42453 connected with 12.0.0.2 port 5001
[ 11] local 12.0.0.1 port 42454 connected with 12.0.0.2 port 5001
[ 12] local 12.0.0.1 port 42455 connected with 12.0.0.2 port 5001
[ 13] local 12.0.0.1 port 42456 connected with 12.0.0.2 port 5001
[ ID] Interval Transfer Bandwidth
[ 6] 0.0-10.0 sec 564 MBytes 473 Mbits/sec
[ 7] 0.0-10.0 sec 297 MBytes 249 Mbits/sec
[ 10] 0.0-10.0 sec 378 MBytes 317 Mbits/sec
[ 12] 0.0-10.0 sec 418 MBytes 351 Mbits/sec
[ 8] 0.0-10.0 sec 457 MBytes 383 Mbits/sec
[ 3] 0.0-10.1 sec 348 MBytes 289 Mbits/sec
[ 9] 0.0-10.1 sec 451 MBytes 375 Mbits/sec
[ 14] 0.0-10.1 sec 492 MBytes 407 Mbits/sec
[ 11] 0.0-10.1 sec 872 MBytes 723 Mbits/sec
[ 5] 0.0-10.2 sec 384 MBytes 316 Mbits/sec
[ 4] 0.0-10.2 sec 480 MBytes 394 Mbits/sec
[ 13] 0.0-10.2 sec 772 MBytes 633 Mbits/sec
[SUM] 0.0-10.2 sec 5.78 GBytes 4.85 Gbits/sec
NICから近いNUMAノードであるNUMA=1に所属するCPUコア=6~11で12プロセスを実行
iperf server(受信側) :
# taskset -c 6-11 iperf -s // CPU=6~11はNUMA=1に所属(eth2から近いNUMAノード)
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
[ 16] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42506
[ 4] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42507
[ 5] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42508
[ 6] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42509
[ 7] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42510
[ 9] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42513
[ 8] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42511
[ 10] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42514
[ 11] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42512
[ 12] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42515
[ 13] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42516
[ 14] local 12.0.0.2 port 5001 connected with 12.0.0.1 port 42517
[ ID] Interval Transfer Bandwidth
[ 16] 0.0-10.0 sec 2.65 GBytes 2.28 Gbits/sec
[ 4] 0.0-10.0 sec 4.09 GBytes 3.51 Gbits/sec
[ 7] 0.0-10.0 sec 5.51 GBytes 4.73 Gbits/sec
[ 8] 0.0-10.0 sec 2.77 GBytes 2.37 Gbits/sec
[ 12] 0.0-10.0 sec 2.80 GBytes 2.40 Gbits/sec
[ 13] 0.0-10.0 sec 2.60 GBytes 2.23 Gbits/sec
[ 5] 0.0-10.0 sec 4.10 GBytes 3.52 Gbits/sec
[ 6] 0.0-10.0 sec 2.34 GBytes 2.01 Gbits/sec
[ 9] 0.0-10.0 sec 2.96 GBytes 2.54 Gbits/sec
[ 10] 0.0-10.0 sec 5.37 GBytes 4.60 Gbits/sec
[ 11] 0.0-10.0 sec 4.23 GBytes 3.62 Gbits/sec
[ 14] 0.0-10.0 sec 4.74 GBytes 4.06 Gbits/sec
[SUM] 0.0-10.0 sec 44.2 GBytes 37.9 Gbits/sec
iperf client(送信側):
# taskset -c 6-11 iperf -c 12.0.0.2 -P 12 // CPU=6~11はNUMA=1に所属(eth2から近いNUMAノード)
------------------------------------------------------------
Client connecting to 12.0.0.2, TCP port 5001
TCP window size: 1.06 MByte (default)
------------------------------------------------------------
[ 14] local 12.0.0.1 port 42517 connected with 12.0.0.2 port 5001
[ 6] local 12.0.0.1 port 42508 connected with 12.0.0.2 port 5001
[ 4] local 12.0.0.1 port 42506 connected with 12.0.0.2 port 5001
[ 3] local 12.0.0.1 port 42507 connected with 12.0.0.2 port 5001
[ 7] local 12.0.0.1 port 42509 connected with 12.0.0.2 port 5001
[ 5] local 12.0.0.1 port 42510 connected with 12.0.0.2 port 5001
[ 8] local 12.0.0.1 port 42511 connected with 12.0.0.2 port 5001
[ 9] local 12.0.0.1 port 42513 connected with 12.0.0.2 port 5001
[ 10] local 12.0.0.1 port 42512 connected with 12.0.0.2 port 5001
[ 11] local 12.0.0.1 port 42514 connected with 12.0.0.2 port 5001
[ 12] local 12.0.0.1 port 42515 connected with 12.0.0.2 port 5001
[ 13] local 12.0.0.1 port 42516 connected with 12.0.0.2 port 5001
[ ID] Interval Transfer Bandwidth
[ 6] 0.0-10.0 sec 4.10 GBytes 3.52 Gbits/sec
[ 4] 0.0-10.0 sec 2.65 GBytes 2.28 Gbits/sec
[ 3] 0.0-10.0 sec 4.09 GBytes 3.52 Gbits/sec
[ 7] 0.0-10.0 sec 2.34 GBytes 2.01 Gbits/sec
[ 5] 0.0-10.0 sec 5.51 GBytes 4.74 Gbits/sec
[ 8] 0.0-10.0 sec 2.77 GBytes 2.38 Gbits/sec
[ 9] 0.0-10.0 sec 2.96 GBytes 2.54 Gbits/sec
[ 12] 0.0-10.0 sec 2.80 GBytes 2.41 Gbits/sec
[ 13] 0.0-10.0 sec 2.60 GBytes 2.24 Gbits/sec
[ 14] 0.0-10.0 sec 4.74 GBytes 4.06 Gbits/sec
[ 10] 0.0-10.0 sec 4.23 GBytes 3.63 Gbits/sec
[ 11] 0.0-10.0 sec 5.37 GBytes 4.60 Gbits/sec
[SUM] 0.0-10.0 sec 44.2 GBytes 37.9 Gbits/sec
まとめ
- NUMA構成上遠い構成でのiperf性能:1プロセス(1コア) 2.00Gbps、12プロセス(6コア) 4.84Gbps
- NUMA構成上近い構成でのiperf性能:1プロセス(1コア) 14.7Gbps、12プロセス(6コア) 37.9Gbps
本測定例からも分かるように、NUMA構成の設定(アフィニティ(Affinity)設定)は非常に重要である。性能的に不利な構成で性能測定を行うと、本例のような極端な構成では、40GbE NICなのに4-5Gbpsしか性能が出ないといったことも起こりうる。
補足
Mellanoxでは、NUMAアフィニティ設定を自動で実行するコマンドを用意している。
# mlnx_affinity start
と実行すれば、コマンドが自動的にNUMAアフィニティ設定を実行する(ワンタイムでの実行で、プロセスは設定後に終了する)。
実行例:
# mlnx_affinity start
INFO - This utility does not support irqbalance control in Ubuntu 14.04 LTS \n \l
INFO - irqbalance status will not change
mlnx_affinity started[ OK ]
また、MLNX OFEDを使用している場合は、設定ファイル(/etc/infiniband/obenib.conf/openib.conf)内の下記パラメータを設定することにより、アフィニティはサーバ起動時に自動設定されるようになる。
/etc/infiniband/obenib.conf/openib.conf
# Run /usr/sbin/mlnx_affinity
RUN_AFFINITY_TUNER=yes // no-->yesに変更
本内容を含む性能チューニングガイドが下記で公開されている。