LoginSignup
38
36

More than 5 years have passed since last update.

Python で rsocket で通信が爆速でやばい.

Posted at

漢なら RDMA でデータ送りたいですね!

とりあえず手っ取り早く rsocket http://syoyo.wordpress.com/2012/12/06/rsocket-new-way-of-rdma-aware-programming/ を使い, 既存の python スクリプトで高速転送を実現してみましょう.

構成

        IPoIB        1 GbE
Server: 172.24.0.1  192.168.11.1
Client: 172.24.0.2  192.168.11.2

Server と Client は InfiniBand QDR と, 1 GbE で物理的に繋がっています.
InfiniBand のレイヤは IPoIB で繋がっているものとします.

テストスクリプト

Client から 1GB のデータを送り, Server 側はそれを受け取るだけというスクリプトです(単方向データ通信).

# server.py
import socket

import itertools

HOST = ''                 
PORT = 8081               
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
ret = []
while 1:
    #print "recv"
    data = conn.recv(1024*1024*1024)
    #print "len:%d", len(data)
    if not data: break
    #ret.append(data)

conn.close()
print "done"
# client.py
import socket
from datetime import datetime
from datetime import timedelta

def millis(s, e):
    dt = e - s
    ms = (dt.days * 24 * 60 * 60 + dt.seconds) * 1000 + dt.microseconds / 1000.0
    return ms

HOST = '192.168.11.1'    # GbE remote host
#HOST = '172.24.0.1'    # IPoIB remote host
PORT = 8081             
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
d = "a" * 1024*1024*1024
print "sending..."
start_ms = datetime.now()
s.sendall(d)
end_ms = datetime.now()
print "sent"
s.close()
print "elap: %d [ms]" % millis(start_ms, end_ms)

1 GbE での接続では...

# server 側で実行
$ python server.py

# client 側で実行
$ python clientpy

elap: 9109 [ms]

1GbE だと理論上限が 100MB/s くらいですから期待通りですね.

IPoIB だと…

elap: 23711 [ms]

あらなんだか IPoIB そのままだと 40 MB/s くらいと遅いですね.
1GB のデータなので少なくとも 10000 ms(10 secs, 100MB/s) くらいで転送してもらいたいところ.

rsocket をつかう.

LD_PRELOAD で dll 差し替えにより, 既存 socket プログラムでも RDMA を使うことができるようになります.
(必ずしも全てではないが, iperf なども動きます)

また, RDMA が使える物理的経路(InfiniBand, etc)が IPoIB で見えている必要があります.

今回はこの LD_PRELOAD による方法を使います.
使った rsocket(librdmacm) のバージョンは 1.0.18 です.

# Server
$ LD_PRELOAD=/usr/local/lib/rsocket/librspreload.so python server.py
# Client
$ LD_PRELOAD=/usr/local/lib/rsocket/librspreload.so python client.py

elap: 695 [ms]

Super cool! 1GB のデータが 0.7 秒 で送れました. 1.4 GB/s ほど. これだと python で GB 単位のデータの処理(バイト配列処理)をするほうが時間かかってしまうレベルですね.

TODO

  • バッファに mmap を使ってより python 側の処理を軽くできないか検討してみる.

まとめ

rsocket すばらしい.

38
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
36