chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:35:51 +08:00
commit c36a561cd8
2172 changed files with 455595 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+97
View File
@@ -0,0 +1,97 @@
import operator
import os
import unittest
import backend as F
import dgl
import pytest
from utils import create_random_graph, generate_ip_config, reset_envs
dist_g = None
def rand_mask(shape, dtype):
return F.randn(shape) > 0
@unittest.skipIf(
dgl.backend.backend_name == "tensorflow",
reason="TF doesn't support some of operations in DistGraph",
)
@unittest.skipIf(
dgl.backend.backend_name == "mxnet", reason="Turn off Mxnet support"
)
def setup_module():
global dist_g
reset_envs()
os.environ["DGL_DIST_MODE"] = "standalone"
dist_g = create_random_graph(10000)
# Partition the graph.
num_parts = 1
graph_name = "dist_graph_test_3"
dist_g.ndata["features"] = F.unsqueeze(F.arange(0, dist_g.num_nodes()), 1)
dist_g.edata["features"] = F.unsqueeze(F.arange(0, dist_g.num_edges()), 1)
dgl.distributed.partition_graph(
dist_g, graph_name, num_parts, "/tmp/dist_graph"
)
dgl.distributed.initialize("kv_ip_config.txt")
dist_g = dgl.distributed.DistGraph(
graph_name, part_config="/tmp/dist_graph/{}.json".format(graph_name)
)
dist_g.edata["mask1"] = dgl.distributed.DistTensor(
(dist_g.num_edges(),), F.bool, init_func=rand_mask
)
dist_g.edata["mask2"] = dgl.distributed.DistTensor(
(dist_g.num_edges(),), F.bool, init_func=rand_mask
)
def check_binary_op(key1, key2, key3, op):
for i in range(0, dist_g.num_edges(), 1000):
i_end = min(i + 1000, dist_g.num_edges())
assert F.array_equal(
dist_g.edata[key3][i:i_end],
op(dist_g.edata[key1][i:i_end], dist_g.edata[key2][i:i_end]),
)
# Test with different index dtypes. int32 is not supported.
with pytest.raises(
dgl.utils.internal.InconsistentDtypeException,
match="DGL now requires the input tensor to have",
):
_ = dist_g.edata[key3][F.tensor([100, 20, 10], F.int32)]
_ = dist_g.edata[key3][F.tensor([100, 20, 10], F.int64)]
@unittest.skipIf(
dgl.backend.backend_name == "tensorflow",
reason="TF doesn't support some of operations in DistGraph",
)
@unittest.skipIf(
dgl.backend.backend_name == "mxnet", reason="Turn off Mxnet support"
)
def test_op():
dist_g.edata["mask3"] = dist_g.edata["mask1"] | dist_g.edata["mask2"]
check_binary_op("mask1", "mask2", "mask3", operator.or_)
@unittest.skipIf(
dgl.backend.backend_name == "tensorflow",
reason="TF doesn't support some of operations in DistGraph",
)
@unittest.skipIf(
dgl.backend.backend_name == "mxnet", reason="Turn off Mxnet support"
)
def teardown_module():
# Since there are two tests in one process, this is needed to make sure
# the client exits properly.
dgl.distributed.exit_client()
if __name__ == "__main__":
setup_module()
test_op()
teardown_module()
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+390
View File
@@ -0,0 +1,390 @@
import multiprocessing as mp
import os
import time
import unittest
import backend as F
import dgl
from numpy.testing import assert_array_equal
from utils import generate_ip_config, reset_envs
# Create an one-part Graph
node_map = {"_N": F.tensor([[0, 6]], F.int64)}
edge_map = {("_N", "_E", "_N"): F.tensor([[0, 7]], F.int64)}
global_nid = F.tensor([0, 1, 2, 3, 4, 5], F.int64)
global_eid = F.tensor([0, 1, 2, 3, 4, 5, 6], F.int64)
g = dgl.graph([])
g.add_nodes(6)
g.add_edges(0, 1) # 0
g.add_edges(0, 2) # 1
g.add_edges(0, 3) # 2
g.add_edges(2, 3) # 3
g.add_edges(1, 1) # 4
g.add_edges(0, 4) # 5
g.add_edges(2, 5) # 6
g.ndata[dgl.NID] = global_nid
g.edata[dgl.EID] = global_eid
gpb = dgl.distributed.graph_partition_book.RangePartitionBook(
part_id=0,
num_parts=1,
node_map=node_map,
edge_map=edge_map,
ntypes={ntype: i for i, ntype in enumerate(g.ntypes)},
etypes={etype: i for i, etype in enumerate(g.canonical_etypes)},
)
node_policy = dgl.distributed.PartitionPolicy(
policy_str="node~_N", partition_book=gpb
)
edge_policy = dgl.distributed.PartitionPolicy(
policy_str="edge~_N:_E:_N", partition_book=gpb
)
data_0 = F.tensor(
[[1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]],
F.float32,
)
data_0_1 = F.tensor([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], F.float32)
data_0_2 = F.tensor([1, 2, 3, 4, 5, 6], F.int32)
data_0_3 = F.tensor([1, 2, 3, 4, 5, 6], F.int64)
data_1 = F.tensor(
[
[2.0, 2.0],
[2.0, 2.0],
[2.0, 2.0],
[2.0, 2.0],
[2.0, 2.0],
[2.0, 2.0],
[2.0, 2.0],
],
F.float32,
)
data_2 = F.tensor(
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
F.float32,
)
def init_zero_func(shape, dtype):
return F.zeros(shape, dtype, F.cpu())
def udf_push(target, name, id_tensor, data_tensor):
target[name][id_tensor] = data_tensor * data_tensor
def add_push(target, name, id_tensor, data_tensor):
target[name][id_tensor] += data_tensor
@unittest.skipIf(
os.name == "nt" or os.getenv("DGLBACKEND") == "tensorflow",
reason="Do not support windows and TF yet",
)
def test_partition_policy():
assert node_policy.part_id == 0
assert edge_policy.part_id == 0
local_nid = node_policy.to_local(F.tensor([0, 1, 2, 3, 4, 5]))
local_eid = edge_policy.to_local(F.tensor([0, 1, 2, 3, 4, 5, 6]))
assert_array_equal(
F.asnumpy(local_nid), F.asnumpy(F.tensor([0, 1, 2, 3, 4, 5], F.int64))
)
assert_array_equal(
F.asnumpy(local_eid),
F.asnumpy(F.tensor([0, 1, 2, 3, 4, 5, 6], F.int64)),
)
nid_partid = node_policy.to_partid(F.tensor([0, 1, 2, 3, 4, 5], F.int64))
eid_partid = edge_policy.to_partid(F.tensor([0, 1, 2, 3, 4, 5, 6], F.int64))
assert_array_equal(
F.asnumpy(nid_partid), F.asnumpy(F.tensor([0, 0, 0, 0, 0, 0], F.int64))
)
assert_array_equal(
F.asnumpy(eid_partid),
F.asnumpy(F.tensor([0, 0, 0, 0, 0, 0, 0], F.int64)),
)
assert node_policy.get_part_size() == len(local_nid)
assert edge_policy.get_part_size() == len(local_eid)
def start_server(server_id, num_clients, num_servers):
# Init kvserver
print("Sleep 5 seconds to test client re-connect.")
time.sleep(5)
kvserver = dgl.distributed.KVServer(
server_id=server_id,
ip_config="kv_ip_config.txt",
num_servers=num_servers,
num_clients=num_clients,
)
kvserver.add_part_policy(node_policy)
kvserver.add_part_policy(edge_policy)
if kvserver.is_backup_server():
kvserver.init_data("data_0", "node~_N")
kvserver.init_data("data_0_1", "node~_N")
kvserver.init_data("data_0_2", "node~_N")
kvserver.init_data("data_0_3", "node~_N")
else:
kvserver.init_data("data_0", "node~_N", data_0)
kvserver.init_data("data_0_1", "node~_N", data_0_1)
kvserver.init_data("data_0_2", "node~_N", data_0_2)
kvserver.init_data("data_0_3", "node~_N", data_0_3)
# start server
server_state = dgl.distributed.ServerState(
kv_store=kvserver, local_g=None, partition_book=None
)
dgl.distributed.start_server(
server_id=server_id,
ip_config="kv_ip_config.txt",
num_servers=num_servers,
num_clients=num_clients,
server_state=server_state,
)
def start_server_mul_role(server_id, num_clients, num_servers):
# Init kvserver
kvserver = dgl.distributed.KVServer(
server_id=server_id,
ip_config="kv_ip_mul_config.txt",
num_servers=num_servers,
num_clients=num_clients,
)
kvserver.add_part_policy(node_policy)
if kvserver.is_backup_server():
kvserver.init_data("data_0", "node~_N")
else:
kvserver.init_data("data_0", "node~_N", data_0)
# start server
server_state = dgl.distributed.ServerState(
kv_store=kvserver, local_g=None, partition_book=None
)
dgl.distributed.start_server(
server_id=server_id,
ip_config="kv_ip_mul_config.txt",
num_servers=num_servers,
num_clients=num_clients,
server_state=server_state,
)
def start_client(num_clients, num_servers):
os.environ["DGL_DIST_MODE"] = "distributed"
# Note: connect to server first !
dgl.distributed.initialize(ip_config="kv_ip_config.txt")
# Init kvclient
kvclient = dgl.distributed.KVClient(
ip_config="kv_ip_config.txt", num_servers=num_servers
)
kvclient.map_shared_data(partition_book=gpb)
assert dgl.distributed.get_num_client() == num_clients
kvclient.init_data(
name="data_1",
shape=F.shape(data_1),
dtype=F.dtype(data_1),
part_policy=edge_policy,
init_func=init_zero_func,
)
kvclient.init_data(
name="data_2",
shape=F.shape(data_2),
dtype=F.dtype(data_2),
part_policy=node_policy,
init_func=init_zero_func,
)
# Test data_name_list
name_list = kvclient.data_name_list()
print(name_list)
assert "data_0" in name_list
assert "data_0_1" in name_list
assert "data_0_2" in name_list
assert "data_0_3" in name_list
assert "data_1" in name_list
assert "data_2" in name_list
# Test get_meta_data
meta = kvclient.get_data_meta("data_0")
dtype, shape, policy = meta
assert dtype == F.dtype(data_0)
assert shape == F.shape(data_0)
assert policy.policy_str == "node~_N"
meta = kvclient.get_data_meta("data_0_1")
dtype, shape, policy = meta
assert dtype == F.dtype(data_0_1)
assert shape == F.shape(data_0_1)
assert policy.policy_str == "node~_N"
meta = kvclient.get_data_meta("data_0_2")
dtype, shape, policy = meta
assert dtype == F.dtype(data_0_2)
assert shape == F.shape(data_0_2)
assert policy.policy_str == "node~_N"
meta = kvclient.get_data_meta("data_0_3")
dtype, shape, policy = meta
assert dtype == F.dtype(data_0_3)
assert shape == F.shape(data_0_3)
assert policy.policy_str == "node~_N"
meta = kvclient.get_data_meta("data_1")
dtype, shape, policy = meta
assert dtype == F.dtype(data_1)
assert shape == F.shape(data_1)
assert policy.policy_str == "edge~_N:_E:_N"
meta = kvclient.get_data_meta("data_2")
dtype, shape, policy = meta
assert dtype == F.dtype(data_2)
assert shape == F.shape(data_2)
assert policy.policy_str == "node~_N"
# Test push and pull
id_tensor = F.tensor([0, 2, 4], F.int64)
data_tensor = F.tensor([[6.0, 6.0], [6.0, 6.0], [6.0, 6.0]], F.float32)
kvclient.push(name="data_0", id_tensor=id_tensor, data_tensor=data_tensor)
kvclient.push(name="data_1", id_tensor=id_tensor, data_tensor=data_tensor)
kvclient.push(name="data_2", id_tensor=id_tensor, data_tensor=data_tensor)
res = kvclient.pull(name="data_0", id_tensor=id_tensor)
assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
res = kvclient.pull(name="data_1", id_tensor=id_tensor)
assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
res = kvclient.pull(name="data_2", id_tensor=id_tensor)
assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
# Register new push handler
kvclient.register_push_handler("data_0", udf_push)
kvclient.register_push_handler("data_1", udf_push)
kvclient.register_push_handler("data_2", udf_push)
# Test push and pull
kvclient.push(name="data_0", id_tensor=id_tensor, data_tensor=data_tensor)
kvclient.push(name="data_1", id_tensor=id_tensor, data_tensor=data_tensor)
kvclient.push(name="data_2", id_tensor=id_tensor, data_tensor=data_tensor)
kvclient.barrier()
data_tensor = data_tensor * data_tensor
res = kvclient.pull(name="data_0", id_tensor=id_tensor)
assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
res = kvclient.pull(name="data_1", id_tensor=id_tensor)
assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
res = kvclient.pull(name="data_2", id_tensor=id_tensor)
assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
# Test delete data
kvclient.delete_data("data_0")
kvclient.delete_data("data_1")
kvclient.delete_data("data_2")
# Register new push handler
kvclient.init_data(
name="data_3",
shape=F.shape(data_2),
dtype=F.dtype(data_2),
part_policy=node_policy,
init_func=init_zero_func,
)
kvclient.register_push_handler("data_3", add_push)
data_tensor = F.tensor([[6.0, 6.0], [6.0, 6.0], [6.0, 6.0]], F.float32)
kvclient.barrier()
time.sleep(kvclient.client_id + 1)
print("add...")
kvclient.push(name="data_3", id_tensor=id_tensor, data_tensor=data_tensor)
kvclient.barrier()
res = kvclient.pull(name="data_3", id_tensor=id_tensor)
data_tensor = data_tensor * num_clients
assert_array_equal(F.asnumpy(res), F.asnumpy(data_tensor))
def start_client_mul_role(i):
os.environ["DGL_DIST_MODE"] = "distributed"
# Initialize creates kvstore !
dgl.distributed.initialize(ip_config="kv_ip_mul_config.txt")
if i == 0: # block one trainer
time.sleep(5)
kvclient = dgl.distributed.kvstore.get_kvstore()
kvclient.barrier()
print("i: %d role: %s" % (i, kvclient.role))
assert dgl.distributed.role.get_num_trainers() == 2
assert dgl.distributed.role.get_trainer_rank() < 2
print(
"trainer rank: %d, global rank: %d"
% (
dgl.distributed.role.get_trainer_rank(),
dgl.distributed.role.get_global_rank(),
)
)
dgl.distributed.exit_client()
@unittest.skipIf(
os.name == "nt" or os.getenv("DGLBACKEND") == "tensorflow",
reason="Do not support windows and TF yet",
)
def test_kv_store():
reset_envs()
num_servers = 2
num_clients = 2
generate_ip_config("kv_ip_config.txt", 1, num_servers)
ctx = mp.get_context("spawn")
pserver_list = []
pclient_list = []
os.environ["DGL_NUM_SERVER"] = str(num_servers)
for i in range(num_servers):
pserver = ctx.Process(
target=start_server, args=(i, num_clients, num_servers)
)
pserver.start()
pserver_list.append(pserver)
for i in range(num_clients):
pclient = ctx.Process(
target=start_client, args=(num_clients, num_servers)
)
pclient.start()
pclient_list.append(pclient)
for i in range(num_clients):
pclient_list[i].join()
for i in range(num_servers):
pserver_list[i].join()
@unittest.skipIf(
os.name == "nt" or os.getenv("DGLBACKEND") == "tensorflow",
reason="Do not support windows and TF yet",
)
def test_kv_multi_role():
reset_envs()
num_servers = 2
num_trainers = 2
num_samplers = 2
generate_ip_config("kv_ip_mul_config.txt", 1, num_servers)
# There are two trainer processes and each trainer process has two sampler processes.
num_clients = num_trainers * (1 + num_samplers)
ctx = mp.get_context("spawn")
pserver_list = []
pclient_list = []
os.environ["DGL_NUM_SAMPLER"] = str(num_samplers)
os.environ["DGL_NUM_SERVER"] = str(num_servers)
for i in range(num_servers):
pserver = ctx.Process(
target=start_server_mul_role, args=(i, num_clients, num_servers)
)
pserver.start()
pserver_list.append(pserver)
for i in range(num_trainers):
pclient = ctx.Process(target=start_client_mul_role, args=(i,))
pclient.start()
pclient_list.append(pclient)
for i in range(num_trainers):
pclient_list[i].join()
for i in range(num_servers):
pserver_list[i].join()
if __name__ == "__main__":
test_partition_policy()
test_kv_store()
test_kv_multi_role()
File diff suppressed because it is too large Load Diff
+425
View File
@@ -0,0 +1,425 @@
import multiprocessing as mp
import os
import socket
import time
import unittest
import backend as F
import dgl
import pytest
from numpy.testing import assert_array_equal
from utils import generate_ip_config, reset_envs
if os.name != "nt":
import fcntl
import struct
INTEGER = 2
STR = "hello world!"
HELLO_SERVICE_ID = 901231
TENSOR = F.zeros((1000, 1000), F.int64, F.cpu())
def foo(x, y):
assert x == 123
assert y == "abc"
class MyRequest(dgl.distributed.Request):
def __init__(self):
self.x = 123
self.y = "abc"
self.z = F.randn((3, 4))
self.foo = foo
def __getstate__(self):
return self.x, self.y, self.z, self.foo
def __setstate__(self, state):
self.x, self.y, self.z, self.foo = state
def process_request(self, server_state):
pass
class MyResponse(dgl.distributed.Response):
def __init__(self):
self.x = 432
def __getstate__(self):
return self.x
def __setstate__(self, state):
self.x = state
def simple_func(tensor):
return tensor
class HelloResponse(dgl.distributed.Response):
def __init__(self, hello_str, integer, tensor):
self.hello_str = hello_str
self.integer = integer
self.tensor = tensor
def __getstate__(self):
return self.hello_str, self.integer, self.tensor
def __setstate__(self, state):
self.hello_str, self.integer, self.tensor = state
class HelloRequest(dgl.distributed.Request):
def __init__(self, hello_str, integer, tensor, func):
self.hello_str = hello_str
self.integer = integer
self.tensor = tensor
self.func = func
def __getstate__(self):
return self.hello_str, self.integer, self.tensor, self.func
def __setstate__(self, state):
self.hello_str, self.integer, self.tensor, self.func = state
def process_request(self, server_state):
assert self.hello_str == STR
assert self.integer == INTEGER
new_tensor = self.func(self.tensor)
res = HelloResponse(self.hello_str, self.integer, new_tensor)
return res
TIMEOUT_SERVICE_ID = 123456789
TIMEOUT_META = "timeout_test"
class TimeoutResponse(dgl.distributed.Response):
def __init__(self, meta):
self.meta = meta
def __getstate__(self):
return self.meta
def __setstate__(self, state):
self.meta = state
class TimeoutRequest(dgl.distributed.Request):
def __init__(self, meta, timeout, response=True):
self.meta = meta
self.timeout = timeout
self.response = response
def __getstate__(self):
return self.meta, self.timeout, self.response
def __setstate__(self, state):
self.meta, self.timeout, self.response = state
def process_request(self, server_state):
assert self.meta == TIMEOUT_META
# convert from milliseconds to seconds
time.sleep(self.timeout / 1000)
if not self.response:
return None
res = TimeoutResponse(self.meta)
return res
def start_server(
num_clients,
ip_config,
server_id=0,
num_servers=1,
):
print("Sleep 1 seconds to test client re-connect.")
time.sleep(1)
server_state = dgl.distributed.ServerState(
None, local_g=None, partition_book=None
)
dgl.distributed.register_service(
HELLO_SERVICE_ID, HelloRequest, HelloResponse
)
dgl.distributed.register_service(
TIMEOUT_SERVICE_ID, TimeoutRequest, TimeoutResponse
)
print("Start server {}".format(server_id))
dgl.distributed.start_server(
server_id=server_id,
ip_config=ip_config,
num_servers=num_servers,
num_clients=num_clients,
server_state=server_state,
)
def start_client(ip_config, group_id=0, num_servers=1):
dgl.distributed.register_service(
HELLO_SERVICE_ID, HelloRequest, HelloResponse
)
dgl.distributed.connect_to_server(
ip_config=ip_config,
num_servers=num_servers,
group_id=group_id,
)
req = HelloRequest(STR, INTEGER, TENSOR, simple_func)
# test send and recv
dgl.distributed.send_request(0, req)
res = dgl.distributed.recv_response()
assert res.hello_str == STR
assert res.integer == INTEGER
assert_array_equal(F.asnumpy(res.tensor), F.asnumpy(TENSOR))
# test remote_call
target_and_requests = []
for i in range(10):
target_and_requests.append((0, req))
res_list = dgl.distributed.remote_call(target_and_requests)
for res in res_list:
assert res.hello_str == STR
assert res.integer == INTEGER
assert_array_equal(F.asnumpy(res.tensor), F.asnumpy(TENSOR))
# test send_request_to_machine
dgl.distributed.send_request_to_machine(0, req)
res = dgl.distributed.recv_response()
assert res.hello_str == STR
assert res.integer == INTEGER
assert_array_equal(F.asnumpy(res.tensor), F.asnumpy(TENSOR))
# test remote_call_to_machine
target_and_requests = []
for i in range(10):
target_and_requests.append((0, req))
res_list = dgl.distributed.remote_call_to_machine(target_and_requests)
for res in res_list:
assert res.hello_str == STR
assert res.integer == INTEGER
assert_array_equal(F.asnumpy(res.tensor), F.asnumpy(TENSOR))
def start_client_timeout(ip_config, group_id=0, num_servers=1):
dgl.distributed.register_service(
TIMEOUT_SERVICE_ID, TimeoutRequest, TimeoutResponse
)
dgl.distributed.connect_to_server(
ip_config=ip_config,
num_servers=num_servers,
group_id=group_id,
)
timeout = 1 * 1000 # milliseconds
req = TimeoutRequest(TIMEOUT_META, timeout)
# test send and recv
dgl.distributed.send_request(0, req)
res = dgl.distributed.recv_response(timeout=int(timeout / 2))
assert res is None
res = dgl.distributed.recv_response()
assert res.meta == TIMEOUT_META
# test remote_call
req = TimeoutRequest(TIMEOUT_META, timeout, response=False)
target_and_requests = []
for i in range(3):
target_and_requests.append((0, req))
expect_except = False
try:
res_list = dgl.distributed.remote_call(
target_and_requests, timeout=int(timeout / 2)
)
except dgl.DGLError:
expect_except = True
assert expect_except
# test send_request_to_machine
req = TimeoutRequest(TIMEOUT_META, timeout)
dgl.distributed.send_request_to_machine(0, req)
res = dgl.distributed.recv_response(timeout=int(timeout / 2))
assert res is None
res = dgl.distributed.recv_response()
assert res.meta == TIMEOUT_META
# test remote_call_to_machine
req = TimeoutRequest(TIMEOUT_META, timeout, response=False)
target_and_requests = []
for i in range(3):
target_and_requests.append((0, req))
expect_except = False
try:
res_list = dgl.distributed.remote_call_to_machine(
target_and_requests, timeout=int(timeout / 2)
)
except dgl.DGLError:
expect_except = True
assert expect_except
@unittest.skipIf(os.name == "nt", reason="Do not support windows yet")
def test_rpc_timeout():
reset_envs()
os.environ["DGL_DIST_MODE"] = "distributed"
ip_config = "rpc_ip_config.txt"
generate_ip_config(ip_config, 1, 1)
ctx = mp.get_context("spawn")
pserver = ctx.Process(target=start_server, args=(1, ip_config, 0, 1))
pclient = ctx.Process(target=start_client_timeout, args=(ip_config, 0, 1))
pserver.start()
pclient.start()
pserver.join()
pclient.join()
def test_serialize():
reset_envs()
os.environ["DGL_DIST_MODE"] = "distributed"
from dgl.distributed.rpc import (
deserialize_from_payload,
serialize_to_payload,
)
SERVICE_ID = 12345
dgl.distributed.register_service(SERVICE_ID, MyRequest, MyResponse)
req = MyRequest()
data, tensors = serialize_to_payload(req)
req1 = deserialize_from_payload(MyRequest, data, tensors)
req1.foo(req1.x, req1.y)
assert req.x == req1.x
assert req.y == req1.y
assert F.array_equal(req.z, req1.z)
res = MyResponse()
data, tensors = serialize_to_payload(res)
res1 = deserialize_from_payload(MyResponse, data, tensors)
assert res.x == res1.x
def test_rpc_msg():
reset_envs()
os.environ["DGL_DIST_MODE"] = "distributed"
from dgl.distributed.rpc import (
deserialize_from_payload,
RPCMessage,
serialize_to_payload,
)
SERVICE_ID = 32452
dgl.distributed.register_service(SERVICE_ID, MyRequest, MyResponse)
req = MyRequest()
data, tensors = serialize_to_payload(req)
rpcmsg = RPCMessage(SERVICE_ID, 23, 0, 1, data, tensors)
assert rpcmsg.service_id == SERVICE_ID
assert rpcmsg.msg_seq == 23
assert rpcmsg.client_id == 0
assert rpcmsg.server_id == 1
assert len(rpcmsg.data) == len(data)
assert len(rpcmsg.tensors) == 1
assert F.array_equal(rpcmsg.tensors[0], req.z)
@unittest.skipIf(os.name == "nt", reason="Do not support windows yet")
def test_multi_client():
reset_envs()
os.environ["DGL_DIST_MODE"] = "distributed"
ip_config = "rpc_ip_config_mul_client.txt"
generate_ip_config(ip_config, 1, 1)
ctx = mp.get_context("spawn")
num_clients = 20
pserver = ctx.Process(
target=start_server,
args=(num_clients, ip_config, 0, 1),
)
pclient_list = []
for i in range(num_clients):
pclient = ctx.Process(target=start_client, args=(ip_config, 0, 1))
pclient_list.append(pclient)
pserver.start()
for i in range(num_clients):
pclient_list[i].start()
for i in range(num_clients):
pclient_list[i].join()
pserver.join()
@unittest.skipIf(os.name == "nt", reason="Do not support windows yet")
def test_multi_thread_rpc():
reset_envs()
os.environ["DGL_DIST_MODE"] = "distributed"
num_servers = 2
ip_config = "rpc_ip_config_multithread.txt"
generate_ip_config(ip_config, num_servers, num_servers)
ctx = mp.get_context("spawn")
pserver_list = []
for i in range(num_servers):
pserver = ctx.Process(target=start_server, args=(1, ip_config, i, 1))
pserver.start()
pserver_list.append(pserver)
def start_client_multithread(ip_config):
import threading
dgl.distributed.connect_to_server(
ip_config=ip_config,
num_servers=1,
)
dgl.distributed.register_service(
HELLO_SERVICE_ID, HelloRequest, HelloResponse
)
req = HelloRequest(STR, INTEGER, TENSOR, simple_func)
dgl.distributed.send_request(0, req)
def subthread_call(server_id):
req = HelloRequest(STR, INTEGER, TENSOR, simple_func)
dgl.distributed.send_request(server_id, req)
subthread = threading.Thread(target=subthread_call, args=(1,))
subthread.start()
subthread.join()
res0 = dgl.distributed.recv_response()
res1 = dgl.distributed.recv_response()
# Order is not guaranteed
assert_array_equal(F.asnumpy(res0.tensor), F.asnumpy(TENSOR))
assert_array_equal(F.asnumpy(res1.tensor), F.asnumpy(TENSOR))
dgl.distributed.exit_client()
start_client_multithread(ip_config)
pserver.join()
@unittest.skipIf(os.name == "nt", reason="Do not support windows yet")
def test_multi_client_connect():
reset_envs()
os.environ["DGL_DIST_MODE"] = "distributed"
ip_config = "rpc_ip_config_mul_client.txt"
generate_ip_config(ip_config, 1, 1)
ctx = mp.get_context("spawn")
num_clients = 1
pserver = ctx.Process(
target=start_server,
args=(num_clients, ip_config, 0, 1),
)
# small max try times
os.environ["DGL_DIST_MAX_TRY_TIMES"] = "1"
expect_except = False
try:
start_client(ip_config, 0, 1)
except dgl.distributed.DistConnectError as err:
print("Expected error: {}".format(err))
expect_except = True
assert expect_except
# large max try times
os.environ["DGL_DIST_MAX_TRY_TIMES"] = "1024"
pclient = ctx.Process(target=start_client, args=(ip_config, 0, 1))
pclient.start()
pserver.start()
pclient.join()
pserver.join()
reset_envs()
if __name__ == "__main__":
test_serialize()
test_rpc_msg()
test_multi_client("socket")
test_multi_client("tesnsorpipe")
test_multi_thread_rpc()
test_multi_client_connect("socket")
+62
View File
@@ -0,0 +1,62 @@
import os
import random
import socket
import dgl
import numpy as np
import scipy.sparse as spsp
def generate_ip_config(file_name, num_machines, num_servers):
"""Get local IP and available ports, writes to file."""
# get available IP in localhost
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't even have to be reachable
sock.connect(("10.255.255.255", 1))
ip = sock.getsockname()[0]
except ValueError:
ip = "127.0.0.1"
finally:
sock.close()
# scan available PORT
ports = []
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
start = random.randint(10000, 30000)
for port in range(start, 65535):
try:
sock.connect((ip, port))
ports = []
except:
ports.append(port)
if len(ports) == num_machines * num_servers:
break
sock.close()
if len(ports) < num_machines * num_servers:
raise RuntimeError(
"Failed to get available IP/PORT with required numbers."
)
with open(file_name, "w") as f:
for i in range(num_machines):
f.write("{} {}\n".format(ip, ports[i * num_servers]))
def reset_envs():
"""Reset common environment variable which are set in tests."""
for key in [
"DGL_ROLE",
"DGL_NUM_SAMPLER",
"DGL_NUM_SERVER",
"DGL_DIST_MODE",
"DGL_NUM_CLIENT",
"DGL_DIST_MAX_TRY_TIMES",
"DGL_DIST_DEBUG",
]:
if key in os.environ:
os.environ.pop(key)
def create_random_graph(n):
return dgl.rand_graph(n, int(n * n * 0.001))