dmlc--dgl
653428bdc7
* [Kernel] Minigun integration and fused kernel support (#519) * kernel interface * add minigun * Add cuda build * functors * working on binary elewise * binary reduce * change kernel interface * WIP * wip * fix minigun * compile * binary reduce kernels * compile * simple test passed * more reducers * fix thrust problem * fix cmake * fix cmake; add proper guard for atomic * WIP: bcast * WIP * bcast kernels * update to new minigun pass-by-value practice * broadcasting dim * add copy src and copy edge * fix linking * fix none array problem * fix copy edge * add device_type and device_id to backend operator * cache csr adj, remove cache for adjmat and incmat * custom ops in backend and pytorch impl * change dgl-mg kernel python interface * add id_mapping var * clean up plus v2e spmv schedule * spmv schedule & clean up fall back * symbolic message and reduce func, remove bundle func * new executors * new backend interface for dgl kernels and pytorch impl * minor fix * fix * fix docstring, comments, func names * nodeflow * fix message id mapping and bugs... * pytorch test case & fix * backward binary reduce * fix bug * WIP: cusparse * change to int32 csr for cusparse workaround * disable cusparse * change back to int64 * broadcasting backward * cusparse; WIP: add rev_csr * unit test for kernels * pytorch backward with dgl kernel * edge softmax * fix backward * improve softmax * cache edge on device * cache mappings on device * fix partial forward code * cusparse done * copy_src_sum with cusparse * rm id getter * reduce grad for broadcast * copy edge reduce backward * kernel unit test for broadcasting * full kernel unit test * add cpu kernels * edge softmax unit test * missing ref * fix compile and small bugs * fix bug in bcast * Add backward both * fix torch utests * expose infershape * create out tensor in python * fix c++ lint * [Kernel] Add GPU utest and kernel utest (#524) * fix gpu utest * cuda utest runnable * temp disable test nodeflow; unified test for kernel * cuda test kernel done * [Kernel] Update kernel branch (#550) * [Model] add multiprocessing training with sampling. (#484) * reorganize sampling code. * add multi-process training. * speed up gcn_cv * fix graphsage_cv. * add new API in graph store. * update barrier impl. * support both local and distributed training. * fix multiprocess train. * fix. * fix barrier. * add script for loading data. * multiprocessing sampling. * accel training. * replace pull with spmv for speedup. * nodeflow copy from parent with context. * enable GPU. * fix a bug in graph store. * enable multi-GPU training. * fix lint. * add comments. * rename to run_store_server.py * fix gcn_cv. * fix a minor bug in sampler. * handle error better in graph store. * improve graphsage_cv for distributed mode. * update README. * fix. * update. * [Tutorial] add sampling tutorial. (#522) * add sampling tutorial. * add readme * update author list. * fix indent in the code. * rename the file. * update tutorial. * fix the last API. * update image. * [BUGFIX] fix the problems in the sampling tutorial. (#523) * add index. * update. * update tutorial. * fix gpu utest * cuda utest runnable * temp disable test nodeflow; unified test for kernel * cuda test kernel done * Fixing typo in JTNN after interface change (#536) * [BugFix] Fix getting src and dst id of ALL edges in NodeFlow.apply_block (#515) * [Bug Fix] Fix inplace op at backend (#546) * Fix inplace operation * fix line seprator * [Feature] Add batch and unbatch for immutable graph (#539) * Add batch and unbatch for immutable graph * fix line seprator * fix lintr * remove unnecessary include * fix code review * [BUGFix] Improve multi-processing training (#526) * fix. * add comment. * remove. * temp fix. * initialize for shared memory. * fix graphsage. * fix gcn. * add more unit tests. * add more tests. * avoid creating shared-memory exclusively. * redefine remote initializer. * improve initializer. * fix unit test. * fix lint. * fix lint. * initialize data in the graph store server properly. * fix test. * fix test. * fix test. * small fix. * add comments. * cleanup server. * test graph store with a random port. * print. * print to stderr. * test1 * test2 * remove comment. * adjust the initializer signature. * [API] update graph store API. (#549) * add init_ndata and init_edata in DGLGraph. * adjust SharedMemoryGraph API. * print warning. * fix comment. * update example * fix. * fix examples. * add unit tests. * add comments. * [Refactor] Immutable graph index (#543) * WIP * header * WIP .cc * WIP * transpose * wip * immutable graph .h and .cc * WIP: nodeflow.cc * compile * remove all tmp dl managed ctx; they caused refcount issue * one simple test * WIP: testing * test_graph * fix graph index * fix bug in sampler; pass pytorch utest * WIP on mxnet * fix lint * fix mxnet unittest w/ unfortunate workaround * fix msvc * fix lint * SliceRows and test_nodeflow * resolve reviews * resolve reviews * try fix win ci * try fix win ci * poke win ci again * poke * lazy multigraph flag; stackoverflow error * revert node subgraph test * lazy object * try fix win build * try fix win build * poke ci * fix build script * fix compile * add a todo * fix reviews * fix compile * [Kernel] Update kernel branch (#576) * [Model] add multiprocessing training with sampling. (#484) * reorganize sampling code. * add multi-process training. * speed up gcn_cv * fix graphsage_cv. * add new API in graph store. * update barrier impl. * support both local and distributed training. * fix multiprocess train. * fix. * fix barrier. * add script for loading data. * multiprocessing sampling. * accel training. * replace pull with spmv for speedup. * nodeflow copy from parent with context. * enable GPU. * fix a bug in graph store. * enable multi-GPU training. * fix lint. * add comments. * rename to run_store_server.py * fix gcn_cv. * fix a minor bug in sampler. * handle error better in graph store. * improve graphsage_cv for distributed mode. * update README. * fix. * update. * [Tutorial] add sampling tutorial. (#522) * add sampling tutorial. * add readme * update author list. * fix indent in the code. * rename the file. * update tutorial. * fix the last API. * update image. * [BUGFIX] fix the problems in the sampling tutorial. (#523) * add index. * update. * update tutorial. * fix gpu utest * cuda utest runnable * temp disable test nodeflow; unified test for kernel * cuda test kernel done * Fixing typo in JTNN after interface change (#536) * [BugFix] Fix getting src and dst id of ALL edges in NodeFlow.apply_block (#515) * [Bug Fix] Fix inplace op at backend (#546) * Fix inplace operation * fix line seprator * [Feature] Add batch and unbatch for immutable graph (#539) * Add batch and unbatch for immutable graph * fix line seprator * fix lintr * remove unnecessary include * fix code review * [BUGFix] Improve multi-processing training (#526) * fix. * add comment. * remove. * temp fix. * initialize for shared memory. * fix graphsage. * fix gcn. * add more unit tests. * add more tests. * avoid creating shared-memory exclusively. * redefine remote initializer. * improve initializer. * fix unit test. * fix lint. * fix lint. * initialize data in the graph store server properly. * fix test. * fix test. * fix test. * small fix. * add comments. * cleanup server. * test graph store with a random port. * print. * print to stderr. * test1 * test2 * remove comment. * adjust the initializer signature. * [API] update graph store API. (#549) * add init_ndata and init_edata in DGLGraph. * adjust SharedMemoryGraph API. * print warning. * fix comment. * update example * fix. * fix examples. * add unit tests. * add comments. * [Refactor] Immutable graph index (#543) * WIP * header * WIP .cc * WIP * transpose * wip * immutable graph .h and .cc * WIP: nodeflow.cc * compile * remove all tmp dl managed ctx; they caused refcount issue * one simple test * WIP: testing * test_graph * fix graph index * fix bug in sampler; pass pytorch utest * WIP on mxnet * fix lint * fix mxnet unittest w/ unfortunate workaround * fix msvc * fix lint * SliceRows and test_nodeflow * resolve reviews * resolve reviews * try fix win ci * try fix win ci * poke win ci again * poke * lazy multigraph flag; stackoverflow error * revert node subgraph test * lazy object * try fix win build * try fix win build * poke ci * fix build script * fix compile * add a todo * fix reviews * fix compile * all demo use python-3 (#555) * [DEMO] Reproduce numbers of distributed training in AMLC giant graph paper (#556) * update * update * update * update num_hops * fix bug * update * report numbers of distributed training in AMLC giant graph paper * [DEMO] Remove duplicate code for sampling (#557) * update * update * re-use single-machine code * update * use relative path * update * update * update * add __init__.py * add __init__.py * import sys, os * fix typo * update * [Perf] Improve performance of graph store. (#554) * fix. * use inplace. * move to shared memory graph store. * fix. * add more unit tests. * fix. * fix test. * fix test. * disable test. * fix. * [BUGIFX] fix a bug in edge_ids (#560) * add test. * fix compute. * fix test. * turn on test. * fix a bug. * add test. * fix. * disable test. * [DEMO] Add Pytorch demo for distributed sampler (#562) * update * update * update * add sender * update * remove duplicate cpde * [Test] Add gtest to project (#547) * add gtest module * add gtest * fix * Update CMakeLists.txt * Update README.md * [Perf] lazily create msg_index. (#563) * lazily create msg_index. * update test. * [BUGFIX] fix bugs for running GCN on giant graphs. (#561) * load mxnet csr. * enable load large csr. * fix * fix. * fix int overflow. * fix test. * [BugFix] Fix error when bfs_level = 0 in Entity Classification with RGCN (#559) * [DEMO] Update demo of distributed sampler (#564) * update * update * update demo * add network cpp test (#565) * Add unittest for C++ RPC (#566) * [CI] Fix CI for cpp test (#570) * fix CI for cpp test * update port number * [Docker] update docker image (#575) * update docker image * specify lint version * rm torch import from unified tests * [Kernel][Scheduler][MXNet] Scheduler for DGL kernels and MXNet backend support (#541) * [Model] add multiprocessing training with sampling. (#484) * reorganize sampling code. * add multi-process training. * speed up gcn_cv * fix graphsage_cv. * add new API in graph store. * update barrier impl. * support both local and distributed training. * fix multiprocess train. * fix. * fix barrier. * add script for loading data. * multiprocessing sampling. * accel training. * replace pull with spmv for speedup. * nodeflow copy from parent with context. * enable GPU. * fix a bug in graph store. * enable multi-GPU training. * fix lint. * add comments. * rename to run_store_server.py * fix gcn_cv. * fix a minor bug in sampler. * handle error better in graph store. * improve graphsage_cv for distributed mode. * update README. * fix. * update. * [Tutorial] add sampling tutorial. (#522) * add sampling tutorial. * add readme * update author list. * fix indent in the code. * rename the file. * update tutorial. * fix the last API. * update image. * [BUGFIX] fix the problems in the sampling tutorial. (#523) * add index. * update. * update tutorial. * fix gpu utest * cuda utest runnable * temp disable test nodeflow; unified test for kernel * cuda test kernel done * edge softmax module * WIP * Fixing typo in JTNN after interface change (#536) * mxnet backend support * improve reduce grad * add max to unittest backend * fix kernel unittest * [BugFix] Fix getting src and dst id of ALL edges in NodeFlow.apply_block (#515) * lint * lint * win build * [Bug Fix] Fix inplace op at backend (#546) * Fix inplace operation * fix line seprator * [Feature] Add batch and unbatch for immutable graph (#539) * Add batch and unbatch for immutable graph * fix line seprator * fix lintr * remove unnecessary include * fix code review * [BUGFix] Improve multi-processing training (#526) * fix. * add comment. * remove. * temp fix. * initialize for shared memory. * fix graphsage. * fix gcn. * add more unit tests. * add more tests. * avoid creating shared-memory exclusively. * redefine remote initializer. * improve initializer. * fix unit test. * fix lint. * fix lint. * initialize data in the graph store server properly. * fix test. * fix test. * fix test. * small fix. * add comments. * cleanup server. * test graph store with a random port. * print. * print to stderr. * test1 * test2 * remove comment. * adjust the initializer signature. * try * fix * fix * fix * fix * fix * try * test * test * test * try * try * try * test * fix * try gen_target * fix gen_target * fix msvc var_args expand issue * fix * [API] update graph store API. (#549) * add init_ndata and init_edata in DGLGraph. * adjust SharedMemoryGraph API. * print warning. * fix comment. * update example * fix. * fix examples. * add unit tests. * add comments. * [Refactor] Immutable graph index (#543) * WIP * header * WIP .cc * WIP * transpose * wip * immutable graph .h and .cc * WIP: nodeflow.cc * compile * remove all tmp dl managed ctx; they caused refcount issue * one simple test * WIP: testing * test_graph * fix graph index * fix bug in sampler; pass pytorch utest * WIP on mxnet * fix lint * fix mxnet unittest w/ unfortunate workaround * fix msvc * fix lint * SliceRows and test_nodeflow * resolve reviews * resolve reviews * try fix win ci * try fix win ci * poke win ci again * poke * lazy multigraph flag; stackoverflow error * revert node subgraph test * lazy object * try fix win build * try fix win build * poke ci * fix build script * fix compile * add a todo * fix reviews * fix compile * WIP * WIP * all demo use python-3 (#555) * ToImmutable and CopyTo * [DEMO] Reproduce numbers of distributed training in AMLC giant graph paper (#556) * update * update * update * update num_hops * fix bug * update * report numbers of distributed training in AMLC giant graph paper * [DEMO] Remove duplicate code for sampling (#557) * update * update * re-use single-machine code * update * use relative path * update * update * update * add __init__.py * add __init__.py * import sys, os * fix typo * update * [Perf] Improve performance of graph store. (#554) * fix. * use inplace. * move to shared memory graph store. * fix. * add more unit tests. * fix. * fix test. * fix test. * disable test. * fix. * [BUGIFX] fix a bug in edge_ids (#560) * add test. * fix compute. * fix test. * turn on test. * fix a bug. * add test. * fix. * disable test. * DGLRetValue DGLContext conversion * [DEMO] Add Pytorch demo for distributed sampler (#562) * update * update * update * add sender * update * remove duplicate cpde * [Test] Add gtest to project (#547) * add gtest module * add gtest * fix * Update CMakeLists.txt * Update README.md * Add support to convert immutable graph to 32 bits * [Perf] lazily create msg_index. (#563) * lazily create msg_index. * update test. * fix binary reduce following new minigun template * enable both int64 and int32 kernels * [BUGFIX] fix bugs for running GCN on giant graphs. (#561) * load mxnet csr. * enable load large csr. * fix * fix. * fix int overflow. * fix test. * new kernel interface done for CPU * docstring * rename & docstring * copy reduce and backward * [BugFix] Fix error when bfs_level = 0 in Entity Classification with RGCN (#559) * [DEMO] Update demo of distributed sampler (#564) * update * update * update demo * adapt cuda kernels to the new interface * add network cpp test (#565) * fix bug * Add unittest for C++ RPC (#566) * [CI] Fix CI for cpp test (#570) * fix CI for cpp test * update port number * [Docker] update docker image (#575) * update docker image * specify lint version * rm torch import from unified tests * remove pytorch-specific test_function * fix unittest * fix * fix unittest backend bug in converting tensor to numpy array * fix * mxnet version * [BUGFIX] fix for MXNet 1.5. (#552) * remove clone. * turn on numpy compatible. * Revert "remove clone." This reverts commit 17bbf76ed72ff178df6b3f35addc428048672457. * revert format changes * fix mxnet api name * revert mistakes in previous revert * roll back CI to 20190523 build * fix unittest * disable test_shared_mem_store.py for now * remove mxnet/test_specialization.py * sync win64 test script * fix lowercase * missing backend in gpu unit test * transpose to get forward graph * pass update all * add sanity check * passing test_specialization.py * fix and pass test_function * fix check * fix pytorch softmax * mxnet kernels * c++ lint * pylint * try * win build * fix * win * ci enable gpu build * init submodule recursively * backend docstring * try * test win dev * doc string * disable pytorch test_nn * try to fix windows issue * bug fixed, revert changes * [Test] fix CI. (#586) * disable unit test in mxnet tutorial. * retry socket connection. * roll back to set_np_compat * try to fix multi-processing test hangs when it fails. * fix test. * fix. * doc string * doc string and clean up * missing field in ctypes * fix node flow schedule and unit test * rename * pylint * copy from parent default context * fix unit test script * fix * demo bug in nodeflow gpu test * [Kernel][Bugfix] fix nodeflow bug (#604) * fix nodeflow bug * remove debug code * add build gtest option * fix cmake; fix graph index bug in spmv.py * remove clone * fix div rhs grad bug * [Kernel] Support full builtin method, edge softmax and unit tests (#605) * add full builtin support * unit test * unit test backend * edge softmax * apply edge with builtin * fix kernel unit test * disable mxnet test_shared_mem_store * gen builtin reduce * enable mxnet gpu unittest * revert some changes * docstring * add note for the hack * [Kernel][Unittest][CI] Fix MXNet GPU CI (#607) * update docker image for MXNet GPU CI * force all dgl graph input and output on CPU * fix gpu unittest * speedup compilation * add some comments * lint * add more comments * fix as requested * add some comments * comment * lint * lint * update pylint * fix as requested * lint * lint * lint * docstrings of python DGL kernel entries * disable lint warnings on arguments in kernel.py * fix docstring in scheduler * fix some bug in unittest; try again * Revert "Merge branch 'kernel' of github.com:zzhang-cn/dgl into kernel" This reverts commit 1d2299e68b004182ea6130b088de1f1122b18a49, reversing changes made to ddc97fbf1bec2b7815c0da7c74f7ecb2f428889b. * Revert "fix some bug in unittest; try again" This reverts commit ddc97fbf1bec2b7815c0da7c74f7ecb2f428889b. * more comprehensive kernel test * remove shape check in test_specialization
353 行
10 KiB
Python
353 行
10 KiB
Python
import numpy as np
|
|
import dgl
|
|
from dgl.graph import DGLGraph
|
|
from collections import defaultdict as ddict
|
|
import scipy.sparse as sp
|
|
import backend as F
|
|
|
|
D = 5
|
|
|
|
def message_func(edges):
|
|
assert len(edges.src['h'].shape) == 2
|
|
assert edges.src['h'].shape[1] == D
|
|
return {'m' : edges.src['h']}
|
|
|
|
def reduce_func(nodes):
|
|
msgs = nodes.mailbox['m']
|
|
assert len(msgs.shape) == 3
|
|
assert msgs.shape[2] == D
|
|
return {'accum' : F.sum(msgs, 1)}
|
|
|
|
def apply_node_func(nodes):
|
|
return {'h' : nodes.data['h'] + nodes.data['accum']}
|
|
|
|
def generate_graph(grad=False):
|
|
g = DGLGraph()
|
|
g.add_nodes(10) # 10 nodes.
|
|
# create a graph where 0 is the source and 9 is the sink
|
|
# 16 edges
|
|
for i in range(1, 9):
|
|
g.add_edge(0, i)
|
|
g.add_edge(i, 9)
|
|
ncol = F.randn((10, D))
|
|
ecol = F.randn((16, D))
|
|
if grad:
|
|
ncol = F.attach_grad(ncol)
|
|
ecol = F.attach_grad(ecol)
|
|
g.set_n_initializer(dgl.init.zero_initializer)
|
|
g.set_e_initializer(dgl.init.zero_initializer)
|
|
g.ndata['h'] = ncol
|
|
g.edata['w'] = ecol
|
|
return g
|
|
|
|
def test_multi_send():
|
|
g = generate_graph()
|
|
def _fmsg(edges):
|
|
assert edges.src['h'].shape == (5, D)
|
|
return {'m' : edges.src['h']}
|
|
g.register_message_func(_fmsg)
|
|
# many-many send
|
|
u = F.tensor([0, 0, 0, 0, 0])
|
|
v = F.tensor([1, 2, 3, 4, 5])
|
|
g.send((u, v))
|
|
# duplicate send
|
|
u = F.tensor([0])
|
|
v = F.tensor([1, 2, 3, 4, 5])
|
|
g.send((u, v))
|
|
# send more
|
|
u = F.tensor([1, 2, 3, 4, 5])
|
|
v = F.tensor([9])
|
|
g.send((u, v))
|
|
|
|
# check if message indicator is as expected
|
|
expected = F.copy_to(F.zeros((g.number_of_edges(),), dtype=F.int64), F.cpu())
|
|
eid = g.edge_ids([0, 0, 0, 0, 0, 1, 2, 3, 4, 5],
|
|
[1, 2, 3, 4, 5, 9, 9, 9, 9, 9])
|
|
expected[eid] = 1
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
|
|
def test_multi_recv():
|
|
# basic recv test
|
|
g = generate_graph()
|
|
h = g.ndata['h']
|
|
g.register_message_func(message_func)
|
|
g.register_reduce_func(reduce_func)
|
|
g.register_apply_node_func(apply_node_func)
|
|
expected = F.copy_to(F.zeros((g.number_of_edges(),), dtype=F.int64), F.cpu())
|
|
# two separate round of send and recv
|
|
u = [4, 5, 6]
|
|
v = [9]
|
|
g.send((u, v))
|
|
eid = g.edge_ids(u, v)
|
|
expected[eid] = 1
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
g.recv(v)
|
|
expected[eid] = 0
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
|
|
u = [0]
|
|
v = [1, 2, 3]
|
|
g.send((u, v))
|
|
eid = g.edge_ids(u, v)
|
|
expected[eid] = 1
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
g.recv(v)
|
|
expected[eid] = 0
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
|
|
h1 = g.ndata['h']
|
|
|
|
# one send, two recv
|
|
g.ndata['h'] = h
|
|
u = F.tensor([0, 0, 0, 4, 5, 6])
|
|
v = F.tensor([1, 2, 3, 9, 9, 9])
|
|
g.send((u, v))
|
|
eid = g.edge_ids(u, v)
|
|
expected[eid] = 1
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
u = [4, 5, 6]
|
|
v = [9]
|
|
g.recv(v)
|
|
eid = g.edge_ids(u, v)
|
|
expected[eid] = 0
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
u = [0]
|
|
v = [1, 2, 3]
|
|
g.recv(v)
|
|
eid = g.edge_ids(u, v)
|
|
expected[eid] = 0
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
|
|
h2 = g.ndata['h']
|
|
assert F.allclose(h1, h2)
|
|
|
|
def test_multi_recv_0deg():
|
|
# test recv with 0deg nodes;
|
|
g = DGLGraph()
|
|
def _message(edges):
|
|
return {'m' : edges.src['h']}
|
|
def _reduce(nodes):
|
|
return {'h' : nodes.data['h'] + nodes.mailbox['m'].sum(1)}
|
|
def _apply(nodes):
|
|
return {'h' : nodes.data['h'] * 2}
|
|
def _init2(shape, dtype, ctx, ids):
|
|
return 2 + F.zeros(shape, dtype=dtype, ctx=ctx)
|
|
g.register_message_func(_message)
|
|
g.register_reduce_func(_reduce)
|
|
g.register_apply_node_func(_apply)
|
|
g.set_n_initializer(_init2)
|
|
g.add_nodes(2)
|
|
g.add_edge(0, 1)
|
|
# recv both 0deg and non-0deg nodes
|
|
old = F.randn((2, 5))
|
|
g.ndata['h'] = old
|
|
g.send((0, 1))
|
|
g.recv([0, 1])
|
|
new = g.ndata['h']
|
|
# 0deg check: initialized with the func and got applied
|
|
assert F.allclose(new[0], F.full((5,), 4, F.float32))
|
|
# non-0deg check
|
|
assert F.allclose(new[1], F.sum(old, 0) * 2)
|
|
|
|
# recv again on zero degree node
|
|
g.recv([0])
|
|
assert F.allclose(g.nodes[0].data['h'], F.full((5,), 8, F.float32))
|
|
|
|
# recv again on node with no incoming message
|
|
g.recv([1])
|
|
assert F.allclose(g.nodes[1].data['h'], F.sum(old, 0) * 4)
|
|
|
|
def test_send_twice_different_shape():
|
|
g = generate_graph()
|
|
def _message_1(edges):
|
|
return {'h': edges.src['h']}
|
|
def _message_2(edges):
|
|
return {'h': F.cat((edges.src['h'], edges.data['w']), dim=1)}
|
|
g.send(message_func=_message_1)
|
|
g.send(message_func=_message_2)
|
|
|
|
def test_send_twice_different_msg():
|
|
g = DGLGraph()
|
|
g.set_n_initializer(dgl.init.zero_initializer)
|
|
g.add_nodes(3)
|
|
g.add_edge(0, 1)
|
|
g.add_edge(2, 1)
|
|
def _message_a(edges):
|
|
return {'a': edges.src['a']}
|
|
def _message_b(edges):
|
|
return {'a': edges.src['a'] * 3}
|
|
def _reduce(nodes):
|
|
return {'a': F.max(nodes.mailbox['a'], 1)}
|
|
|
|
old_repr = F.randn((3, 5))
|
|
g.ndata['a'] = old_repr
|
|
g.send((0, 1), _message_a)
|
|
g.send((0, 1), _message_b)
|
|
g.recv(1, _reduce)
|
|
new_repr = g.ndata['a']
|
|
assert F.allclose(new_repr[1], old_repr[0] * 3)
|
|
|
|
g.ndata['a'] = old_repr
|
|
g.send((0, 1), _message_a)
|
|
g.send((2, 1), _message_b)
|
|
g.recv(1, _reduce)
|
|
new_repr = g.ndata['a']
|
|
assert F.allclose(new_repr[1], F.max(F.stack([old_repr[0], old_repr[2] * 3], 0), 0))
|
|
|
|
def test_send_twice_different_field():
|
|
g = DGLGraph()
|
|
g.set_n_initializer(dgl.init.zero_initializer)
|
|
g.add_nodes(2)
|
|
g.add_edge(0, 1)
|
|
def _message_a(edges):
|
|
return {'a': edges.src['a']}
|
|
def _message_b(edges):
|
|
return {'b': edges.src['b']}
|
|
def _reduce(nodes):
|
|
return {'a': F.sum(nodes.mailbox['a'], 1), 'b': F.sum(nodes.mailbox['b'], 1)}
|
|
old_a = F.randn((2, 5))
|
|
old_b = F.randn((2, 5))
|
|
g.set_n_repr({'a': old_a, 'b': old_b})
|
|
g.send((0, 1), _message_a)
|
|
g.send((0, 1), _message_b)
|
|
g.recv([1], _reduce)
|
|
new_repr = g.get_n_repr()
|
|
assert F.allclose(new_repr['a'][1], old_a[0])
|
|
assert F.allclose(new_repr['b'][1], old_b[0])
|
|
|
|
def test_dynamic_addition():
|
|
N = 3
|
|
D = 1
|
|
|
|
g = DGLGraph()
|
|
def _init(shape, dtype, ctx, ids):
|
|
return F.copy_to(F.astype(F.randn(shape), dtype), ctx)
|
|
g.set_n_initializer(_init)
|
|
g.set_e_initializer(_init)
|
|
|
|
def _message(edges):
|
|
return {'m' : edges.src['h1'] + edges.dst['h2'] + edges.data['h1'] +
|
|
edges.data['h2']}
|
|
def _reduce(nodes):
|
|
return {'h' : F.sum(nodes.mailbox['m'], 1)}
|
|
def _apply(nodes):
|
|
return {'h' : nodes.data['h']}
|
|
|
|
g.register_message_func(_message)
|
|
g.register_reduce_func(_reduce)
|
|
g.register_apply_node_func(_apply)
|
|
g.set_n_initializer(dgl.init.zero_initializer)
|
|
g.set_e_initializer(dgl.init.zero_initializer)
|
|
|
|
# add nodes and edges
|
|
g.add_nodes(N)
|
|
g.ndata.update({'h1': F.randn((N, D)),
|
|
'h2': F.randn((N, D))})
|
|
g.add_nodes(3)
|
|
g.add_edge(0, 1)
|
|
g.add_edge(1, 0)
|
|
g.edata.update({'h1': F.randn((2, D)),
|
|
'h2': F.randn((2, D))})
|
|
g.send()
|
|
expected = F.copy_to(F.ones((g.number_of_edges(),), dtype=F.int64), F.cpu())
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
|
|
# add more edges
|
|
g.add_edges([0, 2], [2, 0], {'h1': F.randn((2, D))})
|
|
g.send(([0, 2], [2, 0]))
|
|
g.recv(0)
|
|
|
|
g.add_edge(1, 2)
|
|
g.edges[4].data['h1'] = F.randn((1, D))
|
|
g.send((1, 2))
|
|
g.recv([1, 2])
|
|
|
|
h = g.ndata.pop('h')
|
|
|
|
# a complete round of send and recv
|
|
g.send()
|
|
g.recv()
|
|
assert F.allclose(h, g.ndata['h'])
|
|
|
|
def test_recv_no_send():
|
|
g = generate_graph()
|
|
g.recv(1, reduce_func)
|
|
# test recv after clear
|
|
g.clear()
|
|
g.add_nodes(3)
|
|
g.add_edges([0, 1], [1, 2])
|
|
g.set_n_initializer(dgl.init.zero_initializer)
|
|
g.ndata['h'] = F.randn((3, D))
|
|
g.send((1, 2), message_func)
|
|
expected = F.copy_to(F.zeros(2, dtype=F.int64), F.cpu())
|
|
expected[1] = 1
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
g.recv(2, reduce_func)
|
|
expected[1] = 0
|
|
assert F.array_equal(g._get_msg_index().tousertensor(), expected)
|
|
|
|
def test_send_recv_after_conversion():
|
|
# test send and recv after converting from a graph with edges
|
|
|
|
g = generate_graph()
|
|
|
|
# nx graph
|
|
nxg = g.to_networkx(node_attrs=['h'])
|
|
g1 = DGLGraph()
|
|
# some random node and edges
|
|
g1.add_nodes(4)
|
|
g1.add_edges([1, 2], [2, 3])
|
|
g1.set_n_initializer(dgl.init.zero_initializer)
|
|
g1.from_networkx(nxg, node_attrs=['h'])
|
|
|
|
# sparse matrix
|
|
row, col= g.all_edges()
|
|
data = range(len(row))
|
|
n = g.number_of_nodes()
|
|
a = sp.coo_matrix(
|
|
(data, (F.zerocopy_to_numpy(row), F.zerocopy_to_numpy(col))),
|
|
shape=(n, n))
|
|
g2 = DGLGraph()
|
|
# some random node and edges
|
|
g2.add_nodes(5)
|
|
g2.add_edges([1, 2, 4], [2, 3, 0])
|
|
g2.set_n_initializer(dgl.init.zero_initializer)
|
|
g2.from_scipy_sparse_matrix(a)
|
|
g2.ndata['h'] = g.ndata['h']
|
|
|
|
# on dgl graph
|
|
g.send(message_func=message_func)
|
|
g.recv([0, 1, 3, 5], reduce_func=reduce_func,
|
|
apply_node_func=apply_node_func)
|
|
g.recv([0, 2, 4, 8], reduce_func=reduce_func,
|
|
apply_node_func=apply_node_func)
|
|
|
|
# nx
|
|
g1.send(message_func=message_func)
|
|
g1.recv([0, 1, 3, 5], reduce_func=reduce_func,
|
|
apply_node_func=apply_node_func)
|
|
g1.recv([0, 2, 4, 8], reduce_func=reduce_func,
|
|
apply_node_func=apply_node_func)
|
|
|
|
# sparse matrix
|
|
g2.send(message_func=message_func)
|
|
g2.recv([0, 1, 3, 5], reduce_func=reduce_func,
|
|
apply_node_func=apply_node_func)
|
|
g2.recv([0, 2, 4, 8], reduce_func=reduce_func,
|
|
apply_node_func=apply_node_func)
|
|
|
|
assert F.allclose(g.ndata['h'], g1.ndata['h'])
|
|
assert F.allclose(g.ndata['h'], g2.ndata['h'])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
test_multi_send()
|
|
test_multi_recv()
|
|
test_multi_recv_0deg()
|
|
test_dynamic_addition()
|
|
test_send_twice_different_shape()
|
|
test_send_twice_different_msg()
|
|
test_send_twice_different_field()
|
|
test_recv_no_send()
|
|
test_send_recv_after_conversion()
|