Skip to content
Merged
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
1 change: 0 additions & 1 deletion python/cuml/cuml/common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from cuml.internals.input_utils import (
input_to_cuml_array,
input_to_host_array,
input_to_host_array_with_sparse_support,
sparse_scipy_to_cp,
)
from cuml.internals.outputs import set_global_output_type, using_output_type
11 changes: 4 additions & 7 deletions python/cuml/cuml/common/array_descriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@

import cuml
from cuml.internals.array import CumlArray
from cuml.internals.input_utils import (
determine_array_type,
input_to_cuml_array,
)
from cuml.internals.outputs import infer_output_type


@dataclass
Expand Down Expand Up @@ -80,9 +77,9 @@ def _to_output(self, instance, to_output_type, to_output_dtype=None):

# If the input type was anything but CumlArray, need to create one now
if "cuml" not in existing.values:
existing.values["cuml"] = input_to_cuml_array(
existing.values["cuml"] = CumlArray.from_input(
existing.get_input_value(), order="K"
).array
)

cuml_arr: CumlArray = existing.values["cuml"]

Expand Down Expand Up @@ -128,7 +125,7 @@ def __set__(self, instance, value):
existing = self._get_meta(instance)

# Determine the type
existing.input_type = determine_array_type(value)
existing.input_type = infer_output_type(value, array_like=None)

# Clear any existing values
existing.values.clear()
Expand Down
7 changes: 3 additions & 4 deletions python/cuml/cuml/internals/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@
import cuml
import cuml.common
import cuml.internals
import cuml.internals.input_utils
import cuml.internals.logger as logger
import cuml.internals.nvtx as nvtx
from cuml.internals.input_utils import determine_array_type
from cuml.internals.mixins import TagsMixin
from cuml.internals.outputs import infer_output_type

_THREAD_STATE = threading.local()

Expand Down Expand Up @@ -192,7 +191,7 @@ def set_params(self, **params):
return self

def _set_output_type(self, inp):
self._input_type = determine_array_type(inp)
self._input_type = infer_output_type(inp)

def _get_output_type(self, inp=None):
"""
Expand All @@ -214,7 +213,7 @@ class output type and global output type.
output_type = self._input_type
else:
# Determine the output from the input
output_type = determine_array_type(inp)
output_type = infer_output_type(inp)

return output_type

Expand Down
193 changes: 0 additions & 193 deletions python/cuml/cuml/internals/input_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION.
# SPDX-License-Identifier: Apache-2.0
#

from collections import namedtuple

import cudf
Expand All @@ -18,160 +17,12 @@
import cuml.internals.nvtx as nvtx
from cuml.internals.array import CumlArray
from cuml.internals.array_sparse import SparseCumlArray
from cuml.internals.global_settings import GlobalSettings
from cuml.internals.mem_type import MemoryType

global_settings = GlobalSettings()
PANDAS_VERSION = Version(pd.__version__)

cuml_array = namedtuple("cuml_array", "array n_rows n_cols dtype")

_input_type_to_str = {
CumlArray: "cuml",
SparseCumlArray: "cuml",
np.ndarray: "numpy",
pd.Series: "pandas",
pd.DataFrame: "pandas",
pd.Index: "pandas",
cp.ndarray: "cupy",
cudf.Series: "cudf",
cudf.DataFrame: "cudf",
cudf.Index: "cudf",
numba_cuda.devicearray.DeviceNDArrayBase: "numba",
cupyx.scipy.sparse.spmatrix: "cupy",
scipy.sparse.spmatrix: "numpy",
scipy.sparse.sparray: "numpy",
}

_input_type_to_mem_type = {
np.ndarray: MemoryType.host,
pd.Series: MemoryType.host,
pd.DataFrame: MemoryType.host,
scipy.sparse.spmatrix: MemoryType.host,
scipy.sparse.sparray: MemoryType.host,
cp.ndarray: MemoryType.device,
cudf.Series: MemoryType.device,
cudf.DataFrame: MemoryType.device,
numba_cuda.devicearray.DeviceNDArrayBase: MemoryType.device,
cupyx.scipy.sparse.spmatrix: MemoryType.device,
}

_SPARSE_TYPES = [
SparseCumlArray,
cupyx.scipy.sparse.spmatrix,
scipy.sparse.spmatrix,
scipy.sparse.sparray,
]


def get_supported_input_type(X):
"""
Determines if the input object is a supported input array-like object or
not. If supported, the type is returned. Otherwise, `None` is returned.

Parameters
----------
X : object
Input object to test

Notes
-----
To closely match the functionality of
:func:`~cuml.internals.input_utils.input_to_cuml_array`, this method will
return `cupy.ndarray` for any object supporting
`__cuda_array_interface__` and `numpy.ndarray` for any object supporting
`__array_interface__`.

Returns
-------
array-like type or None
If the array-like object is supported, the type is returned.
Otherwise, `None` is returned.
"""
# Check CumlArray first to shorten search time
if isinstance(X, CumlArray):
return CumlArray

if isinstance(X, SparseCumlArray):
return SparseCumlArray

if isinstance(X, cudf.Series):
if X.null_count != 0:
return None
else:
return cudf.Series

if isinstance(X, pd.DataFrame):
return pd.DataFrame

if isinstance(X, pd.Series):
return pd.Series

if isinstance(X, pd.Index):
return pd.Index

if isinstance(X, cudf.DataFrame):
return cudf.DataFrame

if isinstance(X, cudf.Index):
return cudf.Index

# A cudf.pandas wrapped Numpy array defines `__cuda_array_interface__`
# which means without this we'd always return a cupy array. We don't want
# to match wrapped cupy arrays, they get dealt with later
if getattr(X, "_fsproxy_slow_type", None) is np.ndarray:
return np.ndarray

if numba_cuda.devicearray.is_cuda_ndarray(X):
return numba_cuda.devicearray.DeviceNDArrayBase

if hasattr(X, "__cuda_array_interface__"):
return cp.ndarray

if hasattr(X, "__array_interface__"):
# For some reason, numpy scalar types also implement
# `__array_interface__`. See numpy.generic.__doc__. Exclude those types
# as well as np.dtypes
if not isinstance(X, np.generic) and not isinstance(X, type):
return np.ndarray

if cupyx.scipy.sparse.issparse(X):
return cupyx.scipy.sparse.spmatrix

if scipy.sparse.isspmatrix(X):
return scipy.sparse.spmatrix

if scipy.sparse.issparse(X) and X.ndim == 2:
return scipy.sparse.sparray

# Return None if this type is not supported
return None


def determine_array_type(X):
if X is None:
return None

# Get the generic type
gen_type = get_supported_input_type(X)

return _input_type_to_str.get(gen_type, None)


def determine_df_obj_type(X):
if X is None:
return None

# Get the generic type
gen_type = get_supported_input_type(X)

if gen_type in (cudf.DataFrame, pd.DataFrame):
return "dataframe"
elif gen_type in (cudf.Series, pd.Series):
return "series"

return None


def determine_array_dtype(X):
if X is None:
Expand All @@ -194,32 +45,6 @@ def determine_array_dtype(X):
return dtype


def determine_array_type_full(X):
"""
Returns a tuple of the array type, and a boolean if it is sparse

Parameters
----------
X : array-like
Input array to test

Returns
-------
(string, bool) Returns a tuple of the array type string and a boolean if it
is a sparse array.
"""
if X is None:
return None, None

# Get the generic type
gen_type = get_supported_input_type(X)

if gen_type is None:
return None, None

return _input_type_to_str[gen_type], gen_type in _SPARSE_TYPES


def is_array_like(X, accept_lists=False):
"""Check if X is array-like.

Expand Down Expand Up @@ -473,24 +298,6 @@ def input_to_host_array(
return out_data._replace(array=out_data.array.to_output("numpy"))


def input_to_host_array_with_sparse_support(X):
if X is None:
return None
if scipy.sparse.issparse(X):
return X
_array_type, is_sparse = determine_array_type_full(X)
if is_sparse:
if _array_type == "cupy":
return SparseCumlArray(X).to_output(output_type="scipy")
elif _array_type == "cuml":
return X.to_output(output_type="scipy")
elif _array_type == "numpy":
return X
else:
raise ValueError(f"Unsupported sparse array type: {_array_type}.")
return input_to_host_array(X).array


def convert_dtype(X, to_dtype=np.float32, legacy=True, safe_dtype=True):
"""
Convert X to be of dtype `dtype`, raising a TypeError
Expand Down
Loading
Loading