UCXを試す(5)
uct_iface_attr_t
の、capabilityに関する値を見ていきます。
ソース:
https://gist.github.com/keisukefukuda/153ec198cf234f0f5b3a43a044523e3a
出力:
Using rc/mlx4_0:1 ib/mlx4_0 component name: ib max alloc: 18446744073709551615 (17179869184[GiB]) max reg: 18446744073709551615 (17179869184[GiB]) rkey packed size: 16 Devices: mlx4_0:1/rc mlx4_0:1/ud iface_config of rc/mlx4_0:1 device_addr_len = 3 iface_addr_len = 1 ep_addr_len = 4 max_conn_priv = 0 overhead = 7.5e-08 bandwidth = 6.74572e+09 latency = 1e-09 * x + 7e-07 priority = 10 attr.cap.put max_short = 88 max_bcopy = 8192 min_zcopy = 0 max_zcopy = 1073741824 (=1024 [MiB]) opt_zcopy_align = 512 align_mtu = 2048 max_iov = 6 attr.cap.get max_bcopy = 8192 min_zcopy = 65 max_zcopy = 1073741824 (=1024 [MiB]) opt_zcopy_align = 512 align_mtu = 2048 max_iov = 6 attr.cap.am max_short = 87 max_bcopy = 8191 min_zcopy = 0 max_zcopy = 8191 (=0 [MiB]) opt_zcopy_align = 512 align_mtu = 2048 max_iov = 5 attr.cap.tag.recv.min_recv = 0 attr.cap.tag.recv.max_zcopy = 0 attr.cap.tag.recv.max_iov = 0 attr.cap.tag.recv.max_outstanding = 0 attr.cap.tag.eager.max_short = 0 attr.cap.tag.eager.max_bcopy = 0 attr.cap.tag.eager.max_zcopy = 0 attr.cap.tag.eager.max_iov = 0 attr.cap.tag.rndv.max_zcopy = 0 attr.cap.tag.rndv.max_hdr = 0 attr.cap.tag.rndv.max_iov = 0
いろいろな値が取得できておもしろげです。
attr.cap
という値は、device/transport layerの各種の上限・下限値(Capability)を示しています。
UCXにおける通信タイプは5種類あり、
- get: 片方向通信 get
- put: 片方向通信 put
- am : Active Message
- タグ付き通信
- recv: Receiveをpostしておく非同期通信
- eager: Eager通信
- rndv: Randezvous通信
があります。この rc/mlx0:1
では、タグ付き通信のCapacityが全てゼロになっていますから、タグ付き通信はできないということだと思われます。Infinibandはタグ付き通信はネイティブにサポートしていないので、それを実装するのはもう1つ上の UCP
レイヤだということになるかと思われます(タグ付き通信をネイティブにサポートしているネットワークは有るのだろうか…?)
ちなみに、Eager通信とRandezvous通信については、こちらの資料に解説があります さらに、それぞれの通信タイプにおいて、さらにメモリコピーの方法によって3つに分かれています。
- short : 小さいデータを、通信ヘッダと一緒に一気に送ってしまう方法
- bcopy : Buffered Copy=プログラムが通信しようとしたデータ領域は、一旦UCXの内部バッファにコピーされ、そこから通信される。
- zcopy : Zero Copy=いわゆるRDMA
ちなみに、bandwidth = 6.74572e+09
となっています。このマシンはInfiniband FDR x 4 を搭載しているので、理論ピーク性能は 56Gbps * 0.96 = 53.76 [Gbps] のはずです。 6.74e+09 = 6.28 [GB/s] = 50.26
なので、まあだいたい合っていますね。UCXのソースを見ると、Extra headerの分だけ実行レートが下がっている計算になるっぽいです
次回から、いよいよ通信をしてみます
UCXを試す(4)
引き続き、 uct_hello_world.c
をC++に写経しながら、次はインターフェースのopen(uct_iface_open
)と、属性取得(uct_iface_attr_t
)をしてみます。
https://gist.github.com/keisukefukuda/63cdd3516bec21437be973b845b2d476
(前回と同じ部分を省略) Using rc/mlx4_0:1 iface_config of rc/mlx4_0:1 device_addr_len = 3 iface_attr_len = 1 ep_addr_len = 4 max_conn_priv = 0 overhead = 7.5e-08 latency = 1e-09 * x + 7e-07 priority = 10
インターフェースごとに、いくつかの属性値が取れるようです。
UCXを試すメモ(3)
uct_md_query()
関数を使って、Memory DomainのAttributesを取ってみました。
https://gist.github.com/keisukefukuda/cf55bf8aaf9f343f529c25ff46487ce0
Resources: self component name: self max alloc: 0 (0[GiB]) max reg: 18446744073709551615 (17179869184[GiB]) rkey packed size: 8 Devices: self/self tcp component name: tcp max alloc: 0 (0[GiB]) max reg: 0 (0[GiB]) rkey packed size: 8 Devices: ib0/tcp eth0/tcp eth1/tcp ib/mlx4_0 component name: ib max alloc: 18446744073709551615 (17179869184[GiB]) max reg: 18446744073709551615 (17179869184[GiB]) rkey packed size: 16 Devices: mlx4_0:1/rc mlx4_0:1/ud cuda_cpy component name: cuda_cpy max alloc: 0 (0[GiB]) max reg: 18446744073709551615 (17179869184[GiB]) rkey packed size: 8 Devices: cudacopy0/cuda_copy sysv component name: sysv max alloc: 18446744073709551615 (17179869184[GiB]) max reg: 0 (0[GiB]) rkey packed size: 32 Devices: sysv/mm posix component name: posix max alloc: 18446744073709551615 (17179869184[GiB]) max reg: 0 (0[GiB]) rkey packed size: 37 Devices: posix/mm cma component name: cma max alloc: 0 (0[GiB]) max reg: 18446744073709551615 (17179869184[GiB]) rkey packed size: 8 Devices: cma/cma Using rc/mlx4_0:1
max_alloc
とか、 max_reg
の2つは今のところ意味のある値は出ていないっぽいですね(なお、18446744073709551615
というのはUINT64_MAX
です)。
rkey packed size
というのは、まだ意味がよくわかりません。
上で出力していない値に、
* uct_linear_growth_t reg_cost
* cpu_set_t local_cpus
というフィールドが2つあります。これもちょっとおもしろそうではありますが、正しい値が出るかどうかは次回のお楽しみ。
reg_cost
というのは、メモリ領域のRegistrationにかかるコストだと思われます。高速通信、特にRDMAを実現するためには、メモリ領域がディスクにスワップされては困りますし、ネットワークデバイスがメモリに直接書き込む際に物理アドレスを知っている必要があります。そこで、LinuxではPage Locked Memory(CUDAでいうPinned Memory)という機能を使って、特定のメモリ領域がSwap Outされないようにするわけですね。その操作をRegistrationと呼びます。
次に、local_cpus
というのは、デバイスとCPUのトポロジのことを言っていると思われます。ネットワークデバイスから見てどのCPU(あるいはNUMAノード)が一番近いかというのは重要で、下手をするとQPIなどを通って通信するハメになるので、どのCPU(正確にはメモリ)を送信/受信バッファにするかというのは慎重に決める必要があります。この情報は hwloc
などのライブラリを使っても知ることが出来ますが、UCXでどの程度の情報を返してくれるのかは興味があります。