Skip to content

Commit 31a814e

Browse files
authored
Complete dpctl tensor removal (#3091)
* Complete dpctl tensor removal * minor follow-up * address remaining dpctl tensor mentions * follow up from rebase
1 parent ca32cbb commit 31a814e

42 files changed

Lines changed: 135 additions & 249 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

onedal/_device_offload.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from sklearn import get_config
2424

2525
from ._config import _get_config
26-
from .datatypes import copy_to_dpnp, copy_to_usm, dlpack_to_numpy
26+
from .datatypes import copy_to_dpnp, dlpack_to_numpy
2727
from .utils import _sycl_queue_manager as QM
2828
from .utils._array_api import _asarray, _get_sycl_namespace, _is_numpy_namespace
2929
from .utils._third_party import is_dpnp_ndarray
@@ -159,11 +159,7 @@ def wrapper_impl(*args, **kwargs):
159159
result = invoke_func(self, *hostargs, **hostkwargs)
160160

161161
if queue and hasattr(data, "__sycl_usm_array_interface__"):
162-
return (
163-
copy_to_dpnp(queue, result)
164-
if is_dpnp_ndarray(data)
165-
else copy_to_usm(queue, result)
166-
)
162+
return copy_to_dpnp(queue, result)
167163

168164
if get_config().get("transform_output") in ("default", None):
169165
input_array_api = getattr(data, "__array_namespace__", lambda: None)()

onedal/datatypes/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616

1717
from ._data_conversion import from_table, return_type_constructor, to_table
1818
from ._dlpack import dlpack_to_numpy, get_torch_queue
19-
from ._sycl_usm import copy_to_dpnp, copy_to_usm
19+
from ._sycl_usm import copy_to_dpnp
2020

2121
__all__ = [
2222
"copy_to_dpnp",
23-
"copy_to_usm",
2423
"dlpack_to_numpy",
2524
"from_table",
2625
"get_torch_queue",

onedal/datatypes/_data_conversion.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,12 @@
1414
# limitations under the License.
1515
# ==============================================================================
1616

17-
import warnings
18-
1917
import numpy as np
2018
import scipy.sparse as sp
2119

2220
from onedal import _default_backend as backend
2321

24-
from ..utils._third_party import is_dpctl_tensor, is_dpnp_ndarray, lazy_import
22+
from ..utils._third_party import is_dpnp_ndarray, lazy_import
2523

2624

2725
def _apply_and_pass(func, *args, **kwargs):
@@ -116,19 +114,7 @@ def return_type_constructor(array):
116114
xp = array.__array_namespace__()
117115
# array api support added in dpnp starting in 0.19, will fail for
118116
# older versions
119-
if is_dpctl_tensor(array):
120-
warnings.warn(
121-
"dpctl tensors are deprecated and support for them in "
122-
"scikit-learn-intelex will be removed in 2026.0.0. "
123-
"Consider using dpnp arrays instead.",
124-
FutureWarning,
125-
)
126-
func = lambda x: (
127-
xp.asarray(x)
128-
if hasattr(x, "__sycl_usm_array_interface__")
129-
else xp.asarray(backend.from_table(x), device=device)
130-
)
131-
elif is_dpnp_ndarray(array):
117+
if is_dpnp_ndarray(array):
132118
func = lambda x: (
133119
xp.asarray(xp.as_usm_ndarray(x))
134120
if hasattr(x, "__sycl_usm_array_interface__")
@@ -152,8 +138,8 @@ def return_type_constructor(array):
152138
def from_table(*args, like=None):
153139
"""Create 2 dimensional arrays from oneDAL tables.
154140
155-
oneDAL tables are converted to numpy ndarrays, dpctl tensors, dpnp
156-
ndarrays, or array API standard arrays of designated type.
141+
oneDAL tables are converted to numpy ndarrays, dpnp ndarrays,
142+
or array API standard arrays of designated type.
157143
158144
Parameters
159145
----------

onedal/datatypes/_dlpack.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def dlpack_to_numpy(obj):
4545
# convert to numpy
4646
try:
4747
# Some frameworks implement an __array__ method just to
48-
# throw a RuntimeError when used (array_api_strict, dpctl),
48+
# throw a RuntimeError when used (array_api_strict),
4949
# or a TypeError (array_api-strict) rather than an AttributeError
5050
# therefore a try catch is necessary (logic is essentially a
5151
# getattr call + some)

onedal/datatypes/_sycl_usm.py

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,22 @@
2222
from ..utils._third_party import lazy_import
2323

2424

25-
@lazy_import("dpctl.memory", "dpctl.tensor")
26-
def _array_to_usm(memory, tensor, queue, array):
25+
@lazy_import("dpnp")
26+
def _to_dpnp(dpnp, queue, array):
2727
try:
28-
mem = memory.MemoryUSMDevice(array.nbytes, queue=queue)
29-
mem.copy_from_host(array.tobytes())
30-
return tensor.usm_ndarray(array.shape, array.dtype, buffer=mem)
28+
return dpnp.asarray(array, usm_type="device", sycl_queue=queue)
3129
except ValueError as e:
3230
# ValueError will raise if device does not support the dtype
3331
# retry with float32 (needed for fp16 and fp64 support issues)
3432
# try again as float32, if it is a float32 just raise the error.
3533
if array.dtype == np.float32:
3634
raise e
37-
return _array_to_usm(queue, array.astype(np.float32))
38-
39-
40-
@lazy_import("dpnp", "dpctl.tensor")
41-
def _to_dpnp(dpnp, tensor, array):
42-
if isinstance(array, tensor.usm_ndarray):
43-
return dpnp.array(array, copy=False)
44-
else:
45-
return array
46-
47-
48-
def copy_to_usm(queue, array):
49-
if hasattr(array, "tobytes"):
50-
return _array_to_usm(queue, array)
51-
else:
52-
if isinstance(array, Iterable) and not sp.issparse(array):
53-
array = [copy_to_usm(queue, i) for i in array]
54-
return array
35+
return _to_dpnp(queue, array.astype(np.float32))
5536

5637

5738
def copy_to_dpnp(queue, array):
5839
if hasattr(array, "tobytes"):
59-
return _to_dpnp(_array_to_usm(queue, array))
40+
return _to_dpnp(queue, array)
6041
else:
6142
if isinstance(array, Iterable) and not sp.issparse(array):
6243
array = [copy_to_dpnp(queue, i) for i in array]

onedal/datatypes/tests/common.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
if dpctl_available:
2828
import dpctl
29-
from dpctl.tensor import usm_ndarray
3029

3130
def _get_sycl_queue(syclobj):
3231
if hasattr(syclobj, "_get_capsule"):
@@ -35,22 +34,12 @@ def _get_sycl_queue(syclobj):
3534
return dpctl.SyclQueue(syclobj)
3635

3736
def _assert_tensor_attr(actual, desired, order):
38-
"""Check attributes of two given USM tensors."""
39-
is_usm_tensor = (
40-
lambda x: dpnp_available
41-
and isinstance(x, dpnp.ndarray)
42-
or isinstance(x, usm_ndarray)
43-
)
44-
assert is_usm_tensor(actual)
45-
assert is_usm_tensor(desired)
46-
# dpctl.tensor is the dpnp.ndarrays's core tensor structure along
47-
# with advanced device management. Convert dpnp to dpctl.tensor with zero copy.
48-
get_tensor = lambda x: (
49-
x.get_array() if dpnp_available and isinstance(x, dpnp.ndarray) else x
50-
)
51-
# Now DPCtl tensors
52-
actual = get_tensor(actual)
53-
desired = get_tensor(desired)
37+
"""Check attributes of two given USM arrays."""
38+
assert dpnp_available and isinstance(actual, dpnp.ndarray)
39+
assert dpnp_available and isinstance(desired, dpnp.ndarray)
40+
# Convert dpnp to underlying usm_ndarray with zero copy.
41+
actual = actual.get_array()
42+
desired = desired.get_array()
5443

5544
assert actual.shape == desired.shape
5645
assert actual.strides == desired.strides

onedal/datatypes/tests/test_data.py

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,7 @@ def test_conversion_to_table(dtype):
246246
not backend.is_dpc,
247247
reason="__sycl_usm_array_interface__ support requires DPC backend.",
248248
)
249-
@pytest.mark.parametrize(
250-
"dataframe,queue", get_dataframes_and_queues("dpctl,dpnp", "cpu,gpu")
251-
)
249+
@pytest.mark.parametrize("dataframe,queue", get_dataframes_and_queues("dpnp", "cpu,gpu"))
252250
@pytest.mark.parametrize("order", ["C", "F"])
253251
@pytest.mark.parametrize("dtype", [np.float32, np.float64, np.int32, np.int64])
254252
def test_input_zero_copy_sycl_usm(dataframe, queue, order, dtype):
@@ -280,9 +278,7 @@ def test_input_zero_copy_sycl_usm(dataframe, queue, order, dtype):
280278
not backend.is_dpc,
281279
reason="__sycl_usm_array_interface__ support requires DPC backend.",
282280
)
283-
@pytest.mark.parametrize(
284-
"dataframe,queue", get_dataframes_and_queues("dpctl,dpnp", "cpu,gpu")
285-
)
281+
@pytest.mark.parametrize("dataframe,queue", get_dataframes_and_queues("dpnp", "cpu,gpu"))
286282
@pytest.mark.parametrize("order", ["F", "C"])
287283
@pytest.mark.parametrize("data_shape", data_shapes)
288284
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
@@ -340,15 +336,15 @@ def test_table_conversions_sycl_usm(dataframe, queue, order, data_shape, dtype):
340336

341337

342338
@pytest.mark.parametrize(
343-
"dataframe,queue", get_dataframes_and_queues("numpy,dpctl,dpnp,array_api", "cpu,gpu")
339+
"dataframe,queue", get_dataframes_and_queues("numpy,dpnp,array_api", "cpu,gpu")
344340
)
345341
@pytest.mark.parametrize("data_shape", unsupported_data_shapes)
346342
def test_interop_invalid_shape(dataframe, queue, data_shape):
347343
X = np.zeros(data_shape)
348344
X = _convert_to_dataframe(X, sycl_queue=queue, target_df=dataframe)
349345

350346
expected_err_msg = r"Input array has wrong dimensionality \(must be 2d\)."
351-
if dataframe in "dpctl,dpnp":
347+
if dataframe == "dpnp":
352348
expected_err_msg = (
353349
"Unable to convert from SUA interface: only 1D & 2D tensors are allowed"
354350
)
@@ -357,7 +353,7 @@ def test_interop_invalid_shape(dataframe, queue, data_shape):
357353

358354

359355
@pytest.mark.parametrize(
360-
"dataframe,queue", get_dataframes_and_queues("dpctl,dpnp,array_api", "cpu,gpu")
356+
"dataframe,queue", get_dataframes_and_queues("dpnp,array_api", "cpu,gpu")
361357
)
362358
@pytest.mark.parametrize(
363359
"dtype",
@@ -370,8 +366,7 @@ def test_interop_invalid_shape(dataframe, queue, data_shape):
370366
def test_interop_unsupported_dtypes(dataframe, queue, dtype):
371367
# sua iface interobility supported only for oneDAL supported dtypes
372368
# for input data: int32, int64, float32, float64.
373-
# Checking some common dtypes supported by dpctl, dpnp for exception
374-
# raise.
369+
# Checking some common dtypes supported by dpnp for exception raise.
375370
X = np.zeros((10, 20), dtype=dtype)
376371
X = _convert_to_dataframe(X, sycl_queue=queue, target_df=dataframe)
377372
expected_err_msg = r"Found unsupported (array|tensor) type"
@@ -381,10 +376,10 @@ def test_interop_unsupported_dtypes(dataframe, queue, dtype):
381376

382377

383378
@pytest.mark.parametrize(
384-
"dataframe,queue", get_dataframes_and_queues("numpy,dpctl,dpnp", "cpu,gpu")
379+
"dataframe,queue", get_dataframes_and_queues("numpy,dpnp", "cpu,gpu")
385380
)
386381
def test_to_table_non_contiguous_input(dataframe, queue):
387-
if dataframe in "dpnp,dpctl" and not backend.is_dpc:
382+
if dataframe == "dpnp" and not backend.is_dpc:
388383
pytest.skip("__sycl_usm_array_interface__ support requires DPC backend.")
389384
X, _ = np.mgrid[:10, :10]
390385
X = _convert_to_dataframe(X, sycl_queue=queue, target_df=dataframe)
@@ -398,9 +393,7 @@ def test_to_table_non_contiguous_input(dataframe, queue):
398393
backend.is_dpc,
399394
reason="Required check should be done if no DPC backend.",
400395
)
401-
@pytest.mark.parametrize(
402-
"dataframe,queue", get_dataframes_and_queues("dpctl,dpnp", "cpu,gpu")
403-
)
396+
@pytest.mark.parametrize("dataframe,queue", get_dataframes_and_queues("dpnp", "cpu,gpu"))
404397
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
405398
def test_interop_if_no_dpc_backend_sycl_usm(dataframe, queue, dtype):
406399
X = np.zeros((10, 20), dtype=dtype)
@@ -524,9 +517,7 @@ def test_basic_ndarray_types_numpy(X):
524517
test_non_array(np.asarray(X), None)
525518

526519

527-
@pytest.mark.parametrize(
528-
"dataframe,queue", get_dataframes_and_queues("dpctl,numpy", "cpu,gpu")
529-
)
520+
@pytest.mark.parametrize("dataframe,queue", get_dataframes_and_queues("numpy", "cpu,gpu"))
530521
@pytest.mark.parametrize("can_copy", [True, False])
531522
def test_to_table_non_contiguous_input_dlpack(dataframe, queue, can_copy):
532523
X, _ = np.mgrid[:10, :10]
@@ -551,9 +542,7 @@ def test_to_table_non_contiguous_input_dlpack(dataframe, queue, can_copy):
551542
to_table(X_tens)
552543

553544

554-
@pytest.mark.parametrize(
555-
"dataframe,queue", get_dataframes_and_queues("dpctl,numpy", "cpu,gpu")
556-
)
545+
@pytest.mark.parametrize("dataframe,queue", get_dataframes_and_queues("numpy", "cpu,gpu"))
557546
@pytest.mark.parametrize("order", ["F", "C"])
558547
@pytest.mark.parametrize("data_shape", data_shapes)
559548
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
@@ -578,7 +567,7 @@ def test_table_conversions_dlpack(dataframe, queue, order, data_shape, dtype):
578567

579568

580569
@pytest.mark.parametrize(
581-
"dataframe,queue", get_dataframes_and_queues("numpy,dpctl,array_api", "cpu,gpu")
570+
"dataframe,queue", get_dataframes_and_queues("numpy,array_api", "cpu,gpu")
582571
)
583572
@pytest.mark.parametrize("order", ["F", "C"])
584573
@pytest.mark.parametrize("data_shape", data_shapes)
@@ -621,7 +610,7 @@ def test_table___dlpack__(dataframe, queue, order, data_shape, dtype):
621610
@pytest.mark.skipif(
622611
not hasattr(np, "from_dlpack"), reason="no dlpack support in installed numpy"
623612
)
624-
@pytest.mark.parametrize("dataframe,queue", get_dataframes_and_queues("dpctl", "cpu,gpu"))
613+
@pytest.mark.parametrize("dataframe,queue", get_dataframes_and_queues("dpnp", "cpu,gpu"))
625614
@pytest.mark.parametrize("order", ["F", "C"])
626615
@pytest.mark.parametrize("data_shape", data_shapes)
627616
@pytest.mark.parametrize("dtype", [np.float32, np.float64, np.int32, np.int64])
@@ -664,7 +653,7 @@ def test_table_writable_dlpack(queue):
664653
"""Test if __dlpack__ attribute can be properly consumed by moving data
665654
to host from a SYCL device.
666655
"""
667-
xp = pytest.importorskip("dpctl.tensor")
656+
xp = pytest.importorskip("dpnp")
668657
X = xp.eye(5, 8, dtype=xp.float32, device=queue)
669658
X.flags["W"] = False
670659
X_table = to_table(X)

onedal/tests/utils/_dataframes_support.py

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@
2020

2121
from sklearnex import get_config
2222

23-
from ...utils._third_party import dpctl_available
24-
25-
if dpctl_available:
26-
import dpctl.tensor as dpt
27-
2823
try:
2924
import dpnp
3025

@@ -55,7 +50,7 @@
5550
from onedal.tests.utils._device_selection import get_queues
5651

5752
test_frameworks = os.environ.get(
58-
"ONEDAL_PYTEST_FRAMEWORKS", "numpy,pandas,dpnp,dpctl,array_api"
53+
"ONEDAL_PYTEST_FRAMEWORKS", "numpy,pandas,dpnp,array_api"
5954
)
6055

6156

@@ -113,8 +108,6 @@ def get_df_and_q(dataframe: str):
113108
df_and_q.append(pytest.param(dataframe, queue.values[0], id=id))
114109
return df_and_q
115110

116-
if dpctl_available and "dpctl" in dataframe_filter_:
117-
dataframes_and_queues.extend(get_df_and_q("dpctl"))
118111
if dpnp_available and "dpnp" in dataframe_filter_:
119112
dataframes_and_queues.extend(get_df_and_q("dpnp"))
120113
if (
@@ -131,8 +124,6 @@ def _as_numpy(obj, *args, **kwargs):
131124
"""Converted input object to numpy.ndarray format."""
132125
if dpnp_available and isinstance(obj, dpnp.ndarray):
133126
return obj.asnumpy(*args, **kwargs)
134-
if dpctl_available and isinstance(obj, dpt.usm_ndarray):
135-
return dpt.to_numpy(obj, *args, **kwargs)
136127
if isinstance(obj, pd.DataFrame) or isinstance(obj, pd.Series):
137128
return obj.to_numpy(*args, **kwargs)
138129
if sp.issparse(obj):
@@ -166,12 +157,8 @@ def _convert_to_dataframe(obj, sycl_queue=None, target_df=None, *args, **kwargs)
166157
return dpnp.asarray(
167158
obj, usm_type="device", sycl_queue=sycl_queue, *args, **kwargs
168159
)
169-
elif target_df == "dpctl":
170-
# DPCtl tensor.
171-
return dpt.asarray(obj, usm_type="device", sycl_queue=sycl_queue, *args, **kwargs)
172160
elif target_df in array_api_modules:
173-
# Array API input other than DPNP ndarray, DPCtl tensor or
174-
# Numpy ndarray.
161+
# Array API input other than DPNP ndarray or Numpy ndarray.
175162

176163
xp = array_api_modules[target_df]
177164
return xp.asarray(obj)

onedal/utils/_array_api.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
"""Tools to support array_api."""
1818

19-
import warnings
2019
from collections.abc import Iterable
2120
from functools import lru_cache
2221

@@ -66,19 +65,7 @@ def _is_numpy_namespace(xp):
6665

6766
@lru_cache(100)
6867
def _cls_to_sycl_namespace(cls):
69-
# use caching to minimize imports, derived from array_api_compat
70-
if _is_subclass_fast(cls, "dpctl.tensor", "usm_ndarray"):
71-
import dpctl.tensor as dpt
72-
73-
warnings.warn(
74-
"dpctl tensors are deprecated and support for them in "
75-
"scikit-learn-intelex will be removed in 2026.0.0. "
76-
"Consider using dpnp arrays instead.",
77-
FutureWarning,
78-
)
79-
80-
return dpt
81-
elif _is_subclass_fast(cls, "dpnp", "ndarray"):
68+
if _is_subclass_fast(cls, "dpnp", "ndarray"):
8269
import dpnp
8370

8471
return dpnp

0 commit comments

Comments
 (0)