Skip to content

Commit

Permalink
Merge branch-25.02 into branch-25.04
Browse files Browse the repository at this point in the history
  • Loading branch information
bdice committed Jan 31, 2025
2 parents e511de6 + edd96f0 commit 3d63ba3
Showing 13 changed files with 210 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -3,15 +3,15 @@
"context": "${localWorkspaceFolder}/.devcontainer",
"dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile",
"args": {
"CUDA": "12.5",
"CUDA": "12.8",
"PYTHON_PACKAGE_MANAGER": "conda",
"BASE": "rapidsai/devcontainers:25.04-cpp-mambaforge-ubuntu22.04"
}
},
"runArgs": [
"--rm",
"--name",
"${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-25.04-cuda12.5-conda"
"${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-25.04-cuda12.8-conda"
],
"hostRequirements": {"gpu": "optional"},
"features": {
@@ -20,7 +20,7 @@
"overrideFeatureInstallOrder": [
"ghcr.io/rapidsai/devcontainers/features/rapids-build-utils"
],
"initializeCommand": ["/bin/bash", "-c", "mkdir -m 0755 -p ${localWorkspaceFolder}/../.{aws,cache,config,conda/pkgs,conda/${localWorkspaceFolderBasename}-cuda12.5-envs}"],
"initializeCommand": ["/bin/bash", "-c", "mkdir -m 0755 -p ${localWorkspaceFolder}/../.{aws,cache,config,conda/pkgs,conda/${localWorkspaceFolderBasename}-cuda12.8-envs}"],
"postAttachCommand": ["/bin/bash", "-c", "if [ ${CODESPACES:-false} = 'true' ]; then . devcontainer-utils-post-attach-command; . rapids-post-attach-command; fi"],
"workspaceFolder": "/home/coder",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/nx-cugraph,type=bind,consistency=consistent",
@@ -29,7 +29,7 @@
"source=${localWorkspaceFolder}/../.cache,target=/home/coder/.cache,type=bind,consistency=consistent",
"source=${localWorkspaceFolder}/../.config,target=/home/coder/.config,type=bind,consistency=consistent",
"source=${localWorkspaceFolder}/../.conda/pkgs,target=/home/coder/.conda/pkgs,type=bind,consistency=consistent",
"source=${localWorkspaceFolder}/../.conda/${localWorkspaceFolderBasename}-cuda12.5-envs,target=/home/coder/.conda/envs,type=bind,consistency=consistent"
"source=${localWorkspaceFolder}/../.conda/${localWorkspaceFolderBasename}-cuda12.8-envs,target=/home/coder/.conda/envs,type=bind,consistency=consistent"
],
"customizations": {
"vscode": {
Original file line number Diff line number Diff line change
@@ -3,20 +3,20 @@
"context": "${localWorkspaceFolder}/.devcontainer",
"dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile",
"args": {
"CUDA": "12.5",
"CUDA": "12.8",
"PYTHON_PACKAGE_MANAGER": "pip",
"BASE": "rapidsai/devcontainers:25.04-cpp-cuda12.5-ucx1.18.0-openmpi-ubuntu22.04"
"BASE": "rapidsai/devcontainers:25.04-cpp-cuda12.8-ucx1.18.0-openmpi-ubuntu22.04"
}
},
"runArgs": [
"--rm",
"--name",
"${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-25.04-cuda12.5-pip"
"${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-25.04-cuda12.8-pip"
],
"hostRequirements": {"gpu": "optional"},
"features": {
"ghcr.io/rapidsai/devcontainers/features/cuda:25.4": {
"version": "12.5",
"version": "12.8",
"installcuBLAS": true,
"installcuSOLVER": true,
"installcuRAND": true,
@@ -28,15 +28,15 @@
"ghcr.io/rapidsai/devcontainers/features/cuda",
"ghcr.io/rapidsai/devcontainers/features/rapids-build-utils"
],
"initializeCommand": ["/bin/bash", "-c", "mkdir -m 0755 -p ${localWorkspaceFolder}/../.{aws,cache,config/pip,local/share/${localWorkspaceFolderBasename}-cuda12.5-venvs}"],
"initializeCommand": ["/bin/bash", "-c", "mkdir -m 0755 -p ${localWorkspaceFolder}/../.{aws,cache,config/pip,local/share/${localWorkspaceFolderBasename}-cuda12.8-venvs}"],
"postAttachCommand": ["/bin/bash", "-c", "if [ ${CODESPACES:-false} = 'true' ]; then . devcontainer-utils-post-attach-command; . rapids-post-attach-command; fi"],
"workspaceFolder": "/home/coder",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/nx-cugraph,type=bind,consistency=consistent",
"mounts": [
"source=${localWorkspaceFolder}/../.aws,target=/home/coder/.aws,type=bind,consistency=consistent",
"source=${localWorkspaceFolder}/../.cache,target=/home/coder/.cache,type=bind,consistency=consistent",
"source=${localWorkspaceFolder}/../.config,target=/home/coder/.config,type=bind,consistency=consistent",
"source=${localWorkspaceFolder}/../.local/share/${localWorkspaceFolderBasename}-cuda12.5-venvs,target=/home/coder/.local/share/venvs,type=bind,consistency=consistent"
"source=${localWorkspaceFolder}/../.local/share/${localWorkspaceFolderBasename}-cuda12.8-venvs,target=/home/coder/.local/share/venvs,type=bind,consistency=consistent"
],
"customizations": {
"vscode": {
2 changes: 1 addition & 1 deletion .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@ jobs:
uses: rapidsai/shared-workflows/.github/workflows/build-in-devcontainer.yaml@branch-25.04
with:
arch: '["amd64"]'
cuda: '["12.5"]'
cuda: '["12.8"]'
build_command: |
sccache -z;
build-all --verbose -j$(nproc --ignore=1);
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -154,6 +154,8 @@ Below is the list of algorithms that are currently supported in nx-cugraph.
│ └─ <a href="https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.link_analysis.hits_alg.hits.html#networkx.algorithms.link_analysis.hits_alg.hits">hits</a>
└─ <a href="https://networkx.org/documentation/stable/reference/algorithms/link_analysis.html#module-networkx.algorithms.link_analysis.pagerank_alg">pagerank_alg</a>
└─ <a href="https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.link_analysis.pagerank_alg.pagerank.html#networkx.algorithms.link_analysis.pagerank_alg.pagerank">pagerank</a>
<a href="https://networkx.org/documentation/stable/reference/algorithms/link_prediction.html#module-networkx.algorithms.link_prediction">link_prediction</a>
└─ <a href="https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.link_prediction.jaccard_coefficient.html#networkx.algorithms.link_prediction.jaccard_coefficient">jaccard_coefficient</a>
<a href="https://networkx.org/documentation/stable/reference/algorithms/operators.html">operators</a>
└─ <a href="https://networkx.org/documentation/stable/reference/algorithms/operators.html#module-networkx.algorithms.operators.unary">unary</a>
├─ <a href="https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.operators.unary.complement.html#networkx.algorithms.operators.unary.complement">complement</a>
1 change: 1 addition & 0 deletions _nx_cugraph/__init__.py
Original file line number Diff line number Diff line change
@@ -110,6 +110,7 @@
"is_tree",
"is_weakly_connected",
"isolates",
"jaccard_coefficient",
"k_truss",
"karate_club_graph",
"katz_centrality",
56 changes: 55 additions & 1 deletion benchmarks/pytest-based/bench_algos.py
Original file line number Diff line number Diff line change
@@ -197,7 +197,11 @@ def get_graph_obj_for_benchmark(graph_obj, backend_wrapper):
"""
G = graph_obj
if backend_wrapper.backend_name == "cugraph-preconverted":
G = nxcg.from_networkx(G, preserve_all_attrs=True)
G = nxcg.from_networkx(
G,
preserve_all_attrs=True,
use_compat_graph=True,
)
return G


@@ -319,6 +323,27 @@ def bench_louvain_communities(benchmark, graph_obj, backend_wrapper):
assert type(result) is list


@pytest.mark.skipif("not hasattr(nx.community, 'leiden_communities')")
def bench_leiden_communities(benchmark, graph_obj, backend_wrapper):
G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper)
# DiGraphs are not supported
if G.is_directed():
G = G.to_undirected()
if G.__networkx_backend__ not in nx.community.leiden_communities.backends:
pytest.skip(
reason=f"leiden_communities not implemented by {G.__networkx_backend__!r}"
)
return
result = benchmark.pedantic(
target=backend_wrapper(nx.community.leiden_communities),
args=(G,),
rounds=rounds,
iterations=iterations,
warmup_rounds=warmup_rounds,
)
assert type(result) is list


def bench_degree_centrality(benchmark, graph_obj, backend_wrapper):
G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper)
result = benchmark.pedantic(
@@ -898,6 +923,35 @@ def bench_bipartite_BC_n1000_m3000_k100000(benchmark, backend_wrapper):
assert type(result) is dict


def bench_jaccard(benchmark, graph_obj, backend_wrapper):
G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper)

# ebunch is a list of node pairs to limit the jaccard run.
nodes = list(G.nodes)
start = nodes[0]
ebunch = [(start, n) for n in nodes[1:]]
start = nodes[1]
ebunch += [(start, n) for n in nodes[2:]]
start = nodes[2]
ebunch += [(start, n) for n in nodes[3:]]

# DiGraphs are not supported
if G.is_directed():
G = G.to_undirected()

result = benchmark.pedantic(
target=backend_wrapper(nx.jaccard_coefficient, force_unlazy_eval=True),
args=(G,),
kwargs=dict(
ebunch=ebunch,
),
rounds=rounds,
iterations=iterations,
warmup_rounds=warmup_rounds,
)
assert type(result) is list


@pytest.mark.skip(reason="benchmark not implemented")
def bench_complete_bipartite_graph(benchmark, graph_obj, backend_wrapper):
pass
6 changes: 3 additions & 3 deletions benchmarks/pytest-based/run-main-benchmarks.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# Copyright (c) 2024, NVIDIA CORPORATION.
# Copyright (c) 2024-2025, NVIDIA CORPORATION.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -58,8 +58,8 @@ fi

for algo in $algos; do
for dataset in $datasets; do
# this script can be used to download benchmarking datasets by name via cugraph.datasets
python get_graph_bench_dataset.py $dataset
# this script can be used to download benchmarking datasets by name via cugraph.datasets
python get_graph_bench_dataset.py $dataset
for backend in $backends; do
name="${backend}__${algo}__${dataset}"
echo "Running: $backend, $dataset, bench_$algo"
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ channels:
- conda-forge
- nvidia
dependencies:
- cuda-version=12.5
- cuda-version=12.8
- cudf==25.4.*,>=0.0.0a0
- cupy>=12.0.0
- graphviz
@@ -33,4 +33,4 @@ dependencies:
- sphinx-markdown-tables
- sphinxcontrib-websupport
- wheel
name: all_cuda-125_arch-x86_64
name: all_cuda-128_arch-x86_64
6 changes: 5 additions & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ files:
all:
output: [conda]
matrix:
cuda: ["11.8", "12.5"]
cuda: ["11.8", "12.8"]
arch: [x86_64]
includes:
- checks
@@ -113,6 +113,10 @@ dependencies:
cuda: "12.5"
packages:
- cuda-version=12.5
- matrix:
cuda: "12.8"
packages:
- cuda-version=12.8
docs:
common:
- output_types: [conda]
4 changes: 3 additions & 1 deletion nx_cugraph/algorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023-2024, NVIDIA CORPORATION.
# Copyright (c) 2023-2025, NVIDIA CORPORATION.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -17,6 +17,7 @@
community,
components,
link_analysis,
link_prediction,
operators,
shortest_paths,
traversal,
@@ -30,6 +31,7 @@
from .dag import *
from .isolate import *
from .link_analysis import *
from .link_prediction import *
from .operators import *
from .reciprocity import *
from .shortest_paths import *
68 changes: 68 additions & 0 deletions nx_cugraph/algorithms/link_prediction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright (c) 2025, NVIDIA CORPORATION.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import cupy as cp
import networkx as nx
import pylibcugraph as plc

from nx_cugraph.convert import _to_undirected_graph
from nx_cugraph.utils import index_dtype, networkx_algorithm, not_implemented_for

__all__ = [
"jaccard_coefficient",
]


@not_implemented_for("directed")
@not_implemented_for("multigraph")
@networkx_algorithm(version_added="25.02", _plc="jaccard_coefficients")
def jaccard_coefficient(G, ebunch=None):
G = _to_undirected_graph(G)

# If ebunch is not specified, create pairs representing all non-edges.
# This can be an extremely large set and is not realistic for large graphs,
# but this is required for NX compatibility.
if ebunch is None:
A = cp.tri(G._N, G._N, dtype=bool)
A[G.src_indices, G.dst_indices] = True
u_indices, v_indices = cp.nonzero(~A)
if u_indices.size == 0:
return iter([])
u_indices = u_indices.astype(index_dtype)
v_indices = v_indices.astype(index_dtype)

else:
(u, v) = zip(*ebunch)
try:
# Convert the ebunch lists to cupy arrays for passing to PLC, possibly
# mapping to integers if the Graph was renumbered.
# Allow the Graph renumber lookup (if renumbering was done) to check
# for invalid node IDs in ebunch.
u_indices = G._list_to_nodearray(u)
v_indices = G._list_to_nodearray(v)
except (KeyError, ValueError) as n:
raise nx.NodeNotFound(f"Node {n} not in G.")

(u, v, p) = plc.jaccard_coefficients(
resource_handle=plc.ResourceHandle(),
graph=G._get_plc_graph(),
first=u_indices,
second=v_indices,
use_weight=False,
do_expensive_check=False,
)

u = G._nodearray_to_list(u)
v = G._nodearray_to_list(v)
p = p.tolist()

return zip(u, v, p)
16 changes: 15 additions & 1 deletion nx_cugraph/classes/graph.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023-2024, NVIDIA CORPORATION.
# Copyright (c) 2023-2025, NVIDIA CORPORATION.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -1009,6 +1009,11 @@ def _get_plc_graph(
dst_indices = self.dst_indices
if switch_indices:
src_indices, dst_indices = dst_indices, src_indices

# FIXME: the SGGraph constructor arg "symmetrize" will perform all
# symmetrization steps required by libcugraph. The edge_array check
# should be kept, but all other code in this `if` block should be
# removed if possible.
if symmetrize is not None:
if edge_array is not None:
raise NotImplementedError(
@@ -1147,6 +1152,15 @@ def _nodearray_to_list(self, node_ids: cp.ndarray[IndexValue]) -> list[NodeKey]:
def _list_to_nodearray(self, nodes: list[NodeKey]) -> cp.ndarray[IndexValue]:
if (key_to_id := self.key_to_id) is not None:
nodes = [key_to_id[node] for node in nodes]
else:
N = self._N
for node in nodes:
try:
n = int(node)
except (TypeError, ValueError):
raise KeyError(node) from None
if n != node or n < 0 or n >= N:
raise KeyError(node)
return cp.array(nodes, dtype=index_dtype)

def _nodearray_to_set(self, node_ids: cp.ndarray[IndexValue]) -> set[NodeKey]:
Loading
Oops, something went wrong.

0 comments on commit 3d63ba3

Please sign in to comment.