本当は怖いHPC

HPC屋の趣味&実益ブログ

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でどの程度の情報を返してくれるのかは興味があります。

【広告】