Shortcuts

高性能RPC框架

简介

DI-engine 集成了 torch.distributed.rpc 模块, torchrpc 专注于高性能 P2P 的 RPC 通信,其可以自动选择最佳的通信策略( NVLINK ,共享内存, RDMA 或是 TCP ),并且支持 GPU direct RDMA 技术。 如果您的集群配备有 InfiniBand/RoCE 网络,则非常建议您使用 torchrpc 作为 DI-engine 的消息队列通信实现;即使没有, torchrpc 实现的多线程 TCP-RPC 通信性能也要优于过去 DI-engine 基于 NNG 的消息队列实现。

../_images/rpc.png

为什么不是NCCL

NCCL 作为广泛使用的高性能集合通信库,其专注于诸如 AllReduce 等集合通信范式,但却不擅长进行任意消息类型的高性能P2P通信,而 torchrpc 填补了这一空白。 下表给出了其和 NCCL 的一些对比:

对比

NCCL

torchrpc

支持GPU数据的RDMA-P2P

True

True

支持CPU数据的RDMA-P2P

False

True

支持传输的对象类型

只支持tensor

任意python对象

适用场景

集合通讯

点对点通信

性能测试

测试环境:配备有 A100-80GB GPU 和 200G 的 Infiniband 网卡的K8S集群

跨节点 P2P 测试

test case(unit:ms)

20 .00 KB

1 .25 MB

10 .00 MB

40 .00 M

64 0.00 M

1. 25GB

2.50 GB

nng-TCP

5.7 353

9.6 782

3 0.5 187

17 2.9 719

3 450. 7418

7 083. 6372

14072 .1213

nccl-TCP

0.0 826

1. 321

3 1.7 813

12 8.0 672

125 9.72

2 477. 2957

5157 .7578

nccl-IB

0.0 928

0.5 618

2.1 134

7.1 768

120 .131

260. 2628

518 .8091

nccl-GDR (PXN<->PXN)

0.5 541

45. 601

9.3 636

1 9.3 071

10 8.11

280. 0556

527 .9732

torchrpc-TCP

5.6 691

5.4 707

1 4.0 155

3 9.4 443

580 .333

1 154. 0793

2297 .3776

torchrpc-IB

2 1.3 884

4.4 093

5.9 105

2 2.3 012

130 .249

236. 8084

477 .2389

torchrpc-GDR (PXN<->PXN)

2 0.5 018

2 3.2 081

1 5.6 427

7. 535 7*

48. 7812

77. 2657

143 .4112

节点内 P2P 测试

test case(unit:ms)

1.25 KB

20.00 KB

1.25 MB

10.00 MB

4 0.00 M

6 40.00 M

1 .25GB

shm

0. 3605

0.352

0. 9924

7 .1229

47. 9575

798 .8635

154 8.782

nccl-nvlink

0. 1969

0 .1104

0. 2162

0 .3285

0. 4532

3 .3166

5 .3828

cud a-shared-tensor

0. 5307

0.578

0. 9643

0 .5908

1. 2449

5 .3707

9.686

Atari 训练任务测试

测试代码: dizoo/atari/example/atari_dqn_dist_rdma.py

  • memory: “32Gi”

  • cpu: 16

  • gpu: A100

test case(unit:s)

100 epoch avg time

TCP-nng

127.64

torchrpc-CP

29.3906

torchrpc-IB

28.7763

使用

cli-ditask 引入了新的命令行参数:

  • –mq_type :引入了 cuda 和 torchrpc:cpu 选项:

    • cuda :使用 torchrpc ,需要设置 device_map ,如果集群配置了 GPU direct RDMA 则可以自动使用。

    • torchrpc:cpu :使用 torchrpc ,但不设置 device_map 。 GPU数据会被拷贝到内存进行通信。

  • –init-method :init_rpc的初始化入口(如果选择 torchrpc 作为后端则为必填项),同 torch.distributed.init_process_group 中的 init-method 参数。

  • –local-cuda-devices :设置当前进程可用GPU设备(可选,只有在 mq_type 为 cuda 有效,默认为所有可见设备),用逗号分隔的 int 列表。

  • –cuda-device-map :用于设置 torchrpc 的 device_map,(可选,只有在 mq_type 为 cuda 有效,默认会映射全部可用 GPU ,使得各 GPU 之间可以 P2P ),格式如下:

    Format:
    <Peer Node ID>_<Local GPU Local Rank>_<Peer GPU Local Rank>,[...]
    example:
    --cuda-device-map=1_0_1,2_0_2,0_0_0
    

一个具体的例子:

export INIT_METHOD="tcp://XX.XX.XX.XX:12345"

# learner 位于节点 0 ,使用 GPU0 ,并建立和节点1的GPU0间的P2P映射
ditask --package . \
    --main atari_dqn_dist_rdma.main \
    --parallel-workers 1 \
    --labels learner \
    --mq-type torchrpc:cuda \
    --init-method=${INIT_METHOD} \
    --cuda-device-map 1_0_0 \
    --node-ids 0

# collector 位于节点 1 ,使用 GPU0 ,并建立和节点0的GPU0间的P2P映射
ditask --package . \
    --main atari_dqn_dist_rdma.main \
    --parallel-workers 1 \
    --labels collector \
    --mq-type torchrpc \
    --init-method=${INIT_METHOD} \
    --global_rank 1 \
    --attach-to 0_0_0 \
    --node-ids 1

注意事项

如果您在K8S或其他容器集群环境下使用 DI-engine ,请使用 opendilab 提供的镜像,或参照此处的 Dockerfile 。否则 torchrpc 可能无法正常工作。

多IB设备

如果您的集群环境有多张 HCA 设备,torchrpc 可能不会正常工作,这一问题是由 torchrpc 底层的 tensorpip 代码缺陷导致的,我们在 opendilab 的镜像中修复了这一问题。如果您无法使用我们的镜像,请保证您机器上的 HCA 的端口都处于可用状态。

容器环境

torchrpc 无法判断自己是否处于容器环境,我们的opendilab的镜像增加了容器环境的判断功能,避免 torchrpc 在容器环境下进行 GPU 设备映射导致的初始化错误。

和fork()混合使用

torchrpc 没有考虑到进程混合使用 RDMA 和 fork 的情况。如果在使用 RDMA 时没有进行相应的初始化措施,使用 fork 会出现严重问题, 请参考。 因此,如果您在 IB/RoCE 网络环境下使用 torchrpc,并需要配合 fork 混合使用,请指定环境变量 IBV_FORK_SAFE=1RDMAV_FORK_SAFE=1

反馈

因为目前 tensorpipe 不会有活跃的开发计划, 如果您遇到和 torchrpc 有关的问题或 bug , 您可以在 DI-engine 社区中提 issue 。 同时我们正在积极和 tensorpipe 社区沟通并跟踪上述问题的修复情况,如果有任何修复我们会第一时间进行更新。