Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates nx-cugraph README for latest h/w, CUDA, python, NX requirements, moves updater to pre-commit #4225

Merged
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 20 additions & 0 deletions .pre-commit-config.yaml
Expand Up @@ -63,3 +63,23 @@ repos:
[.]flake8[.]cython$|
meta[.]yaml$|
setup[.]cfg$
- repo: local
hooks:
- id: nx-cugraph-meta-data-update
name: nx-cugraph meta-data updater
entry: bash -c "PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/_nx_cugraph/__init__.py"
files: ^python/nx-cugraph/
types: [python]
language: python
pass_filenames: false
additional_dependencies: ["networkx>=3.2"]
- repo: local
hooks:
- id: nx-cugraph-readme-update
name: nx-cugraph README updater
entry: bash -c "PYTHONPATH=./python/nx-cugraph python ./python/nx-cugraph/scripts/update_readme.py ./python/nx-cugraph/README.md"
files: ^python/nx-cugraph/
types_or: [python, markdown]
language: python
pass_filenames: false
additional_dependencies: ["networkx>=3.2"]
7 changes: 0 additions & 7 deletions ci/test_python.sh
Expand Up @@ -127,13 +127,6 @@ python -m nx_cugraph.scripts.print_tree --dispatch-name --plc --incomplete --dif
python -m nx_cugraph.scripts.print_table
popd

rapids-logger "ensure nx-cugraph autogenerated files are up to date"
pushd python/nx-cugraph
make || true
git diff --exit-code .
git checkout .
popd

rlratzel marked this conversation as resolved.
Show resolved Hide resolved
rapids-logger "pytest cugraph-service (single GPU)"
./ci/run_cugraph_service_pytests.sh \
--verbose \
Expand Down
20 changes: 14 additions & 6 deletions python/nx-cugraph/README.md
Expand Up @@ -7,11 +7,10 @@ to run supported algorithms with GPU acceleration.
## System Requirements

nx-cugraph requires the following:

* NVIDIA GPU, Pascal architecture or later
* NVIDIA GPU, Volta architecture or later, with [compute capability](https://developer.nvidia.com/cuda-gpus) 7.0+
* CUDA 11.2, 11.4, 11.5, 11.8, or 12.0
* Python versions 3.9, 3.10, or 3.11
* NetworkX >= version 3.2
* Python version 3.9, 3.10, or 3.11
* NetworkX >= version 3.0 (version 3.2 or higher recommended)

More details about system requirements can be found in the [RAPIDS System Requirements documentation](https://docs.rapids.ai/install#system-req).

Expand All @@ -20,16 +19,25 @@ More details about system requirements can be found in the [RAPIDS System Requir
nx-cugraph can be installed using either conda or pip.

### conda
#### latest nightly version
```
conda install -c rapidsai-nightly -c conda-forge -c nvidia nx-cugraph
```
#### latest stable version
```
conda install -c rapidsai -c conda-forge -c nvidia nx-cugraph
```
### pip
#### latest nightly version
```
python -m pip install nx-cugraph-cu11 --extra-index-url https://pypi.anaconda.org/rapidsai-wheels-nightly/simple
```
#### latest stable version
```
python -m pip install nx-cugraph-cu11 --extra-index-url https://pypi.nvidia.com
```
Notes:

* Nightly wheel builds will not be available until the 23.12 release, therefore the index URL for the stable release version is being used in the pip install command above.
* The pip example above installs for CUDA 11. To install for CUDA 12, replace `-cu11` with `-cu12`
* Additional information relevant to installing any RAPIDS package can be found [here](https://rapids.ai/#quick-start).

## Enabling nx-cugraph
Expand Down
16 changes: 16 additions & 0 deletions python/nx-cugraph/_nx_cugraph/__init__.py
Expand Up @@ -208,6 +208,22 @@ def get_info():
if __name__ == "__main__":
from pathlib import Path

# This script imports nx_cugraph modules, which imports nx_cugraph runtime
# dependencies. The modules do not need the runtime deps, so stub them out
# to avoid installing them.
class Stub:
def __getattr__(self, *args, **kwargs):
return Stub()

def __call__(self, *args, **kwargs):
return Stub()

import sys

sys.modules["cupy"] = Stub()
sys.modules["numpy"] = Stub()
sys.modules["pylibcugraph"] = Stub()

from _nx_cugraph.core import main

filepath = Path(__file__)
Expand Down
19 changes: 14 additions & 5 deletions python/nx-cugraph/_nx_cugraph/core.py
Expand Up @@ -45,18 +45,27 @@ def update_text(text, lines_to_add, target, indent=" " * 8):
return f"{text[:start]}{begin}{to_add}\n{indent}{text[stop:]}"


def dq_repr(s):
"""Return repr(s) quoted with the double quote preference used by black."""
rs = repr(s)
if rs.startswith("'") and '"' not in rs:
rs = rs.strip("'").replace('"', '\\"')
rlratzel marked this conversation as resolved.
Show resolved Hide resolved
return f'"{rs}"'
return rs


def dict_to_lines(d, *, indent=""):
for key in sorted(d):
val = d[key]
if "\n" not in val:
yield f"{indent}{key!r}: {val!r},"
yield f"{indent}{dq_repr(key)}: {dq_repr(val)},"
else:
yield f"{indent}{key!r}: ("
yield f"{indent}{dq_repr(key)}: ("
*lines, last_line = val.split("\n")
for line in lines:
line += "\n"
yield f" {indent}{line!r}"
yield f" {indent}{last_line!r}"
yield f" {indent}{dq_repr(line)}"
yield f" {indent}{dq_repr(last_line)}"
yield f"{indent}),"


Expand All @@ -83,7 +92,7 @@ def main(filepath):
to_add = []
for name in sorted(additional_parameters):
params = additional_parameters[name]
to_add.append(f"{name!r}: {{")
to_add.append(f"{dq_repr(name)}: {{")
to_add.extend(dict_to_lines(params, indent=" " * 4))
to_add.append("},")
text = update_text(text, to_add, "additional_parameters")
Expand Down
57 changes: 52 additions & 5 deletions python/nx-cugraph/scripts/update_readme.py
@@ -1,4 +1,3 @@
#!/usr/bin/env python
# Copyright (c) 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.
Expand All @@ -13,12 +12,13 @@
# limitations under the License.
import argparse
import re
import urllib.request
import zlib
from collections import namedtuple
from pathlib import Path
from warnings import warn

from nx_cugraph.scripts.print_tree import create_tree, tree_lines
_objs_file_url = "https://networkx.org/documentation/stable/objects.inv"

# See: https://sphobjinv.readthedocs.io/en/stable/syntax.html
DocObject = namedtuple(
Expand Down Expand Up @@ -75,6 +75,8 @@ def replace_body(text, match, new_body):

def main(readme_file, objects_filename):
"""``readme_file`` must be readable and writable, so use mode ``"a+"``"""
from nx_cugraph.scripts.print_tree import create_tree, tree_lines

# Use the `objects.inv` file to determine URLs. For details about this file, see:
# https://sphobjinv.readthedocs.io/en/stable/syntax.html
# We might be better off using a library like that, but roll our own for now.
Expand Down Expand Up @@ -190,14 +192,59 @@ def get_payload_internal(keys):
return text


def find_or_download_objs_file(objs_file_dir):
"""
Returns the path to <objs_file_dir>/objects.inv, downloading it from
_objs_file_url if it does not already exist.
"""
objs_file_path = objs_file_dir / "objects.inv"
if not objs_file_path.exists():
request = urllib.request.Request(_objs_file_url)
with (
urllib.request.urlopen(request) as response,
Path(objs_file_path).open("wb") as out,
):
out.write(response.read())
return objs_file_path


if __name__ == "__main__":
# This script imports a nx_cugraph script module, which imports nx_cugraph
# runtime dependencies. The script module does not need the runtime deps,
# so stub them out to avoid installing them.
class Stub:
def __getattr__(self, *args, **kwargs):
return Stub()

def __call__(self, *args, **kwargs):
return Stub()

import sys

sys.modules["cupy"] = Stub()
sys.modules["numpy"] = Stub()
sys.modules["pylibcugraph"] = Stub()

parser = argparse.ArgumentParser(
"Update README.md to show NetworkX functions implemented by nx-cugraph"
)
parser.add_argument("readme_filename", help="Path to the README.md file")
parser.add_argument(
"networkx_objects", help="Path to the objects.inv file from networkx docs"
"networkx_objects",
nargs="?",
default=None,
help="Optional path to the objects.inv file from the NetworkX docs. Default is "
"the objects.inv file in the directory containing the specified README.md. If "
"an objects.inv file does not exist in that location, one will be downloaded "
"and saved to that location.",
)
args = parser.parse_args()
with Path(args.readme_filename).open("a+") as readme_file:
main(readme_file, args.networkx_objects)

readme_filename = args.readme_filename
readme_path = Path(readme_filename)
objects_filename = args.networkx_objects
if objects_filename is None:
objects_filename = find_or_download_objs_file(readme_path.parent)

with readme_path.open("a+") as readme_file:
main(readme_file, objects_filename)