Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion docs/source/gfql/standard_algorithms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Algorithms and options
in each component.
* - ``pagerank``
- ``pagerank``
- cuGraph-compatible controls plus ``weight``, ``chunks``, ``stopping``
- cuGraph controls plus ``weight``, ``method``, ``chunks``, ``stopping``
- Directed, optionally weighted PageRank. Convergence is the default;
fixed-iteration execution is explicit.
* - ``cdlp``
Expand Down Expand Up @@ -101,6 +101,14 @@ Pass ``weight`` as an edge-column name. When omitted, the graph's bound edge
weight is used; without either, every edge has weight 1. ``chunks`` controls
dataframe chunking without changing the result.

``method='auto'`` is the default. With ``chunks=1``, it uses a conservative
preflight estimate and selects the backend-native NumPy or CuPy fast path only
when its estimated peak scratch is at most half the detected free host/device
memory. Unknown or tighter memory falls back to the dataframe path. Explicit
``method='fast'`` bypasses the estimate and requires ``chunks=1``. Set
``method='bounded'`` with ``chunks>1`` for the strongest explicit peak-memory
control; setting ``chunks`` above one also makes ``auto`` select ``bounded``.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought should be clear that the main value of this implementation is lower memory consumption for handling bigger graphs on smaller GPUs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise, typically better to use the GPU or CPU ones when fit in memory

By default PageRank raises when ``max_iter`` is exhausted. Set
``fail_on_nonconvergence: false`` to keep the last iterate. The Graphistry extra
``converged_col`` then writes the solver status as a boolean node column:
Expand Down
42 changes: 40 additions & 2 deletions graphistry/compute/algorithms/_dfops.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
from __future__ import annotations

from types import ModuleType
from typing import Iterator, Mapping, Optional, Sequence, SupportsInt, Tuple
from typing import Iterator, Mapping, Optional, Sequence, SupportsFloat, SupportsInt, Tuple

import pandas as pd

from graphistry.compute.typing import DataFrameT, SeriesT
from graphistry.compute.typing import ArrayLike, ArrayNamespace, DataFrameT, SeriesT

# 2**32, as a plain Python int. Used for bit-packing via arithmetic.
SHIFT32 = 1 << 32
Expand All @@ -37,6 +37,44 @@ def is_cudf(obj: object) -> bool:
return type(obj).__module__.split(".")[0] == "cudf"


def array_namespace(template: object) -> ArrayNamespace:
"""NumPy or CuPy for the dataframe or Series engine holding the template."""
if is_cudf(template):
import cupy

return cupy
import numpy

return numpy # type: ignore[return-value]


def series_to_array(series: SeriesT) -> ArrayLike:
"""A host or device array view of a dense positional Series."""
if is_cudf(series):
return series.values
return series.to_numpy()


def series_from_array(template: object, values: ArrayLike) -> SeriesT:
"""Build a default-index Series on the same engine as the template."""
if is_cudf(template):
import cudf

return cudf.Series(values)
return pd.Series(values)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Send most of these live in our SeriesT / DataframeT cross platform files ?



def to_host_floats(values: Sequence[SupportsFloat]) -> tuple[float, ...]:
"""Transfer several backend scalars together, requiring one GPU sync."""
if not values:
return ()
if type(values[0]).__module__.split(".")[0] == "cupy":
import cupy

return tuple(float(value) for value in cupy.asnumpy(cupy.stack(values)))
return tuple(float(value) for value in values)


def _mod(frame: DataFrameT) -> ModuleType:
"""The dataframe module that produced `frame` (pandas or cudf)."""
if is_cudf(frame):
Expand Down
Loading
Loading