漢なら 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 すばらしい.