diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..96e491f4c --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,35 @@ +# syntax=docker/dockerfile:1.5 + +ARG BASE +ARG PYTHON_PACKAGE_MANAGER=conda + +FROM ${BASE} as pip-base + +ENV DEFAULT_VIRTUAL_ENV=rapids + +RUN apt update -y \ + && DEBIAN_FRONTEND=noninteractive apt install -y \ + libblas-dev liblapack-dev \ + && rm -rf /tmp/* /var/tmp/* /var/cache/apt/* /var/lib/apt/lists/*; + +FROM ${BASE} as conda-base + +ENV DEFAULT_CONDA_ENV=rapids + +FROM ${PYTHON_PACKAGE_MANAGER}-base + +ARG CUDA +ENV CUDAARCHS="RAPIDS" +ENV CUDA_VERSION="${CUDA_VERSION:-${CUDA}}" + +ARG PYTHON_PACKAGE_MANAGER +ENV PYTHON_PACKAGE_MANAGER="${PYTHON_PACKAGE_MANAGER}" + +ENV PYTHONSAFEPATH="1" +ENV PYTHONUNBUFFERED="1" +ENV PYTHONDONTWRITEBYTECODE="1" + +ENV SCCACHE_REGION="us-east-2" +ENV SCCACHE_BUCKET="rapids-sccache-devs" +ENV AWS_ROLE_ARN="arn:aws:iam::279114543810:role/nv-gha-token-sccache-devs" +ENV HISTFILE="/home/coder/.cache/._bash_history" diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 000000000..81692bb87 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,34 @@ +# nx-cugraph Development Containers + +This directory contains [devcontainer configurations](https://containers.dev/implementors/json_reference/) for using VSCode to [develop in a container](https://code.visualstudio.com/docs/devcontainers/containers) via the `Remote Containers` [extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) or [GitHub Codespaces](https://github.com/codespaces). + +This container is a turnkey development environment for building and testing nx-cugraph. + +## Table of Contents + +* [Prerequisites](#prerequisites) +* [Host bind mounts](#host-bind-mounts) +* [Launch a Dev Container](#launch-a-dev-container) +## Prerequisites + +* [VSCode](https://code.visualstudio.com/download) +* [VSCode Remote Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) + +## Host bind mounts + +By default, the following directories are bind-mounted into the devcontainer: + +* `${repo}:/home/coder/nx-cugraph` +* `${repo}/../.aws:/home/coder/.aws` +* `${repo}/../.local:/home/coder/.local` +* `${repo}/../.cache:/home/coder/.cache` +* `${repo}/../.conda:/home/coder/.conda` +* `${repo}/../.config:/home/coder/.config` + +This ensures caches, configurations, dependencies, and your commits are persisted on the host across container runs. + +## Launch a Dev Container + +To launch a devcontainer from VSCode, open the nx-cugraph repo and select the "Reopen in Container" button in the bottom right. + +Alternatively, open the VSCode command palette (typically `cmd/ctrl + shift + P`) and run the "Rebuild and Reopen in Container" command. diff --git a/.devcontainer/cuda11.8-conda/devcontainer.json b/.devcontainer/cuda11.8-conda/devcontainer.json new file mode 100644 index 000000000..d67f9ee2a --- /dev/null +++ b/.devcontainer/cuda11.8-conda/devcontainer.json @@ -0,0 +1,42 @@ +{ + "build": { + "context": "${localWorkspaceFolder}/.devcontainer", + "dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile", + "args": { + "CUDA": "11.8", + "PYTHON_PACKAGE_MANAGER": "conda", + "BASE": "rapidsai/devcontainers:24.12-cpp-cuda11.8-mambaforge-ubuntu22.04" + } + }, + "runArgs": [ + "--rm", + "--name", + "${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-24.12-cuda11.8-conda" + ], + "hostRequirements": {"gpu": "optional"}, + "features": { + "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils:24.12": {} + }, + "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}-cuda11.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", + "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}/../.conda/pkgs,target=/home/coder/.conda/pkgs,type=bind,consistency=consistent", + "source=${localWorkspaceFolder}/../.conda/${localWorkspaceFolderBasename}-cuda11.8-envs,target=/home/coder/.conda/envs,type=bind,consistency=consistent" + ], + "customizations": { + "vscode": { + "extensions": [ + "ms-python.flake8", + "nvidia.nsight-vscode-edition" + ] + } + } +} diff --git a/.devcontainer/cuda11.8-pip/devcontainer.json b/.devcontainer/cuda11.8-pip/devcontainer.json new file mode 100644 index 000000000..626af5a54 --- /dev/null +++ b/.devcontainer/cuda11.8-pip/devcontainer.json @@ -0,0 +1,49 @@ +{ + "build": { + "context": "${localWorkspaceFolder}/.devcontainer", + "dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile", + "args": { + "CUDA": "11.8", + "PYTHON_PACKAGE_MANAGER": "pip", + "BASE": "rapidsai/devcontainers:24.12-cpp-cuda11.8-ucx1.15.0-openmpi-ubuntu22.04" + } + }, + "runArgs": [ + "--rm", + "--name", + "${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-24.12-cuda11.8-pip" + ], + "hostRequirements": {"gpu": "optional"}, + "features": { + "ghcr.io/rapidsai/devcontainers/features/cuda:24.12": { + "version": "11.8", + "installcuBLAS": true, + "installcuSOLVER": true, + "installcuRAND": true, + "installcuSPARSE": true + }, + "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils:24.12": {} + }, + "overrideFeatureInstallOrder": [ + "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}-cuda11.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}-cuda11.8-venvs,target=/home/coder/.local/share/venvs,type=bind,consistency=consistent" + ], + "customizations": { + "vscode": { + "extensions": [ + "ms-python.flake8", + "nvidia.nsight-vscode-edition" + ] + } + } +} diff --git a/.devcontainer/cuda12.5-conda/devcontainer.json b/.devcontainer/cuda12.5-conda/devcontainer.json new file mode 100644 index 000000000..8f4db8c4a --- /dev/null +++ b/.devcontainer/cuda12.5-conda/devcontainer.json @@ -0,0 +1,42 @@ +{ + "build": { + "context": "${localWorkspaceFolder}/.devcontainer", + "dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile", + "args": { + "CUDA": "12.5", + "PYTHON_PACKAGE_MANAGER": "conda", + "BASE": "rapidsai/devcontainers:24.12-cpp-mambaforge-ubuntu22.04" + } + }, + "runArgs": [ + "--rm", + "--name", + "${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-24.12-cuda12.5-conda" + ], + "hostRequirements": {"gpu": "optional"}, + "features": { + "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils:24.12": {} + }, + "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}"], + "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}/../.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" + ], + "customizations": { + "vscode": { + "extensions": [ + "ms-python.flake8", + "nvidia.nsight-vscode-edition" + ] + } + } +} diff --git a/.devcontainer/cuda12.5-pip/devcontainer.json b/.devcontainer/cuda12.5-pip/devcontainer.json new file mode 100644 index 000000000..d970002d6 --- /dev/null +++ b/.devcontainer/cuda12.5-pip/devcontainer.json @@ -0,0 +1,49 @@ +{ + "build": { + "context": "${localWorkspaceFolder}/.devcontainer", + "dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile", + "args": { + "CUDA": "12.5", + "PYTHON_PACKAGE_MANAGER": "pip", + "BASE": "rapidsai/devcontainers:24.12-cpp-cuda12.5-ucx1.17.0-openmpi-ubuntu22.04" + } + }, + "runArgs": [ + "--rm", + "--name", + "${localEnv:USER:anon}-rapids-${localWorkspaceFolderBasename}-24.12-cuda12.5-pip" + ], + "hostRequirements": {"gpu": "optional"}, + "features": { + "ghcr.io/rapidsai/devcontainers/features/cuda:24.12": { + "version": "12.5", + "installcuBLAS": true, + "installcuSOLVER": true, + "installcuRAND": true, + "installcuSPARSE": true + }, + "ghcr.io/rapidsai/devcontainers/features/rapids-build-utils:24.12": {} + }, + "overrideFeatureInstallOrder": [ + "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}"], + "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" + ], + "customizations": { + "vscode": { + "extensions": [ + "ms-python.flake8", + "nvidia.nsight-vscode-edition" + ] + } + } +} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index e74ba55ec..0f8a705ea 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -14,6 +14,7 @@ jobs: needs: - changed-files - checks + - devcontainer - conda-python-build - conda-python-tests - wheel-build-nx-cugraph @@ -30,13 +31,25 @@ jobs: files_yaml: | test_notebooks: - '**' + - '!.devcontainer/**' - '!README.md' - '!docs/**' test_python: - '**' + - '!.devcontainer/**' - '!README.md' - '!docs/**' - '!notebooks/**' + devcontainer: + secrets: inherit + uses: rapidsai/shared-workflows/.github/workflows/build-in-devcontainer.yaml@branch-24.12 + with: + arch: '["amd64"]' + cuda: '["12.5"]' + build_command: | + sccache -z; + build-all --verbose -j$(nproc --ignore=1); + sccache -s; checks: secrets: inherit uses: rapidsai/shared-workflows/.github/workflows/checks.yaml@branch-24.12 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d748cd92e..e98b01fbb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -49,6 +49,7 @@ repos: rev: 24.10.0 hooks: - id: black + # - id: black-jupyter # Consider adding this - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.7.3 hooks: @@ -108,6 +109,11 @@ repos: language: python pass_filenames: false additional_dependencies: ["networkx>=3.4"] + - repo: https://github.com/sphinx-contrib/sphinx-lint + rev: v1.0.0 + hooks: + - id: sphinx-lint + args: ["--enable=all", "--disable=line-too-long"] - repo: https://github.com/rapidsai/pre-commit-hooks rev: v0.4.0 hooks: diff --git a/benchmarks/nx-cugraph/pytest-based/bench_algos.py b/benchmarks/nx-cugraph/pytest-based/bench_algos.py index 015318c5a..d5257e2ef 100644 --- a/benchmarks/nx-cugraph/pytest-based/bench_algos.py +++ b/benchmarks/nx-cugraph/pytest-based/bench_algos.py @@ -130,12 +130,21 @@ def get_backend_wrapper(backend_name): "backend" kwarg on it. """ - def wrap_callable_for_dispatch(func, exhaust_returned_iterator=False): + # FIXME: consider a pytest param to run force_unlazy_eval=False for + # benchmarks that set it to True in order to measure the time spent for any + # deferred computation/conversions. + def wrap_callable_for_dispatch(func, force_unlazy_eval=False): + # force_unlazy_eval=True forces iterators and other containers to + # generate a complete set of results in order to include any deferred + # compute or conversion in the benchmark def wrapper(*args, **kwargs): kwargs["backend"] = backend_name retval = func(*args, **kwargs) - if exhaust_returned_iterator: - retval = list(retval) + if force_unlazy_eval: + if isinstance(retval, Mapping): + retval = dict(retval) + else: + retval = list(retval) return retval return wrapper @@ -440,7 +449,7 @@ def bench_shortest_path(benchmark, graph_obj, backend_wrapper): node = get_highest_degree_node(graph_obj) result = benchmark.pedantic( - target=backend_wrapper(nx.shortest_path), + target=backend_wrapper(nx.shortest_path, force_unlazy_eval=True), args=(G,), kwargs=dict( source=node, @@ -474,7 +483,7 @@ def bench_single_target_shortest_path_length(benchmark, graph_obj, backend_wrapp node = get_highest_degree_node(graph_obj) result = benchmark.pedantic( target=backend_wrapper( - nx.single_target_shortest_path_length, exhaust_returned_iterator=True + nx.single_target_shortest_path_length, force_unlazy_eval=True ), args=(G,), kwargs=dict( @@ -484,9 +493,11 @@ def bench_single_target_shortest_path_length(benchmark, graph_obj, backend_wrapp iterations=iterations, warmup_rounds=warmup_rounds, ) - # exhaust_returned_iterator=True forces the result to a list, but is not - # needed for this algo in NX 3.3+ which returns a dict instead of an - # iterator. Forcing to a list does not change the benchmark timing. + # force_unlazy_eval=True forces iterators and other containers to generate + # a complete set of results (in order to include any deferred compute or + # conversion in the benchmark), but is not needed for this algo in NX 3.3+ + # since it returns a dict instead of an iterator. Forcing eval does not + # change the benchmark timing. assert type(result) is list @@ -525,7 +536,7 @@ def bench_generic_bfs_edges(benchmark, graph_obj, backend_wrapper): G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper) node = get_highest_degree_node(graph_obj) result = benchmark.pedantic( - target=backend_wrapper(nx.generic_bfs_edges, exhaust_returned_iterator=True), + target=backend_wrapper(nx.generic_bfs_edges, force_unlazy_eval=True), args=(G,), kwargs=dict( source=node, @@ -541,7 +552,7 @@ def bench_bfs_edges(benchmark, graph_obj, backend_wrapper): G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper) node = get_highest_degree_node(graph_obj) result = benchmark.pedantic( - target=backend_wrapper(nx.bfs_edges, exhaust_returned_iterator=True), + target=backend_wrapper(nx.bfs_edges, force_unlazy_eval=True), args=(G,), kwargs=dict( source=node, @@ -557,7 +568,7 @@ def bench_bfs_layers(benchmark, graph_obj, backend_wrapper): G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper) node = get_highest_degree_node(graph_obj) result = benchmark.pedantic( - target=backend_wrapper(nx.bfs_layers, exhaust_returned_iterator=True), + target=backend_wrapper(nx.bfs_layers, force_unlazy_eval=True), args=(G,), kwargs=dict( sources=node, @@ -573,7 +584,7 @@ def bench_bfs_predecessors(benchmark, graph_obj, backend_wrapper): G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper) node = get_highest_degree_node(graph_obj) result = benchmark.pedantic( - target=backend_wrapper(nx.bfs_predecessors, exhaust_returned_iterator=True), + target=backend_wrapper(nx.bfs_predecessors, force_unlazy_eval=True), args=(G,), kwargs=dict( source=node, @@ -589,7 +600,7 @@ def bench_bfs_successors(benchmark, graph_obj, backend_wrapper): G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper) node = get_highest_degree_node(graph_obj) result = benchmark.pedantic( - target=backend_wrapper(nx.bfs_successors, exhaust_returned_iterator=True), + target=backend_wrapper(nx.bfs_successors, force_unlazy_eval=True), args=(G,), kwargs=dict( source=node, @@ -773,7 +784,7 @@ def bench_strongly_connected_components(benchmark, graph_obj, backend_wrapper): G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper) result = benchmark.pedantic( target=backend_wrapper( - nx.strongly_connected_components, exhaust_returned_iterator=True + nx.strongly_connected_components, force_unlazy_eval=True ), args=(G,), rounds=rounds, @@ -816,9 +827,7 @@ def bench_triangles(benchmark, graph_obj, backend_wrapper): def bench_weakly_connected_components(benchmark, graph_obj, backend_wrapper): G = get_graph_obj_for_benchmark(graph_obj, backend_wrapper) result = benchmark.pedantic( - target=backend_wrapper( - nx.weakly_connected_components, exhaust_returned_iterator=True - ), + target=backend_wrapper(nx.weakly_connected_components, force_unlazy_eval=True), args=(G,), rounds=rounds, iterations=iterations, diff --git a/docs/nx-cugraph/Makefile b/docs/nx-cugraph/Makefile deleted file mode 100644 index ac16367ef..000000000 --- a/docs/nx-cugraph/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = "-v" -SPHINXBUILD = sphinx-build -SPHINXPROJ = cugraph -SOURCEDIR = source -BUILDDIR = build -IMGDIR = images - -gen_doc_dirs = build source/api_docs/api -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile clean - -# clean to remove all the generated documentation files in build and source -clean: - rm -rf $(gen_doc_dirs) - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/nx-cugraph/README.md b/docs/nx-cugraph/README.md deleted file mode 100644 index 970a03a04..000000000 --- a/docs/nx-cugraph/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Building Documentation - -All prerequisite for building docs are in the cugraph development conda environment. -[See build instructions](../../SOURCEBUILD.md) on how to create the development conda environment - -## Steps to follow: - -In order to build the docs, we need the conda dev environment from cugraph and we need to build cugraph from source. - -1. Create a conda env and build cugraph from source. The dependencies to build rapids from source are installed in that conda environment, and then rapids is built and installed into the same environment. - -2. Once cugraph is built from source, navigate to `../docs/cugraph/`. If you have your documentation written and want to turn it into HTML, run makefile: - - -```bash -# most be in the /docs/cugraph directory -make html -``` - -This should run Sphinx in your shell, and outputs to `build/html/index.html` - - -## View docs web page by opening HTML in browser: - -First navigate to `/build/html/` folder, and then run the following command: - -```bash -python -m http.server -``` -Then, navigate a web browser to the IP address or hostname of the host machine at port 8000: - -``` -https://:8000 -``` -Now you can check if your docs edits formatted correctly, and read well. diff --git a/docs/nx-cugraph/make.bat b/docs/nx-cugraph/make.bat deleted file mode 100644 index 807e0de85..000000000 --- a/docs/nx-cugraph/make.bat +++ /dev/null @@ -1,36 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build -set SPHINXPROJ=cuGraph - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% - -:end -popd diff --git a/docs/nx-cugraph/source/_static/EMPTY b/docs/nx-cugraph/source/_static/EMPTY deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/nx-cugraph/source/_static/bc_benchmark.png b/docs/nx-cugraph/source/_static/bc_benchmark.png deleted file mode 100644 index 9e385c97e..000000000 Binary files a/docs/nx-cugraph/source/_static/bc_benchmark.png and /dev/null differ diff --git a/docs/nx-cugraph/source/_static/colab.png b/docs/nx-cugraph/source/_static/colab.png deleted file mode 100644 index c4c3f5b46..000000000 Binary files a/docs/nx-cugraph/source/_static/colab.png and /dev/null differ diff --git a/docs/nx-cugraph/source/_static/nxcg-execution-diagram.jpg b/docs/nx-cugraph/source/_static/nxcg-execution-diagram.jpg deleted file mode 100644 index 48136289a..000000000 Binary files a/docs/nx-cugraph/source/_static/nxcg-execution-diagram.jpg and /dev/null differ diff --git a/docs/nx-cugraph/source/_static/references.css b/docs/nx-cugraph/source/_static/references.css deleted file mode 100644 index d1f647233..000000000 --- a/docs/nx-cugraph/source/_static/references.css +++ /dev/null @@ -1,23 +0,0 @@ - -/* Fix references to not look like parameters */ -dl.citation > dt.label { - display: unset !important; - float: left !important; - border: unset !important; - background: unset !important; - padding: unset !important; - margin: unset !important; - font-size: unset !important; - line-height: unset !important; - padding-right: 0.5rem !important; -} - -/* Add opening bracket */ -dl.citation > dt.label > span::before { - content: "["; -} - -/* Add closing bracket */ -dl.citation > dt.label > span::after { - content: "]"; -} diff --git a/docs/nx-cugraph/source/api_docs/index.rst b/docs/nx-cugraph/source/api_docs/index.rst deleted file mode 100644 index c4b90b579..000000000 --- a/docs/nx-cugraph/source/api_docs/index.rst +++ /dev/null @@ -1,37 +0,0 @@ -API Reference -============= - -This page provides a list of all publicly accessible Python modules with in the Graph collection - -Core Graph API Documentation ----------------------------- - -.. toctree:: - :maxdepth: 3 - :caption: Core Graph API Documentation - - cugraph/index.rst - plc/pylibcugraph.rst - cugraph_c/index.rst - cugraph_cpp/index.rst - -Graph Neural Networks API Documentation ---------------------------------------- - -.. toctree:: - :maxdepth: 3 - :caption: Graph Neural Networks API Documentation - - cugraph-dgl/cugraph_dgl.rst - cugraph-pyg/cugraph_pyg.rst - cugraph-ops/index.rst - wholegraph/index.rst - -Additional Graph Packages API Documentation ----------------------------------- - -.. toctree:: - :maxdepth: 3 - :caption: Additional Graph Packages API Documentation - - service/index.rst diff --git a/docs/nx-cugraph/source/conf.py b/docs/nx-cugraph/source/conf.py deleted file mode 100644 index f03d7f4a3..000000000 --- a/docs/nx-cugraph/source/conf.py +++ /dev/null @@ -1,239 +0,0 @@ -# Copyright (c) 2018-2024, NVIDIA CORPORATION. -# -# pygdf documentation build configuration file, created by -# sphinx-quickstart on Wed May 3 10:59:22 2017. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -import sys - -from github_link import make_linkcode_resolve -from packaging.version import Version - -import nx_cugraph - -# If extensions (or modules to document with autodoc) are in another -# directory, add these directories to sys.path here. If the directory -# is relative to the documentation root, use os.path.abspath to make it -# absolute, like shown here. -sys.path.insert(0, os.path.abspath("sphinxext")) - - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "breathe", - "sphinx.ext.intersphinx", - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "numpydoc", - "sphinx_markdown_tables", - "sphinx.ext.doctest", - "sphinx.ext.linkcode", - "IPython.sphinxext.ipython_console_highlighting", - "IPython.sphinxext.ipython_directive", - "nbsphinx", - "recommonmark", - "sphinx_copybutton", -] - - -ipython_mplbackend = "str" - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = {".rst": "restructuredtext", ".md": "markdown"} - -# The master toctree document. -master_doc = "index" - -# General information about the project. -project = "nx-cugraph" -copyright = "2019-2024, NVIDIA Corporation" -author = "NVIDIA Corporation" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -NXCG_VERSION = Version(nx_cugraph.__version__) -# The short X.Y version. -version = f"{NXCG_VERSION.major:02}.{NXCG_VERSION.minor:02}" -# The full version, including alpha/beta/rc tags. Skipping `black` formatting -# for readability -# fmt: off -release = f"{NXCG_VERSION.major:02}.{NXCG_VERSION.minor:02}.{NXCG_VERSION.micro:02}" -# fmt: on - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = "en" - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = [] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# - -html_theme = "pydata_sphinx_theme" - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -html_theme_options = { - "external_links": [], - "github_url": "https://github.com/rapidsai/nx-cugraph", - "twitter_url": "https://twitter.com/rapidsai", - "show_toc_level": 1, - "navbar_align": "right", -} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - - -# -- Options for HTMLHelp output ------------------------------------------ - -# Output file base name for HTML help builder. -htmlhelp_basename = "nx-cugraphdoc" - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ( - master_doc, - "cugraph.tex", - "cugraph Documentation", - "NVIDIA Corporation", - "manual", - ), -] - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "nx-cugraph", "nx-cugraph Documentation", [author], 1)] - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "nx-cugraph", - "nx-cugraph Documentation", - author, - "nx-cugraph", - "GPU-accelerated graph analysis.", - "Miscellaneous", - ), -] - -# Connect docs in other projects -intersphinx_mapping = { - "networkx": ( - "https://networkx.org/documentation/stable/", - "https://networkx.org/documentation/stable/objects.inv", - ), - "python": ( - "https://docs.python.org/3", - "https://docs.python.org/3/objects.inv", - ), -} - -# Config numpydoc -numpydoc_show_inherited_class_members = False -numpydoc_class_members_toctree = False - - -def setup(app): - app.add_css_file("https://docs.rapids.ai/assets/css/custom.css") - app.add_js_file( - "https://docs.rapids.ai/assets/js/custom.js", loading_method="defer" - ) - app.add_css_file("references.css") - - -source_suffix = [".rst", ".md"] - -# The following is used by sphinx.ext.linkcode to provide links to github -linkcode_resolve = make_linkcode_resolve( - "https://github.com/rapidsai/nx_cugraph/blob/{revision}/python/{path}#L{lineno}" -) - -breathe_projects = { - "libcugraph": os.environ["XML_DIR_LIBCUGRAPH"], - "libcugraphops": os.environ["XML_DIR_LIBCUGRAPHOPS"], - "libwholegraph": os.environ["XML_DIR_LIBWHOLEGRAPH"], -} - -breathe_default_project = "libcugraph" diff --git a/docs/nx-cugraph/source/dev_resources/API.rst b/docs/nx-cugraph/source/dev_resources/API.rst deleted file mode 100644 index e32315d2f..000000000 --- a/docs/nx-cugraph/source/dev_resources/API.rst +++ /dev/null @@ -1,5 +0,0 @@ -=== -API -=== - -https://docs.rapids.ai/api/cugraph/nightly/api_docs/index.html diff --git a/docs/nx-cugraph/source/dev_resources/index.rst b/docs/nx-cugraph/source/dev_resources/index.rst deleted file mode 100644 index fc2c4f478..000000000 --- a/docs/nx-cugraph/source/dev_resources/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -=================== -Developer Resources -=================== - - -.. toctree:: - :maxdepth: 3 - - https://docs.rapids.ai/maintainers - API.rst diff --git a/docs/nx-cugraph/source/images/Nx_Cg_1.png b/docs/nx-cugraph/source/images/Nx_Cg_1.png deleted file mode 100644 index 6d29f76ad..000000000 Binary files a/docs/nx-cugraph/source/images/Nx_Cg_1.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/Nx_Cg_2.png b/docs/nx-cugraph/source/images/Nx_Cg_2.png deleted file mode 100644 index f8f685386..000000000 Binary files a/docs/nx-cugraph/source/images/Nx_Cg_2.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/Stack2.png b/docs/nx-cugraph/source/images/Stack2.png deleted file mode 100644 index 132e85c9d..000000000 Binary files a/docs/nx-cugraph/source/images/Stack2.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/ancestors.png b/docs/nx-cugraph/source/images/ancestors.png deleted file mode 100644 index 37b8e7933..000000000 Binary files a/docs/nx-cugraph/source/images/ancestors.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/bfs_tree.png b/docs/nx-cugraph/source/images/bfs_tree.png deleted file mode 100644 index 5bca39ca3..000000000 Binary files a/docs/nx-cugraph/source/images/bfs_tree.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/conn_component.png b/docs/nx-cugraph/source/images/conn_component.png deleted file mode 100644 index b7db09657..000000000 Binary files a/docs/nx-cugraph/source/images/conn_component.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/cugraph_logo_2.png b/docs/nx-cugraph/source/images/cugraph_logo_2.png deleted file mode 100644 index 62dd79c4b..000000000 Binary files a/docs/nx-cugraph/source/images/cugraph_logo_2.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/descendents.png b/docs/nx-cugraph/source/images/descendents.png deleted file mode 100644 index 8afc38b4e..000000000 Binary files a/docs/nx-cugraph/source/images/descendents.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/k_truss.png b/docs/nx-cugraph/source/images/k_truss.png deleted file mode 100644 index 78a1978d1..000000000 Binary files a/docs/nx-cugraph/source/images/k_truss.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/katz.png b/docs/nx-cugraph/source/images/katz.png deleted file mode 100644 index 9f2303a21..000000000 Binary files a/docs/nx-cugraph/source/images/katz.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/pagerank.png b/docs/nx-cugraph/source/images/pagerank.png deleted file mode 100644 index 193c0a8bb..000000000 Binary files a/docs/nx-cugraph/source/images/pagerank.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/pg_example.png b/docs/nx-cugraph/source/images/pg_example.png deleted file mode 100644 index 5ce8a0f20..000000000 Binary files a/docs/nx-cugraph/source/images/pg_example.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/sssp.png b/docs/nx-cugraph/source/images/sssp.png deleted file mode 100644 index 2c9dfc368..000000000 Binary files a/docs/nx-cugraph/source/images/sssp.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/wcc.png b/docs/nx-cugraph/source/images/wcc.png deleted file mode 100644 index 2d27a3f67..000000000 Binary files a/docs/nx-cugraph/source/images/wcc.png and /dev/null differ diff --git a/docs/nx-cugraph/source/images/zachary_graph_centrality.png b/docs/nx-cugraph/source/images/zachary_graph_centrality.png deleted file mode 100644 index 54a91314d..000000000 Binary files a/docs/nx-cugraph/source/images/zachary_graph_centrality.png and /dev/null differ diff --git a/docs/nx-cugraph/source/index.rst b/docs/nx-cugraph/source/index.rst deleted file mode 100644 index c9243f63e..000000000 --- a/docs/nx-cugraph/source/index.rst +++ /dev/null @@ -1,85 +0,0 @@ -RAPIDS Graph documentation -========================== - -.. image:: images/cugraph_logo_2.png - :width: 600 - - -~~~~~~~~~~~~ -Introduction -~~~~~~~~~~~~ -cuGraph is a library of graph algorithms that seamlessly integrates into the -RAPIDS data science ecosystem and allows the data scientist to easily call -graph algorithms using data stored in GPU DataFrames, NetworkX Graphs, or even -CuPy or SciPy sparse Matrices. Our major integration effort with NetworkX -allows for **zero code change** GPU acceleration through the use of the -nx-cugraph backend. NetworkX and the nx-cugraph backend offer a seamless -transition to GPU accelerated graph analytics for NetworkX users with access to -a supported GPU. - -Getting started with cuGraph - -Required hardware/software for cuGraph and `RAPIDS `_ - * NVIDIA GPU, Volta architecture or later, with `compute capability 7.0+`_ - * CUDA 11.2-11.8, 12.0-12.5 - * Python version 3.10, 3.11, or 3.12 - * NetworkX version 3.2 or newer in order to use use the nx-cuGraph backend. NetworkX version 3.4 or newer is recommended. (`see below <#cugraph-using-networkx-code>`). - -Installation -The latest RAPIDS System Requirements documentation is located `here `_. - -This includes several ways to set up cuGraph - -* From Unix - - * `Conda `_ - * `Docker `_ - * `pip `_ - - -**Note: Windows use of RAPIDS depends on prior installation of** `WSL2 `_. - -* From Windows - - * `Conda `_ - * `Docker `_ - * `pip `_ - - -cuGraph Using NetworkX Code - -cuGraph is now available as a NetworkX backend using `nx-cugraph `_. -nx-cugraph offers NetworkX users a **zero code change** option to accelerate -their existing NetworkX code using an NVIDIA GPU and cuGraph. - - - Cugraph API Example - - .. code-block:: python - - import cugraph - import cudf - - # Create an instance of the popular Zachary Karate Club graph - from cugraph.datasets import karate - G = karate.get_graph() - - # Call cugraph.degree_centrality - vertex_bc = cugraph.degree_centrality(G) - -There are several resources containing cuGraph examples, `the cuGraph notebook repository `_ -has many examples of loading graph data and running algorithms in Jupyter notebooks. -The `cuGraph test code _` contain python scripts setting up and calling cuGraph algorithms. -A simple example of `testing the degree centrality algorithm `_ -is a good place to start. Some of these show `multi-GPU tests/examples `_ with larger data sets as well. - -.. toctree:: - :maxdepth: 2 - - top_toc - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` diff --git a/docs/nx-cugraph/source/nx_cugraph/benchmarks.md b/docs/nx-cugraph/source/nx_cugraph/benchmarks.md deleted file mode 100644 index 31d5e5b09..000000000 --- a/docs/nx-cugraph/source/nx_cugraph/benchmarks.md +++ /dev/null @@ -1,28 +0,0 @@ -# Benchmarks - -## NetworkX vs. nx-cugraph -We ran several commonly used graph algorithms on both `networkx` and `nx-cugraph`. Here are the results - - -
- -![bench-image](../_static/bc_benchmark.png) - -
Results from running this Benchmark
-
- -## Reproducing Benchmarks - -Below are the steps to reproduce the results on your workstation. These are documented in this [README](https://github.com/rapidsai/cugraph/blob/HEAD/benchmarks/nx-cugraph/pytest-based). - -1. Clone the latest - -2. Follow the instructions to build an environment - -3. Activate the environment - -4. Install the latest `nx-cugraph` by following the [guide](installation.md) - -5. Follow the instructions written in the README here: `cugraph/benchmarks/nx-cugraph/pytest-based/` diff --git a/docs/nx-cugraph/source/nx_cugraph/faqs.md b/docs/nx-cugraph/source/nx_cugraph/faqs.md deleted file mode 100644 index dee943d19..000000000 --- a/docs/nx-cugraph/source/nx_cugraph/faqs.md +++ /dev/null @@ -1,5 +0,0 @@ -# FAQ - - > **1. Is `nx-cugraph` able to run across multiple GPUs?** - -nx-cugraph currently does not support multi-GPU. Multi-GPU support may be added to a future release of nx-cugraph, but consider [cugraph](https://docs.rapids.ai/api/cugraph/stable) for multi-GPU accelerated graph analytics in Python today. diff --git a/docs/nx-cugraph/source/nx_cugraph/how-it-works.md b/docs/nx-cugraph/source/nx_cugraph/how-it-works.md deleted file mode 100644 index f9dc5af67..000000000 --- a/docs/nx-cugraph/source/nx_cugraph/how-it-works.md +++ /dev/null @@ -1,114 +0,0 @@ -# How it Works - -NetworkX has the ability to **dispatch function calls to separately-installed third-party backends**. - -NetworkX backends let users experience improved performance and/or additional functionality without changing their NetworkX Python code. Examples include backends that provide algorithm acceleration using GPUs, parallel processing, graph database integration, and more. - -While NetworkX is a pure-Python implementation with minimal to no dependencies, backends may be written in other languages and require specialized hardware and/or OS support, additional software dependencies, or even separate services. Installation instructions vary based on the backend, and additional information can be found from the individual backend project pages listed in the NetworkX Backend Gallery. - - -![nxcg-execution-flow](../_static/nxcg-execution-diagram.jpg) - -## Enabling nx-cugraph - -NetworkX will use nx-cugraph as the graph analytics backend if any of the -following are used: - -### `NETWORKX_BACKEND_PRIORITY` environment variable. - -The `NETWORKX_BACKEND_PRIORITY` environment variable can be used to have NetworkX automatically dispatch to specified backends. This variable can be set to a single backend name, or a comma-separated list of backends ordered using the priority which NetworkX should try. If a NetworkX function is called that nx-cugraph supports, NetworkX will redirect the function call to nx-cugraph automatically, or fall back to the next backend in the list if provided, or run using the default NetworkX implementation. See [NetworkX Backends and Configs](https://networkx.org/documentation/stable/reference/backends.html). - -For example, this setting will have NetworkX use nx-cugraph for any function called by the script supported by nx-cugraph, and the default NetworkX implementation for all others. -``` -bash> NETWORKX_BACKEND_PRIORITY=cugraph python my_networkx_script.py -``` - -This example will have NetworkX use nx-cugraph for functions it supports, then try other_backend if nx-cugraph does not support them, and finally the default NetworkX implementation if not supported by either backend: -``` -bash> NETWORKX_BACKEND_PRIORITY="cugraph,other_backend" python my_networkx_script.py -``` - -### `backend=` keyword argument - -To explicitly specify a particular backend for an API, use the `backend=` -keyword argument. This argument takes precedence over the -`NETWORKX_BACKEND_PRIORITY` environment variable. This requires anyone -running code that uses the `backend=` keyword argument to have the specified -backend installed. - -Example: -```python -nx.betweenness_centrality(cit_patents_graph, k=k, backend="cugraph") -``` - -### Type-based dispatching - -NetworkX also supports automatically dispatching to backends associated with -specific graph types. Like the `backend=` keyword argument example above, this -requires the user to write code for a specific backend, and therefore requires -the backend to be installed, but has the advantage of ensuring a particular -behavior without the potential for runtime conversions. - -To use type-based dispatching with nx-cugraph, the user must import the backend -directly in their code to access the utilities provided to create a Graph -instance specifically for the nx-cugraph backend. - -Example: -```python -import networkx as nx -import nx_cugraph as nxcg - -G = nx.Graph() -... -nxcg_G = nxcg.from_networkx(G) # conversion happens once here -nx.betweenness_centrality(nxcg_G, k=1000) # nxcg Graph type causes cugraph backend - # to be used, no conversion necessary -``` - -## Command Line Example - ---- - -Create `bc_demo.ipy` and paste the code below. - -```python -import pandas as pd -import networkx as nx - -url = "https://data.rapids.ai/cugraph/datasets/cit-Patents.csv" -df = pd.read_csv(url, sep=" ", names=["src", "dst"], dtype="int32") -G = nx.from_pandas_edgelist(df, source="src", target="dst") - -%time result = nx.betweenness_centrality(G, k=10) -``` -Run the command: -``` -user@machine:/# ipython bc_demo.ipy -``` - -You will observe a run time of approximately 7 minutes...more or less depending on your CPU. - -Run the command again, this time specifying cugraph as the NetworkX backend. -``` -user@machine:/# NETWORKX_BACKEND_PRIORITY=cugraph ipython bc_demo.ipy -``` -This run will be much faster, typically around 20 seconds depending on your GPU. -``` -user@machine:/# NETWORKX_BACKEND_PRIORITY=cugraph ipython bc_demo.ipy -``` -There is also an option to cache the graph conversion to GPU. This can dramatically improve performance when running multiple algorithms on the same graph. Caching is enabled by default for NetworkX versions 3.4 and later, but if using an older version, set "NETWORKX_CACHE_CONVERTED_GRAPHS=True" -``` -NETWORKX_BACKEND_PRIORITY=cugraph NETWORKX_CACHE_CONVERTED_GRAPHS=True ipython bc_demo.ipy -``` - -When running Python interactively, the cugraph backend can be specified as an argument in the algorithm call. - -For example: -``` -nx.betweenness_centrality(cit_patents_graph, k=k, backend="cugraph") -``` - - -The latest list of algorithms supported by nx-cugraph can be found [here](https://github.com/rapidsai/cugraph/blob/HEAD/python/nx-cugraph/README.md#algorithms) or in the next section. - ---- diff --git a/docs/nx-cugraph/source/nx_cugraph/index.rst b/docs/nx-cugraph/source/nx_cugraph/index.rst deleted file mode 100644 index 110300c18..000000000 --- a/docs/nx-cugraph/source/nx_cugraph/index.rst +++ /dev/null @@ -1,48 +0,0 @@ -nx-cugraph ------------ - -nx-cugraph is a `NetworkX backend `_ that provides **GPU acceleration** to many popular NetworkX algorithms. - -By simply `installing and enabling nx-cugraph `_, users can see significant speedup on workflows where performance is hindered by the default NetworkX implementation. With ``nx-cugraph``, users can have GPU-based, large-scale performance **without** changing their familiar and easy-to-use NetworkX code. - -.. code-block:: python - - import pandas as pd - import networkx as nx - - url = "https://data.rapids.ai/cugraph/datasets/cit-Patents.csv" - df = pd.read_csv(url, sep=" ", names=["src", "dst"], dtype="int32") - G = nx.from_pandas_edgelist(df, source="src", target="dst") - - %time result = nx.betweenness_centrality(G, k=10) - -.. figure:: ../_static/colab.png - :width: 200px - :target: https://nvda.ws/4drM4re - - Try it on Google Colab! - - -+------------------------------------------------------------------------------------------------------------------------+ -| **Zero Code Change Acceleration** | -| | -| Just ``nx.config.backend_priority=["cugraph"]`` in Jupyter, or set ``NETWORKX_BACKEND_PRIORITY=cugraph`` in the shell. | -+------------------------------------------------------------------------------------------------------------------------+ -| **Run the same code on CPU or GPU** | -| | -| Nothing changes, not even your `import` statements, when going from CPU to GPU. | -+------------------------------------------------------------------------------------------------------------------------+ - - -``nx-cugraph`` is now Generally Available (GA) as part of the ``RAPIDS`` package. See `RAPIDS -Quick Start `_ to get up-and-running with ``nx-cugraph``. - -.. toctree:: - :maxdepth: 1 - :caption: Contents: - - how-it-works - supported-algorithms - installation - benchmarks - faqs diff --git a/docs/nx-cugraph/source/nx_cugraph/installation.md b/docs/nx-cugraph/source/nx_cugraph/installation.md deleted file mode 100644 index 5260b2282..000000000 --- a/docs/nx-cugraph/source/nx_cugraph/installation.md +++ /dev/null @@ -1,50 +0,0 @@ -# Getting Started - -This guide describes how to install ``nx-cugraph`` and use it in your workflows. - - -## System Requirements - -`nx-cugraph` requires the following: - - - **Volta architecture or later NVIDIA GPU, with [compute capability](https://developer.nvidia.com/cuda-gpus) 7.0+** - - **[CUDA](https://docs.nvidia.com/cuda/index.html) 11.2, 11.4, 11.5, 11.8, 12.0, 12.2, or 12.5** - - **Python >= 3.10** - - **[NetworkX](https://networkx.org/documentation/stable/install.html#) >= 3.2 (version 3.4 or higher recommended)** - -More details about system requirements can be found in the [RAPIDS System Requirements Documentation](https://docs.rapids.ai/install#system-req). - -## Installing nx-cugraph - -Read the [RAPIDS Quick Start Guide](https://docs.rapids.ai/install) to learn more about installing all RAPIDS libraries. - -`nx-cugraph` can be installed using conda or pip. It is included in the RAPIDS metapackage, or can be installed separately. - -### Conda -**Nightly version** -```bash -conda install -c rapidsai-nightly -c conda-forge -c nvidia nx-cugraph -``` - -**Stable version** -```bash -conda install -c rapidsai -c conda-forge -c nvidia nx-cugraph -``` - -### pip -**Nightly version** -```bash -pip install nx-cugraph-cu11 --extra-index-url https://pypi.anaconda.org/rapidsai-wheels-nightly/simple -``` - -**Stable version** -```bash -pip install nx-cugraph-cu11 --extra-index-url https://pypi.nvidia.com -``` - -
- -**Note:** - - The `pip install` examples above are for CUDA 11. To install for CUDA 12, replace `-cu11` with `-cu12` - -
diff --git a/docs/nx-cugraph/source/nx_cugraph/nx_cugraph.md b/docs/nx-cugraph/source/nx_cugraph/nx_cugraph.md deleted file mode 100644 index 900362a6e..000000000 --- a/docs/nx-cugraph/source/nx_cugraph/nx_cugraph.md +++ /dev/null @@ -1,16 +0,0 @@ -### nx_cugraph - - -`nx-cugraph` is a [networkX backend]() that accelerates many popular NetworkX functions using cuGraph and NVIDIA GPUs. -Users simply [install and enable nx-cugraph](installation.md) to experience GPU speedups. - -Lets look at some examples of algorithm speedups comparing CPU based NetworkX to dispatched versions run on GPU with nx_cugraph. - -![Ancestors](../images/ancestors.png) -![BFS Tree](../images/bfs_tree.png) -![Connected Components](../images/conn_component.png) -![Descendents](../images/descendents.png) -![Katz](../images/katz.png) -![Pagerank](../images/pagerank.png) -![Single Source Shortest Path](../images/sssp.png) -![Weakly Connected Components](../images/wcc.png) diff --git a/docs/nx-cugraph/source/nx_cugraph/supported-algorithms.rst b/docs/nx-cugraph/source/nx_cugraph/supported-algorithms.rst deleted file mode 100644 index b21ef7bb6..000000000 --- a/docs/nx-cugraph/source/nx_cugraph/supported-algorithms.rst +++ /dev/null @@ -1,354 +0,0 @@ -Supported Algorithms -===================== - -The nx-cugraph backend to NetworkX connects -`pylibcugraph <../../readme_pages/pylibcugraph.md>`_ (cuGraph's low-level Python -interface to its CUDA-based graph analytics library) and -`CuPy `_ (a GPU-accelerated array library) to NetworkX's -familiar and easy-to-use API. - -Below is the list of algorithms that are currently supported in nx-cugraph. - - -Algorithms ----------- - -+-----------------------------+ -| **Centrality** | -+=============================+ -| betweenness_centrality | -+-----------------------------+ -| edge_betweenness_centrality | -+-----------------------------+ -| degree_centrality | -+-----------------------------+ -| in_degree_centrality | -+-----------------------------+ -| out_degree_centrality | -+-----------------------------+ -| eigenvector_centrality | -+-----------------------------+ -| katz_centrality | -+-----------------------------+ - -+---------------------+ -| **Cluster** | -+=====================+ -| average_clustering | -+---------------------+ -| clustering | -+---------------------+ -| transitivity | -+---------------------+ -| triangles | -+---------------------+ - -+--------------------------+ -| **Community** | -+==========================+ -| louvain_communities | -+--------------------------+ - -+--------------------------+ -| **Bipartite** | -+==========================+ -| complete_bipartite_graph | -+--------------------------+ - -+------------------------------------+ -| **Components** | -+====================================+ -| connected_components | -+------------------------------------+ -| is_connected | -+------------------------------------+ -| node_connected_component | -+------------------------------------+ -| number_connected_components | -+------------------------------------+ -| weakly_connected | -+------------------------------------+ -| is_weakly_connected | -+------------------------------------+ -| number_weakly_connected_components | -+------------------------------------+ -| weakly_connected_components | -+------------------------------------+ - -+-------------+ -| **Core** | -+=============+ -| core_number | -+-------------+ -| k_truss | -+-------------+ - -+-------------+ -| **DAG** | -+=============+ -| ancestors | -+-------------+ -| descendants | -+-------------+ - -+--------------------+ -| **Isolate** | -+====================+ -| is_isolate | -+--------------------+ -| isolates | -+--------------------+ -| number_of_isolates | -+--------------------+ - -+-------------------+ -| **Link analysis** | -+===================+ -| hits | -+-------------------+ -| pagerank | -+-------------------+ - -+----------------+ -| **Operators** | -+================+ -| complement | -+----------------+ -| reverse | -+----------------+ - -+----------------------+ -| **Reciprocity** | -+======================+ -| overall_reciprocity | -+----------------------+ -| reciprocity | -+----------------------+ - -+---------------------------------------+ -| **Shortest Paths** | -+=======================================+ -| has_path | -+---------------------------------------+ -| shortest_path | -+---------------------------------------+ -| shortest_path_length | -+---------------------------------------+ -| all_pairs_shortest_path | -+---------------------------------------+ -| all_pairs_shortest_path_length | -+---------------------------------------+ -| bidirectional_shortest_path | -+---------------------------------------+ -| single_source_shortest_path | -+---------------------------------------+ -| single_source_shortest_path_length | -+---------------------------------------+ -| single_target_shortest_path | -+---------------------------------------+ -| single_target_shortest_path_length | -+---------------------------------------+ -| all_pairs_bellman_ford_path | -+---------------------------------------+ -| all_pairs_bellman_ford_path_length | -+---------------------------------------+ -| all_pairs_dijkstra | -+---------------------------------------+ -| all_pairs_dijkstra_path | -+---------------------------------------+ -| all_pairs_dijkstra_path_length | -+---------------------------------------+ -| bellman_ford_path | -+---------------------------------------+ -| bellman_ford_path_length | -+---------------------------------------+ -| dijkstra_path | -+---------------------------------------+ -| dijkstra_path_length | -+---------------------------------------+ -| single_source_bellman_ford | -+---------------------------------------+ -| single_source_bellman_ford_path | -+---------------------------------------+ -| single_source_bellman_ford_path_length| -+---------------------------------------+ -| single_source_dijkstra | -+---------------------------------------+ -| single_source_dijkstra_path | -+---------------------------------------+ -| single_source_dijkstra_path_length | -+---------------------------------------+ - -+---------------------------+ -| **Traversal** | -+===========================+ -| bfs_edges | -+---------------------------+ -| bfs_layers | -+---------------------------+ -| bfs_predecessors | -+---------------------------+ -| bfs_successors | -+---------------------------+ -| bfs_tree | -+---------------------------+ -| descendants_at_distance | -+---------------------------+ -| generic_bfs_edges | -+---------------------------+ - -+---------------------+ -| **Tree** | -+=====================+ -| is_arborescence | -+---------------------+ -| is_branching | -+---------------------+ -| is_forest | -+---------------------+ -| is_tree | -+---------------------+ - -Generators ------------- - -+-------------------------------+ -| **Classic** | -+===============================+ -| barbell_graph | -+-------------------------------+ -| circular_ladder_graph | -+-------------------------------+ -| complete_graph | -+-------------------------------+ -| complete_multipartite_graph | -+-------------------------------+ -| cycle_graph | -+-------------------------------+ -| empty_graph | -+-------------------------------+ -| ladder_graph | -+-------------------------------+ -| lollipop_graph | -+-------------------------------+ -| null_graph | -+-------------------------------+ -| path_graph | -+-------------------------------+ -| star_graph | -+-------------------------------+ -| tadpole_graph | -+-------------------------------+ -| trivial_graph | -+-------------------------------+ -| turan_graph | -+-------------------------------+ -| wheel_graph | -+-------------------------------+ - -+-----------------+ -| **Classic** | -+=================+ -| caveman_graph | -+-----------------+ - -+------------+ -| **Ego** | -+============+ -| ego_graph | -+------------+ - -+------------------------------+ -| **small** | -+==============================+ -| bull_graph | -+------------------------------+ -| chvatal_graph | -+------------------------------+ -| cubical_graph | -+------------------------------+ -| desargues_graph | -+------------------------------+ -| diamond_graph | -+------------------------------+ -| dodecahedral_graph | -+------------------------------+ -| frucht_graph | -+------------------------------+ -| heawood_graph | -+------------------------------+ -| house_graph | -+------------------------------+ -| house_x_graph | -+------------------------------+ -| icosahedral_graph | -+------------------------------+ -| krackhardt_kite_graph | -+------------------------------+ -| moebius_kantor_graph | -+------------------------------+ -| octahedral_graph | -+------------------------------+ -| pappus_graph | -+------------------------------+ -| petersen_graph | -+------------------------------+ -| sedgewick_maze_graph | -+------------------------------+ -| tetrahedral_graph | -+------------------------------+ -| truncated_cube_graph | -+------------------------------+ -| truncated_tetrahedron_graph | -+------------------------------+ -| tutte_graph | -+------------------------------+ - -+-------------------------------+ -| **Social** | -+===============================+ -| davis_southern_women_graph | -+-------------------------------+ -| florentine_families_graph | -+-------------------------------+ -| karate_club_graph | -+-------------------------------+ -| les_miserables_graph | -+-------------------------------+ - -Other -------- - -+-------------------------+ -| **Classes** | -+=========================+ -| is_negatively_weighted | -+-------------------------+ - -+----------------------+ -| **Convert** | -+======================+ -| from_dict_of_lists | -+----------------------+ -| to_dict_of_lists | -+----------------------+ - -+--------------------------+ -| **Convert Matrix** | -+==========================+ -| from_pandas_edgelist | -+--------------------------+ -| from_scipy_sparse_array | -+--------------------------+ - -+-----------------------------------+ -| **Relabel** | -+===================================+ -| convert_node_labels_to_integers | -+-----------------------------------+ -| relabel_nodes | -+-----------------------------------+ - - -To request nx-cugraph backend support for a NetworkX API that is not listed -above, visit the `cuGraph GitHub repo `_. diff --git a/docs/nx-cugraph/source/references/index.rst b/docs/nx-cugraph/source/references/index.rst deleted file mode 100644 index a8529246d..000000000 --- a/docs/nx-cugraph/source/references/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -========== -References -========== - - -.. toctree:: - :maxdepth: 3 - - licenses.md diff --git a/docs/nx-cugraph/source/references/licenses.md b/docs/nx-cugraph/source/references/licenses.md deleted file mode 100644 index b95905d9f..000000000 --- a/docs/nx-cugraph/source/references/licenses.md +++ /dev/null @@ -1,208 +0,0 @@ -# License - -Most of the Graph code is open-sourced and developed under the Apache 2.0 licnese. -The cugraph-ops code is closed sourced and developed under a NVIDIA copyright - - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018 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. diff --git a/docs/nx-cugraph/source/releases/index.rst b/docs/nx-cugraph/source/releases/index.rst deleted file mode 100644 index cbd22324b..000000000 --- a/docs/nx-cugraph/source/releases/index.rst +++ /dev/null @@ -1,5 +0,0 @@ -======== -Releases -======== - -https://github.com/rapidsai/cugraph/blob/main/CHANGELOG.md diff --git a/docs/nx-cugraph/source/sphinxext/github_link.py b/docs/nx-cugraph/source/sphinxext/github_link.py deleted file mode 100644 index b9101a851..000000000 --- a/docs/nx-cugraph/source/sphinxext/github_link.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright (c) 2019-2024, 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. - -# NOTE: -# This contains code with copyright by the scikit-learn project, subject to the -# license in /thirdparty/LICENSES/LICENSE.scikit_learn - -import inspect -import re -import subprocess -from functools import partial -from operator import attrgetter - -orig = inspect.isfunction - - -# See https://opendreamkit.org/2017/06/09/CythonSphinx/ -def isfunction(obj): - - orig_val = orig(obj) - - new_val = hasattr(type(obj), "__code__") - - if orig_val != new_val: - return new_val - - return orig_val - - -inspect.isfunction = isfunction - -REVISION_CMD = "git rev-parse --short HEAD" - -source_regex = re.compile(r"^File: (.*?) \(starting at line ([0-9]*?)\)$", re.MULTILINE) - - -def _get_git_revision(): - try: - revision = subprocess.check_output(REVISION_CMD.split()).strip() - except (subprocess.CalledProcessError, OSError): - print("Failed to execute git to get revision") - return None - return revision.decode("utf-8") - - -def _linkcode_resolve(domain, info, url_fmt, revision): - """Determine a link to online source for a class/method/function - - This is called by sphinx.ext.linkcode - - An example with a long-untouched module that everyone has - >>> _linkcode_resolve('py', {'module': 'tty', - ... 'fullname': 'setraw'}, - ... package='tty', - ... url_fmt='http://hg.python.org/cpython/file/' - ... '{revision}/Lib/{package}/{path}#L{lineno}', - ... revision='xxxx') - 'http://hg.python.org/cpython/file/xxxx/Lib/tty/tty.py#L18' - """ - if revision is None: - return - if domain != "py": - return - if not info.get("module") or not info.get("fullname"): - return - - class_name = info["fullname"].split(".")[0] - module = __import__(info["module"], fromlist=[class_name]) - obj = attrgetter(info["fullname"])(module) - - # Unwrap the object to get the correct source - # file in case that is wrapped by a decorator - obj = inspect.unwrap(obj) - - fn: str = None - lineno: str = None - - obj_module = inspect.getmodule(obj) - if not obj_module: - print(f"could not infer source code link for: {info}") - return - module_name = obj_module.__name__.split(".")[0] - - module_dir_dict = { - "cugraph_dgl": "cugraph-dgl", - "cugraph_pyg": "cugraph-pyg", - "cugraph_service_client": "cugraph-service/client", - "cugraph_service_server": "cugraph-service/server", - "cugraph": "cugraph", - "pylibcugraph": "pylibcugraph", - } - module_dir = module_dir_dict.get(module_name) - if not module_dir: - print(f"no source path directory set for {module_name}") - return - - obj_path = "/".join(obj_module.__name__.split(".")[1:]) - obj_file_ext = obj_module.__file__.split(".")[-1] - source_ext = "pyx" if obj_file_ext == "so" else "py" - fn = f"{module_dir}/{module_name}/{obj_path}.{source_ext}" - - # Get the line number if we need it. (Can work without it) - if lineno is None: - try: - lineno = inspect.getsourcelines(obj)[1] - except Exception: - - # Can happen if its a cyfunction. See if it has `__code__` - if hasattr(obj, "__code__"): - lineno = obj.__code__.co_firstlineno - else: - lineno = "" - return url_fmt.format(revision=revision, path=fn, lineno=lineno) - - -def make_linkcode_resolve(url_fmt): - """Returns a linkcode_resolve function for the given URL format - - revision is a git commit reference (hash or name) - - url_fmt is along the lines of ('https://github.com/USER/PROJECT/' - 'blob/{revision}/{package}/' - '{path}#L{lineno}') - """ - revision = _get_git_revision() - return partial(_linkcode_resolve, revision=revision, url_fmt=url_fmt) diff --git a/docs/nx-cugraph/source/top_toc.rst b/docs/nx-cugraph/source/top_toc.rst deleted file mode 100644 index 8e31e70ca..000000000 --- a/docs/nx-cugraph/source/top_toc.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. toctree:: - :maxdepth: 2 - :caption: cuGraph documentation Contents: - :name: top_toc - - basics/index - nx_cugraph/index - installation/index - tutorials/index - graph_support/index - wholegraph/index - references/index - api_docs/index diff --git a/nx_cugraph/algorithms/core.py b/nx_cugraph/algorithms/core.py index c56a679ea..1873f7606 100644 --- a/nx_cugraph/algorithms/core.py +++ b/nx_cugraph/algorithms/core.py @@ -43,10 +43,9 @@ def core_number(G): node_ids, core_numbers = plc.core_number( resource_handle=plc.ResourceHandle(), graph=G._get_plc_graph(), - degree_type="bidirectional", + degree_type="outgoing", do_expensive_check=False, ) - core_numbers = core_numbers // 2 # Added this in 24.12 (behavior changed) return G._nodearrays_to_dict(node_ids, core_numbers) diff --git a/nx_cugraph/classes/digraph.py b/nx_cugraph/classes/digraph.py index 178bf44f1..a73ca8d0b 100644 --- a/nx_cugraph/classes/digraph.py +++ b/nx_cugraph/classes/digraph.py @@ -34,6 +34,7 @@ __all__ = ["CudaDiGraph", "DiGraph"] networkx_api = nxcg.utils.decorators.networkx_class(nx.DiGraph) +gpu_cpu_api = nxcg.utils.decorators._gpu_cpu_api(nx.DiGraph, __name__) class DiGraph(nx.DiGraph, Graph): @@ -105,6 +106,43 @@ def to_cudagraph_class(cls) -> type[CudaDiGraph]: def to_networkx_class(cls) -> type[nx.DiGraph]: return nx.DiGraph + ########################## + # Networkx graph methods # + ########################## + + # Dispatch to nx.DiGraph or CudaDiGraph + __contains__ = gpu_cpu_api("__contains__") + __len__ = gpu_cpu_api("__len__") + __iter__ = gpu_cpu_api("__iter__") + + @networkx_api + def clear(self) -> None: + cudagraph = self._cudagraph if self._is_on_gpu else None + if self._is_on_cpu: + super().clear() + if cudagraph is not None: + cudagraph.clear() + self._set_cudagraph(cudagraph, clear_cpu=False) + + @networkx_api + def clear_edges(self) -> None: + cudagraph = self._cudagraph if self._is_on_gpu else None + if self._is_on_cpu: + super().clear_edges() + if cudagraph is not None: + cudagraph.clear_edges() + self._set_cudagraph(cudagraph, clear_cpu=False) + + get_edge_data = gpu_cpu_api("get_edge_data", edge_data=True) + has_edge = gpu_cpu_api("has_edge") + neighbors = gpu_cpu_api("neighbors") + has_node = gpu_cpu_api("has_node") + nbunch_iter = gpu_cpu_api("nbunch_iter") + number_of_edges = Graph.number_of_edges + number_of_nodes = gpu_cpu_api("number_of_nodes") + order = gpu_cpu_api("order") + successors = gpu_cpu_api("successors") + class CudaDiGraph(CudaGraph): ################# @@ -244,6 +282,7 @@ def to_undirected(self, reciprocal=False, as_view=False): rv.graph.update(deepcopy(self.graph)) return rv + successors = CudaGraph.neighbors # Alias # Many more methods to implement... ################### diff --git a/nx_cugraph/classes/graph.py b/nx_cugraph/classes/graph.py index 11c6215d8..018636228 100644 --- a/nx_cugraph/classes/graph.py +++ b/nx_cugraph/classes/graph.py @@ -48,6 +48,7 @@ __all__ = ["CudaGraph", "Graph"] networkx_api = nxcg.utils.decorators.networkx_class(nx.Graph) +gpu_cpu_api = nxcg.utils.decorators._gpu_cpu_api(nx.Graph, __name__) # The "everything" cache key is an internal implementation detail of NetworkX # that may change between releases. @@ -63,6 +64,8 @@ True, # Include all node values # `.graph` attributes are always included now ) +_EDGE_KEY_INDEX = 0 +_NODE_KEY_INDEX = 1 # Use to indicate when a full conversion to GPU failed so we don't try again. _CANT_CONVERT_TO_GPU = "_CANT_CONVERT_TO_GPU" @@ -210,8 +213,7 @@ def _cudagraph(self): cache[_CACHE_KEY] = Gcg return Gcg - @_cudagraph.setter - def _cudagraph(self, val, *, clear_cpu=True): + def _set_cudagraph(self, val, *, clear_cpu=True): """Set the full ``CudaGraph`` for this graph, or remove from device if None.""" if (cache := getattr(self, "__networkx_cache__", None)) is None: # Should we warn? @@ -228,6 +230,32 @@ def _cudagraph(self, val, *, clear_cpu=True): for key in self._nx_attrs: self.__dict__[key] = None + def _get_cudagraph(self, *, edge_data=False, node_data=False): + """Get a valid cached ``CudaGraph``, optionally with edge or node data. + + Returns None if no valid graph is found. + + Parameters + ---------- + edge_data : bool, default False + Whether to return a CudaGraph with edge data. + node_data : bool, default False + Whether to return a CudaGraph with node data. + """ + nx_cache = getattr(self, "__networkx_cache__", None) + if nx_cache is None or _CANT_CONVERT_TO_GPU in nx_cache: + return None + cache = nx_cache.get("backends", {}).get("cugraph", {}) + if _CACHE_KEY in cache: + # Always return the canonical CudaGraph if it exists + return cache[_CACHE_KEY] + for key, val in cache.items(): + if (key[_EDGE_KEY_INDEX] is True or edge_data is False) and ( + key[_NODE_KEY_INDEX] is True or node_data is False + ): + return val + return None + @nx.Graph.name.setter def name(self, s): # Don't clear the cache when setting the name, since `.graph` is shared. @@ -509,6 +537,54 @@ def from_dcsc( **attr, ) + ########################## + # Networkx graph methods # + ########################## + + # Dispatch to nx.Graph or CudaGraph + __contains__ = gpu_cpu_api("__contains__") + __len__ = gpu_cpu_api("__len__") + __iter__ = gpu_cpu_api("__iter__") + + @networkx_api + def clear(self) -> None: + cudagraph = self._cudagraph if self._is_on_gpu else None + if self._is_on_cpu: + super().clear() + if cudagraph is not None: + cudagraph.clear() + self._set_cudagraph(cudagraph, clear_cpu=False) + + @networkx_api + def clear_edges(self) -> None: + cudagraph = self._cudagraph if self._is_on_gpu else None + if self._is_on_cpu: + super().clear_edges() + if cudagraph is not None: + cudagraph.clear_edges() + self._set_cudagraph(cudagraph, clear_cpu=False) + + get_edge_data = gpu_cpu_api("get_edge_data", edge_data=True) + has_edge = gpu_cpu_api("has_edge") + neighbors = gpu_cpu_api("neighbors") + has_node = gpu_cpu_api("has_node") + nbunch_iter = gpu_cpu_api("nbunch_iter") + + @networkx_api + def number_of_edges( + self, u: NodeKey | None = None, v: NodeKey | None = None + ) -> int: + if u is not None or v is not None: + # NotImplemented by CudaGraph + nx_class = self.to_networkx_class() + return nx_class.number_of_edges(self, u, v) + return self._number_of_edges(u, v) + + _number_of_edges = gpu_cpu_api("number_of_edges") + number_of_nodes = gpu_cpu_api("number_of_nodes") + order = gpu_cpu_api("order") + # Future work: implement more graph methods, and handle e.g. `copy` + class CudaGraph: # Tell networkx to dispatch calls with this object to nx-cugraph @@ -803,7 +879,7 @@ def to_undirected(self, as_view: bool = False) -> CudaGraph: def _to_compat_graph(self) -> Graph: rv = self._to_compat_graph_class()() - rv._cudagraph = self + rv._set_cudagraph(self) return rv # Not implemented... diff --git a/nx_cugraph/classes/multidigraph.py b/nx_cugraph/classes/multidigraph.py index 5a6595567..0671d21a8 100644 --- a/nx_cugraph/classes/multidigraph.py +++ b/nx_cugraph/classes/multidigraph.py @@ -23,6 +23,7 @@ __all__ = ["CudaMultiDiGraph", "MultiDiGraph"] networkx_api = nxcg.utils.decorators.networkx_class(nx.MultiDiGraph) +gpu_cpu_api = nxcg.utils.decorators._gpu_cpu_api(nx.MultiDiGraph, __name__) class MultiDiGraph(nx.MultiDiGraph, MultiGraph, DiGraph): @@ -50,6 +51,26 @@ def to_cudagraph_class(cls) -> type[CudaMultiDiGraph]: def to_networkx_class(cls) -> type[nx.MultiDiGraph]: return nx.MultiDiGraph + ########################## + # Networkx graph methods # + ########################## + + # Dispatch to nx.MultiDiGraph or CudaMultiDiGraph + __contains__ = gpu_cpu_api("__contains__") + __len__ = gpu_cpu_api("__len__") + __iter__ = gpu_cpu_api("__iter__") + clear = DiGraph.clear + clear_edges = DiGraph.clear_edges + get_edge_data = gpu_cpu_api("get_edge_data", edge_data=True) + has_edge = gpu_cpu_api("has_edge") + neighbors = gpu_cpu_api("neighbors") + has_node = gpu_cpu_api("has_node") + nbunch_iter = gpu_cpu_api("nbunch_iter") + number_of_edges = MultiGraph.number_of_edges + number_of_nodes = gpu_cpu_api("number_of_nodes") + order = gpu_cpu_api("order") + successors = gpu_cpu_api("successors") + class CudaMultiDiGraph(CudaMultiGraph, CudaDiGraph): is_directed = classmethod(MultiDiGraph.is_directed.__func__) diff --git a/nx_cugraph/classes/multigraph.py b/nx_cugraph/classes/multigraph.py index c8c8f1dfb..3f0204f69 100644 --- a/nx_cugraph/classes/multigraph.py +++ b/nx_cugraph/classes/multigraph.py @@ -37,6 +37,7 @@ __all__ = ["MultiGraph", "CudaMultiGraph"] networkx_api = nxcg.utils.decorators.networkx_class(nx.MultiGraph) +gpu_cpu_api = nxcg.utils.decorators._gpu_cpu_api(nx.MultiGraph, __name__) class MultiGraph(nx.MultiGraph, Graph): @@ -277,6 +278,36 @@ def from_dcsc( **attr, ) + ########################## + # Networkx graph methods # + ########################## + + # Dispatch to nx.MultiGraph or CudaMultiGraph + __contains__ = gpu_cpu_api("__contains__") + __len__ = gpu_cpu_api("__len__") + __iter__ = gpu_cpu_api("__iter__") + clear = Graph.clear + clear_edges = Graph.clear_edges + get_edge_data = gpu_cpu_api("get_edge_data", edge_data=True) + has_edge = gpu_cpu_api("has_edge") + neighbors = gpu_cpu_api("neighbors") + has_node = gpu_cpu_api("has_node") + nbunch_iter = gpu_cpu_api("nbunch_iter") + + @networkx_api + def number_of_edges( + self, u: NodeKey | None = None, v: NodeKey | None = None + ) -> int: + if u is not None or v is not None: + # NotImplemented by CudaGraph + nx_class = self.to_networkx_class() + return nx_class.number_of_edges(self, u, v) + return self._number_of_edges(u, v) + + _number_of_edges = gpu_cpu_api("number_of_edges") + number_of_nodes = gpu_cpu_api("number_of_nodes") + order = gpu_cpu_api("order") + class CudaMultiGraph(CudaGraph): # networkx properties @@ -390,14 +421,13 @@ def get_edge_data( mask = (self.src_indices == u) & (self.dst_indices == v) if not mask.any(): return default - if self.edge_keys is None: + if self.edge_keys is None and key is not None: if self.edge_indices is None: self._calculate_edge_indices() - if key is not None: - try: - mask = mask & (self.edge_indices == key) - except TypeError: - return default + try: + mask = mask & (self.edge_indices == key) + except TypeError: + return default indices = cp.nonzero(mask)[0] if indices.size == 0: return default diff --git a/nx_cugraph/tests/test_graph_methods.py b/nx_cugraph/tests/test_graph_methods.py index 40a361b10..abc71ed77 100644 --- a/nx_cugraph/tests/test_graph_methods.py +++ b/nx_cugraph/tests/test_graph_methods.py @@ -17,6 +17,8 @@ from .testing_utils import assert_graphs_equal +CREATE_USING = [nxcg.Graph, nxcg.DiGraph, nxcg.MultiGraph, nxcg.MultiDiGraph] + def _create_Gs(): rv = [] @@ -65,3 +67,51 @@ def test_multidigraph_to_undirected(): Gcg = nxcg.CudaMultiDiGraph(Gnx) with pytest.raises(NotImplementedError): Gcg.to_undirected() + + +@pytest.mark.parametrize("create_using", CREATE_USING) +@pytest.mark.parametrize( + "method", + [ + ("__iter__", ()), + ("__len__", ()), + ("clear", ()), + ("clear_edges", ()), + ("nbunch_iter", ()), + ("number_of_edges", ()), + ("number_of_nodes", ()), + ("order", ()), + ("__contains__", (0,)), + ("neighbors", (0,)), + ("has_node", (0,)), + ("successors", (0,)), + ("get_edge_data", (0, 1)), + ("has_edge", (0, 1)), + ("nbunch_iter", ([0, 1],)), + ], +) +@pytest.mark.parametrize("where", ["gpu", "cpu"]) +def test_method_does_not_convert_to_cpu_or_gpu(create_using, method, where): + attr, args = method + if attr == "successors" and not create_using.is_directed(): + return + G = nxcg.complete_graph(3, create_using=create_using) + is_on_gpu = where == "gpu" + is_on_cpu = where == "cpu" + if is_on_cpu: + G.add_edge(10, 20) + assert G._is_on_gpu == is_on_gpu + assert G._is_on_cpu == is_on_cpu + getattr(G, attr)(*args) + assert G._is_on_gpu == is_on_gpu + assert G._is_on_cpu == is_on_cpu + # Also usable from the class and dispatches correctly + func = getattr(create_using, attr) + func(G, *args) + assert G._is_on_gpu == is_on_gpu + assert G._is_on_cpu == is_on_cpu + # Basic "looks like networkx" checks + nx_class = create_using.to_networkx_class() + nx_func = getattr(nx_class, attr) + assert func.__name__ == nx_func.__name__ + assert func.__module__.startswith("nx_cugraph") diff --git a/nx_cugraph/utils/decorators.py b/nx_cugraph/utils/decorators.py index 15cb010e9..26fce7350 100644 --- a/nx_cugraph/utils/decorators.py +++ b/nx_cugraph/utils/decorators.py @@ -167,3 +167,31 @@ def _default_should_run(*args, **kwargs): def _restore_networkx_dispatched(name): return getattr(BackendInterface, name) + + +def _gpu_cpu_api(nx_class, module_name): + def _gpu_cpu_graph_method(attr, *, edge_data=False, node_data=False): + """Dispatch property to NetworkX or CudaGraph based on cache. + + For example, this will use any cached CudaGraph for ``len(G)``, which + prevents creating NetworkX data structures. + """ + nx_func = getattr(nx_class, attr) + + def inner(self, *args, **kwargs): + cuda_graph = self._get_cudagraph(edge_data=edge_data, node_data=node_data) + if cuda_graph is None: + return nx_func(self, *args, **kwargs) + return getattr(cuda_graph, attr)(*args, **kwargs) + + inner.__name__ = nx_func.__name__ + inner.__doc__ = nx_func.__doc__ + inner.__qualname__ = nx_func.__qualname__ + inner.__defaults__ = nx_func.__defaults__ + inner.__kwdefaults__ = nx_func.__kwdefaults__ + inner.__module__ = module_name + inner.__dict__.update(nx_func.__dict__) + inner.__wrapped__ = nx_func + return inner + + return _gpu_cpu_graph_method