首先,我们来看看数据传输速率。为了测试tensor在两台机器之间的传输速率,我们使用了一个简单的测试程序。两台机器都配备了万兆以太网网卡。通过在两台机器上运行测试程序的worker和ps,我们可以模拟实际的分布式训练环境。
在测试中,worker会反复将自己的variable传输给ps。我们设置了variable的大小为100MB,并进行了100次传输。测试结果显示,传输速率大约为173MB/s。同时,使用ifstat工具监测网络传输性能,数据传输速率也在170mbps左右。尽管这两个结果有些许差异,但都与10Gbps网卡的理论传输速率1.25GBps有较大差距,显示出网卡的利用率并不高。
接下来,我们单独测试了grpc的传输效率。为此,我们使用了另一个测试程序,其设计要点包括尽量减少额外的操作开销、直接使用grpc的ByteBuffer、以及允许多个工作线程等。测试中,Client向server发送了100MB的数据,共进行了1000次发送。
通过ifstat工具观察,我们发现数据传输速率约为170MBps,这与之前测试tensor传输的速率基本一致。这表明,性能问题可能确实与grpc有关。
那么,为什么grpc会这么慢呢?为了进一步分析,我们使用了iperf工具对网络的throughput进行了单独测试。测试结果显示,网络的传输速率并没有达到理论值,这也暗示了可能存在的瓶颈。
综合上述测试,我们可以推测,grpc的传输效率可能受到多种因素的影响。首先,grpc在传输数据时会增加额外的header信息,这可能会影响传输效率。其次,grpc的线程模型和并发处理机制可能没有得到最优化,导致实际传输速率低于理论值。
此外,还有可能是因为网络设备和操作系统对grpc的支持不够完善,或者是一些未知的内部实现问题。不过,这些只是推测,具体的原因还需深入研究和分析。
总的来说,tensorflow分布式训练中grpc的传输效率确实存在一些问题。对于开发者来说,了解这些问题的存在,并在实际应用中采取相应的优化措施,将有助于提高分布式训练的整体性能。
TensorFlow 网络传输
0. 写在前面
tensorflow分布式训练时,grpc的 慢 一直都被很多人所诟病。在早期的版本中,由于实现的一些原因,的确存在一些性能问题(可以参见这个 issue )。
但随着项目的迭代,现在性能如何,就有些莫衷一是了。这里通过对两个项目master分支代码的一些测试,希望能探讨下这些问题。
1. 直观的看传输速率
这里先用 一个测试程序 测试下tensor在两个机器中的传输速率。测试使用的两台机器配置的都是万兆以太网的网卡:
[work@host benchtools]$ ethtool eth0
Settings for eth0:
...
Speed: 10000Mb/s
...
在两台机器上分别跑测试程序的worker和ps:
[host1] Python tensor_transfer_throughput.py --ps_hosts=host1:12222 --worker_hosts=host2:12222 --job=ps --task=0
[host2] python tensor_transfer_throughput.py --ps_hosts=host1:12222 --worker_hosts=host2:12222 --data_mb=100 --job=worker --task=0 --iters=100
测试程序干的事情很简单:在ps和worker上各创建一个相同大小的variable, 然后worker反复将自己的variable assign给ps。在上面的测试中,我们将variable的大小设置为100M,传输次数为100。
测试结果在worker运行结束后可以看到:
[host2] python tensor_transfer_throughput.py --ps_hosts=host1:12222 --worker_hosts=host2:12222 --data_mb=100 --job=worker --task=0 --iters=100
....
transfer rate: 173.488801 MB/s
利用ifstat工具也可以看到网络的传输性能:
[hosts1]$ ./ifstat
eth0 eth1
KB/s in KB/s out KB/s in KB/s out
191.95 176435.6 0.00 0.00
206.18 170675.3 0.00 0.00
222.45 220156.5 0.00 0.00
162.84 169024.8 0.00 0.00
224.44 211070.7 0.00 0.00
可以看到两种测试的througput效果差不多。理论上来说ifstat可能会比worker的输出稍微大一点,因为grpc要为每次传输额外添加一些header信息。但和100MB的数据相比,应该可以忽略不计。
但无论是哪个结果,离理论值的1.25GBps(10Gbps)差距仍旧非常大。所以初步来看,网卡的利用率是比较低的。
2. 单独测试grpc
为了验证问题是不是出在grpc这里,我利用 另一个测试程序 ,来测试grpc本身的传输效率。
程序不太复杂,要点包括:
client和server端的功能要简单,尽量减少额外操作所带来的时间开销:client只负责无脑发送,server端也要直接丢弃收到的数据。
直接利用grpc的ByteBuffer,从而避免掉在发送和接收时的memcpy。这点和tensorflow发送tensor的流程也是一致的。
server端可以创建多个completion queue, 从而可以指定多个worker线程。
client利用异步接口。可以指定传输并发度,也可以允许grpc创建多个channel。
可以指定发送数据和响应数据块的大小。
然后将程序部署到两台机器上开始测试。client每次向server发送100M数据,共发送1000条:
[host1] ./grpc_raw --job_type=server --server_threads=1 --message_size=10
[host2] ./grpc_raw --job_type=client --job_type=client --target_ip=host1 --total_message=1000 --message_size=104857600
利用ifstat看结果:
[work@host2 benchtools]$ ./ifstat
eth0 eth1
KB/s in KB/s out KB/s in KB/s out
162.05 198529.9 0.00 0.00
128.67 150799.5 0.00 0.00
196.09 203136.0 0.00 0.00
169.20 192864.8 0.00 0.00
130.67 146532.7 0.00 0.00
可以看到和测tensor传输时类似,也是170MBps左右,离1.25GBps的理论值也差距较大。
3. 为什么慢
为了进一步确定问题,我用 iperf 工具对网络的throughput做了单独的测试:
[host1] ./iperf3 -s -i 5
[host2] ./iperf3 -c host1 -i 5 -t 1000
测试结果如下: