Skip to content

Commit 33f9e49

Browse files
authored
Merge pull request #1522 from rapidsai/branch-0.19
[gpuCI] Forward-merge branch-0.19 to branch-0.20 [skip ci]
2 parents fb14030 + 63e69fc commit 33f9e49

File tree

9 files changed

+424
-0
lines changed

9 files changed

+424
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ As of Release 0.18 - including 0.18 nightly
8282
| | Breadth First Search (BFS) | Multi-GPU | with cutoff support <br/> [C++ README](cpp/src/traversal/README.md#BFS) |
8383
| | Single Source Shortest Path (SSSP) | Multi-GPU | [C++ README](cpp/src/traversal/README.md#SSSP) |
8484
| | Traveling Salesperson Problem (TSP) | Single-GPU | |
85+
| Sampling | Random Walks (RW) | Single-GPU | |
8586
| Structure | | | |
8687
| | Renumbering | Single-GPU | multiple columns, any data type |
8788
| | Symmetrize | Multi-GPU | |

docs/source/api.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,17 @@ Overlap Coefficient
225225
:undoc-members:
226226

227227

228+
Sampling
229+
========
230+
231+
Random Walks
232+
------------
233+
234+
.. automodule:: cugraph.sampling.random_walks
235+
:members:
236+
:undoc-members:
237+
238+
228239
Traversal
229240
=========
230241

python/cugraph/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@
101101
from cugraph.raft import raft_include_test
102102
from cugraph.comms import comms
103103

104+
from cugraph.sampling import random_walks
105+
104106
# Versioneer
105107
from ._version import get_versions
106108

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright (c) 2021, NVIDIA CORPORATION.
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
from cugraph.sampling.random_walks import random_walks
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright (c) 2021, NVIDIA CORPORATION.
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
#from cugraph.structure.graph_primtypes cimport *
14+
from cugraph.structure.graph_utilities cimport *
15+
16+
cdef extern from "utilities/cython.hpp" namespace "cugraph::cython":
17+
cdef unique_ptr[random_walk_ret_t] call_random_walks[vertex_t, edge_t](
18+
const handle_t &handle,
19+
const graph_container_t &g,
20+
const vertex_t *ptr_d_start,
21+
edge_t num_paths,
22+
edge_t max_depth) except +
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Copyright (c) 2021, NVIDIA CORPORATION.
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
import cudf
15+
from cugraph.sampling import random_walks_wrapper
16+
import cugraph
17+
from collections import defaultdict
18+
19+
# FIXME might be more efficient to return either (df + offset) or 3 cudf.Series
20+
21+
22+
def random_walks(
23+
G,
24+
start_vertices,
25+
max_depth=None
26+
):
27+
"""
28+
compute random walks for each nodes in 'start_vertices'
29+
30+
parameters
31+
----------
32+
G : cuGraph.Graph or networkx.Graph
33+
The graph can be either directed (DiGraph) or undirected (Graph).
34+
Weights in the graph are ignored.
35+
Use weight parameter if weights need to be considered
36+
(currently not supported)
37+
38+
start_vertices : int or list or cudf.Series
39+
A single node or a list or a cudf.Series of nodes from which to run
40+
the random walks
41+
42+
max_depth : int
43+
The maximum depth of the random walks
44+
45+
46+
Returns
47+
-------
48+
random_walks_edge_lists : cudf.DataFrame
49+
GPU data frame containing all random walks sources identifiers,
50+
destination identifiers, edge weights
51+
52+
seeds_offsets: cudf.Series
53+
Series containing the starting offset in the returned edge list
54+
for each vertex in start_vertices.
55+
"""
56+
if max_depth is None:
57+
raise TypeError("must specify a 'max_depth'")
58+
59+
G, _ = cugraph.utilities.check_nx_graph(G)
60+
61+
if start_vertices is int:
62+
start_vertices = [start_vertices]
63+
64+
if not isinstance(start_vertices, cudf.Series):
65+
start_vertices = cudf.Series(start_vertices)
66+
67+
if G.renumbered is True:
68+
start_vertices = G.lookup_internal_vertex_id(start_vertices)
69+
vertex_set, edge_set, sizes = random_walks_wrapper.random_walks(
70+
G, start_vertices, max_depth)
71+
72+
if G.renumbered:
73+
df_ = cudf.DataFrame()
74+
df_['vertex_set'] = vertex_set
75+
df_ = G.unrenumber(df_, 'vertex_set', preserve_order=True)
76+
vertex_set = cudf.Series(df_['vertex_set'])
77+
78+
edge_list = defaultdict(list)
79+
next_path_idx = 0
80+
offsets = [0]
81+
82+
df = cudf.DataFrame()
83+
for s in sizes.values_host:
84+
for i in range(next_path_idx, s+next_path_idx-1):
85+
edge_list['src'].append(vertex_set.values_host[i])
86+
edge_list['dst'].append(vertex_set.values_host[i+1])
87+
next_path_idx += s
88+
df = df.append(edge_list, ignore_index=True)
89+
offsets.append(df.index[-1]+1)
90+
edge_list['src'].clear()
91+
edge_list['dst'].clear()
92+
df['weight'] = edge_set
93+
offsets = cudf.Series(offsets)
94+
95+
return df, offsets
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Copyright (c) 2021, NVIDIA CORPORATION.
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
from cugraph.sampling.random_walks cimport call_random_walks
14+
#from cugraph.structure.graph_primtypes cimport *
15+
from cugraph.structure.graph_utilities cimport *
16+
from libcpp cimport bool
17+
from libcpp.utility cimport move
18+
from libc.stdint cimport uintptr_t
19+
from cugraph.structure import graph_primtypes_wrapper
20+
import cudf
21+
import rmm
22+
import numpy as np
23+
import numpy.ctypeslib as ctypeslib
24+
from rmm._lib.device_buffer cimport DeviceBuffer
25+
from cudf.core.buffer import Buffer
26+
from cython.operator cimport dereference as deref
27+
def random_walks(input_graph, start_vertices, max_depth):
28+
"""
29+
Call random_walks
30+
"""
31+
# FIXME: Offsets and indices are currently hardcoded to int, but this may
32+
# not be acceptable in the future.
33+
numberTypeMap = {np.dtype("int32") : <int>numberTypeEnum.int32Type,
34+
np.dtype("int64") : <int>numberTypeEnum.int64Type,
35+
np.dtype("float32") : <int>numberTypeEnum.floatType,
36+
np.dtype("double") : <int>numberTypeEnum.doubleType}
37+
[src, dst] = [input_graph.edgelist.edgelist_df['src'], input_graph.edgelist.edgelist_df['dst']]
38+
vertex_t = src.dtype
39+
edge_t = np.dtype("int32")
40+
weights = None
41+
if input_graph.edgelist.weights:
42+
weights = input_graph.edgelist.edgelist_df['weights']
43+
num_verts = input_graph.number_of_vertices()
44+
num_edges = input_graph.number_of_edges(directed_edges=True)
45+
num_partition_edges = num_edges
46+
47+
if num_edges > (2**31 - 1):
48+
edge_t = np.dtype("int64")
49+
cdef unique_ptr[random_walk_ret_t] rw_ret_ptr
50+
51+
cdef uintptr_t c_src_vertices = src.__cuda_array_interface__['data'][0]
52+
cdef uintptr_t c_dst_vertices = dst.__cuda_array_interface__['data'][0]
53+
cdef uintptr_t c_edge_weights = <uintptr_t>NULL
54+
if weights is not None:
55+
c_edge_weights = weights.__cuda_array_interface__['data'][0]
56+
weight_t = weights.dtype
57+
is_weighted = True
58+
else:
59+
weight_t = np.dtype("float32")
60+
is_weighted = False
61+
# Pointers for random_walks
62+
start_vertices = start_vertices.astype('int32')
63+
cdef uintptr_t c_start_vertex_ptr = start_vertices.__cuda_array_interface__['data'][0]
64+
num_paths = start_vertices.size
65+
cdef unique_ptr[handle_t] handle_ptr
66+
handle_ptr.reset(new handle_t())
67+
handle_ = handle_ptr.get()
68+
cdef graph_container_t graph_container
69+
populate_graph_container(graph_container,
70+
handle_[0],
71+
<void*>c_src_vertices, <void*>c_dst_vertices, <void*>c_edge_weights,
72+
<void*>NULL,
73+
<numberTypeEnum>(<int>(numberTypeMap[vertex_t])),
74+
<numberTypeEnum>(<int>(numberTypeMap[edge_t])),
75+
<numberTypeEnum>(<int>(numberTypeMap[weight_t])),
76+
num_partition_edges,
77+
num_verts,
78+
num_edges,
79+
False,
80+
is_weighted,
81+
False, False)
82+
if(vertex_t == np.dtype("int32")):
83+
if(edge_t == np.dtype("int32")):
84+
rw_ret_ptr = move(call_random_walks[int, int]( deref(handle_),
85+
graph_container,
86+
<int*> c_start_vertex_ptr,
87+
<int> num_paths,
88+
<int> max_depth))
89+
else: # (edge_t == np.dtype("int64")):
90+
rw_ret_ptr = move(call_random_walks[int, long]( deref(handle_),
91+
graph_container,
92+
<int*> c_start_vertex_ptr,
93+
<long> num_paths,
94+
<long> max_depth))
95+
else: # (vertex_t == edge_t == np.dtype("int64")):
96+
rw_ret_ptr = move(call_random_walks[long, long]( deref(handle_),
97+
graph_container,
98+
<long*> c_start_vertex_ptr,
99+
<long> num_paths,
100+
<long> max_depth))
101+
102+
103+
rw_ret= move(rw_ret_ptr.get()[0])
104+
vertex_set = DeviceBuffer.c_from_unique_ptr(move(rw_ret.d_coalesced_v_))
105+
edge_set = DeviceBuffer.c_from_unique_ptr(move(rw_ret.d_coalesced_w_))
106+
sizes = DeviceBuffer.c_from_unique_ptr(move(rw_ret.d_sizes_))
107+
vertex_set = Buffer(vertex_set)
108+
edge_set = Buffer(edge_set)
109+
sizes = Buffer(sizes)
110+
111+
set_vertex = cudf.Series(data=vertex_set, dtype=vertex_t)
112+
set_edge = cudf.Series(data=edge_set, dtype=weight_t)
113+
set_sizes = cudf.Series(data=sizes, dtype=edge_t)
114+
115+
return set_vertex, set_edge, set_sizes
116+

python/cugraph/structure/graph_utilities.pxd

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ cdef extern from "utilities/cython.hpp" namespace "cugraph::cython":
8383
unique_ptr[device_buffer] dst_indices
8484
unique_ptr[device_buffer] edge_data
8585
unique_ptr[device_buffer] subgraph_offsets
86+
87+
cdef cppclass random_walk_ret_t:
88+
size_t coalesced_sz_v_
89+
size_t coalesced_sz_w_
90+
size_t num_paths_
91+
size_t max_depth_
92+
unique_ptr[device_buffer] d_coalesced_v_
93+
unique_ptr[device_buffer] d_coalesced_w_
94+
unique_ptr[device_buffer] d_sizes_
8695

8796
cdef extern from "<utility>" namespace "std" nogil:
8897
cdef device_buffer move(device_buffer)

0 commit comments

Comments
 (0)