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

[experiment] ENH: using only raw inputs for onedal backend #2153

Draft
wants to merge 65 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
daed528
ENH: using only raw inputs for onedal backend
samir-nasibli Nov 5, 2024
1be2ffb
minor fix
samir-nasibli Nov 5, 2024
a23b677
lin
samir-nasibli Nov 5, 2024
664e140
fix usw_raw_input True/False with dpctl tensor on device
ahuber21 Nov 5, 2024
518dceb
Add hacks to kmeans
ahuber21 Nov 5, 2024
df9d930
Basic statistics online
samir-nasibli Nov 5, 2024
2954913
Merge branch 'enh/raw_inputs' of https://github.com/samir-nasibli/sci…
samir-nasibli Nov 5, 2024
3ef345c
Covariance support
ethanglaser Nov 5, 2024
f1c9233
Merge branch 'enh/raw_inputs' of https://github.com/samir-nasibli/sci…
ethanglaser Nov 5, 2024
66d7b2d
DBSCAN support
samir-nasibli Nov 5, 2024
c5d26a4
Merge branch 'enh/raw_inputs' of https://github.com/samir-nasibli/sci…
samir-nasibli Nov 5, 2024
1350c10
minor fix for dbscan
samir-nasibli Nov 5, 2024
8aaaa70
minor fix for DBSCAN
samir-nasibli Nov 5, 2024
f0d92ae
Apply raw input for batch linear and logistic regression
Alexsandruss Nov 5, 2024
3b58beb
Apply linters
Alexsandruss Nov 5, 2024
d7f2c3c
fix for DBSCAN
samir-nasibli Nov 5, 2024
1aca420
support for Random Forest
samir-nasibli Nov 5, 2024
362930a
PCA support (batch)
ethanglaser Nov 5, 2024
bc37391
Merge branch 'enh/raw_inputs' of https://github.com/samir-nasibli/sci…
ethanglaser Nov 5, 2024
102dcae
minor fix for dbscan and rf
samir-nasibli Nov 5, 2024
6edab5b
fully fixed DBSCAN
samir-nasibli Nov 6, 2024
e153a28
Add Incremental Linear Regression
Alexsandruss Nov 6, 2024
37d32c9
Linting
Alexsandruss Nov 6, 2024
71c5135
add modification to knn
ahuber21 Nov 6, 2024
db9f021
minor update for RF
samir-nasibli Nov 6, 2024
bc353da
fix for RandomForestClassifier
samir-nasibli Nov 7, 2024
e873205
minor for RF
samir-nasibli Nov 7, 2024
fe3222a
Update online algos
olegkkruglov Nov 7, 2024
5b3ad17
Merge branch 'enh/raw_inputs' of https://github.com/samir-nasibli/sci…
samir-nasibli Nov 7, 2024
eaaab32
fix for RF regressor
samir-nasibli Nov 7, 2024
a7f0c2d
fix workaround for knn
ahuber21 Nov 7, 2024
d9a2966
kmeans predict support
ethanglaser Nov 12, 2024
3562c69
Merge remote-tracking branch 'origin/main' into enh/raw_inputs
ahuber21 Dec 16, 2024
42c3614
fix merge errors
ahuber21 Dec 16, 2024
53bcc7b
fix some tests
ahuber21 Dec 17, 2024
9964c5a
fixup
ahuber21 Dec 17, 2024
84afb62
undo more changes that broke tests
ahuber21 Dec 17, 2024
cf5b736
format
ahuber21 Dec 17, 2024
92393b9
restore original behavior when running without raw inputs
ahuber21 Dec 18, 2024
13471e5
restore original behavior when running without raw inputs
ahuber21 Dec 18, 2024
a8f3f19
align code
ahuber21 Dec 18, 2024
2b07c00
restore original from_table
ahuber21 Dec 19, 2024
6104736
add use_raw_input tests for incremental covariance
ahuber21 Dec 19, 2024
df03233
Add basic statistics testing
ahuber21 Dec 19, 2024
8a166b7
add incremental basic statistics
ahuber21 Dec 19, 2024
fb5f5fa
add dbscan
ahuber21 Dec 19, 2024
7072041
Merge remote-tracking branch 'origin/main' into dev/ahuber/raw-inputs…
ahuber21 Dec 19, 2024
91384ed
add kmeans
ahuber21 Dec 20, 2024
6dec57d
add covariance
ahuber21 Dec 20, 2024
529a7b8
align get_config() import and use_raw_input retrieval
ahuber21 Dec 20, 2024
9f78cbd
add incremental_pca
ahuber21 Dec 20, 2024
658ccc1
add pca
ahuber21 Dec 20, 2024
5e74a54
add incremental linear
ahuber21 Dec 20, 2024
dfbf223
add linear_model
ahuber21 Dec 22, 2024
c4094fb
Merge branch 'dev/ahuber/raw-inputs-dispatching' into enh/raw_inputs
ahuber21 Dec 22, 2024
bb5206f
raw inputs updates for functional forest predict
ethanglaser Jan 9, 2025
8211a23
fixes for logreg predict_proba, knnreg, inc cov, inc pca
ethanglaser Jan 18, 2025
e3425bf
dbscan + inc linreg changes
ethanglaser Jan 20, 2025
0630bc1
Merge 'upstream/main' into enh/raw_inputs
ethanglaser Jan 20, 2025
52ba18a
black
ethanglaser Jan 20, 2025
90b7175
temporary for CI
ethanglaser Jan 21, 2025
f4d18cd
isorted
ethanglaser Jan 21, 2025
d84a559
tuple indices safeguarding
ethanglaser Jan 22, 2025
2daeeb7
incremental bs fit fixes
ethanglaser Jan 22, 2025
fb3d0bc
dbscan CI fixes
ethanglaser Jan 22, 2025
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: 1 addition & 0 deletions onedal/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"target_offload": "auto",
"allow_fallback_to_host": False,
"allow_sklearn_after_onedal": True,
"use_raw_input": False,
}

_threadlocal = threading.local()
Expand Down
51 changes: 28 additions & 23 deletions onedal/_device_offload.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,30 +180,35 @@ def support_input_format(freefunc=False, queue_param=True):

def decorator(func):
def wrapper_impl(obj, *args, **kwargs):
if len(args) == 0 and len(kwargs) == 0:
return _run_on_device(func, obj, *args, **kwargs)
data = (*args, *kwargs.values())
data_queue, hostargs, hostkwargs = _get_host_inputs(*args, **kwargs)
if queue_param and not (
"queue" in hostkwargs and hostkwargs["queue"] is not None
):
hostkwargs["queue"] = data_queue
result = _run_on_device(func, obj, *hostargs, **hostkwargs)
usm_iface = getattr(data[0], "__sycl_usm_array_interface__", None)
if usm_iface is not None:
result = _copy_to_usm(data_queue, result)
if dpnp_available and isinstance(data[0], dpnp.ndarray):
result = _convert_to_dpnp(result)
if not get_config()["use_raw_input"] == True:
if len(args) == 0 and len(kwargs) == 0:
return _run_on_device(func, obj, *args, **kwargs)
data = (*args, *kwargs.values())
data_queue, hostargs, hostkwargs = _get_host_inputs(*args, **kwargs)
if queue_param and not (
"queue" in hostkwargs and hostkwargs["queue"] is not None
):
hostkwargs["queue"] = data_queue
result = _run_on_device(func, obj, *hostargs, **hostkwargs)
usm_iface = getattr(data[0], "__sycl_usm_array_interface__", None)
if usm_iface is not None:
result = _copy_to_usm(data_queue, result)
if dpnp_available and isinstance(data[0], dpnp.ndarray):
result = _convert_to_dpnp(result)
return result
config = get_config()
if not ("transform_output" in config and config["transform_output"]):
input_array_api = getattr(
data[0], "__array_namespace__", lambda: None
)()
if input_array_api:
input_array_api_device = data[0].device
result = _asarray(
result, input_array_api, device=input_array_api_device
)
return result
config = get_config()
if not ("transform_output" in config and config["transform_output"]):
input_array_api = getattr(data[0], "__array_namespace__", lambda: None)()
if input_array_api:
input_array_api_device = data[0].device
result = _asarray(
result, input_array_api, device=input_array_api_device
)
return result
else:
return _run_on_device(func, obj, *args, **kwargs)

if freefunc:

Expand Down
36 changes: 26 additions & 10 deletions onedal/basic_statistics/basic_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@

import numpy as np

from .._config import _get_config
from ..common._base import BaseEstimator
from ..datatypes import _convert_to_supported, from_table, to_table
from ..utils import _is_csr
from ..utils._array_api import _get_sycl_namespace
from ..utils.validation import _check_array


Expand Down Expand Up @@ -72,23 +74,37 @@ def __init__(self, result_options="all", algorithm="by_default"):
super().__init__(result_options, algorithm)

def fit(self, data, sample_weight=None, queue=None):
use_raw_input = _get_config()["use_raw_input"]
# All data should use the same sycl queue.
sua_iface, xp, _ = _get_sycl_namespace(data)
# TODO:
# update support_input_format.
if use_raw_input and sua_iface:
queue = data.sycl_queue
policy = self._get_policy(queue, data, sample_weight)

is_csr = _is_csr(data)

if data is not None and not is_csr:
data = _check_array(data, ensure_2d=False)
if sample_weight is not None:
sample_weight = _check_array(sample_weight, ensure_2d=False)

if not use_raw_input:
is_csr = _is_csr(data)

if data is not None and not is_csr:
data = _check_array(data, ensure_2d=False)
if sample_weight is not None:
sample_weight = _check_array(sample_weight, ensure_2d=False)
# TODO
# use xp for dtype.
data, sample_weight = _convert_to_supported(policy, data, sample_weight)
is_single_dim = data.ndim == 1
data_table, weights_table = to_table(data, sample_weight)
data_table = to_table(data, sua_iface=sua_iface)
weights_table = to_table(sample_weight, sua_iface=sua_iface)
samir-nasibli marked this conversation as resolved.
Show resolved Hide resolved

dtype = data.dtype
raw_result = self._compute_raw(data_table, weights_table, policy, dtype, is_csr)
for opt, raw_value in raw_result.items():
value = from_table(raw_value).ravel()
# value = from_table(raw_value.responses, sua_iface=sua_iface, sycl_queue=queue, xp=xp).reshape(-1)
value = xp.ravel(
from_table(
raw_value.responses, sua_iface=sua_iface, sycl_queue=queue, xp=xp
)
)
if is_single_dim:
setattr(self, opt, value[0])
else:
Expand Down
3 changes: 3 additions & 0 deletions sklearnex/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def set_config(
target_offload=None,
allow_fallback_to_host=None,
allow_sklearn_after_onedal=None,
use_raw_input=None,
**sklearn_configs,
):
"""Set global configuration
Expand Down Expand Up @@ -75,6 +76,8 @@ def set_config(
local_config["allow_fallback_to_host"] = allow_fallback_to_host
if allow_sklearn_after_onedal is not None:
local_config["allow_sklearn_after_onedal"] = allow_sklearn_after_onedal
if use_raw_input is not None:
local_config["use_raw_input"] = use_raw_input


@contextmanager
Expand Down
77 changes: 41 additions & 36 deletions sklearnex/_device_offload.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,44 +58,49 @@ def _get_backend(obj, queue, method_name, *data):


def dispatch(obj, method_name, branches, *args, **kwargs):
q = _get_global_queue()
has_usm_data_for_args, q, hostargs = _transfer_to_host(q, *args)
has_usm_data_for_kwargs, q, hostvalues = _transfer_to_host(q, *kwargs.values())
hostkwargs = dict(zip(kwargs.keys(), hostvalues))

backend, q, patching_status = _get_backend(obj, q, method_name, *hostargs)
has_usm_data = has_usm_data_for_args or has_usm_data_for_kwargs
if backend == "onedal":
# Host args only used before onedal backend call.
# Device will be offloaded when onedal backend will be called.
patching_status.write_log(queue=q, transferred_to_host=False)
return branches[backend](obj, *hostargs, **hostkwargs, queue=q)
if backend == "sklearn":
if (
"array_api_dispatch" in get_config()
and get_config()["array_api_dispatch"]
and "array_api_support" in obj._get_tags()
and obj._get_tags()["array_api_support"]
and not has_usm_data
):
# USM ndarrays are also excluded for the fallback Array API. Currently, DPNP.ndarray is
# not compliant with the Array API standard, and DPCTL usm_ndarray Array API is compliant,
# except for the linalg module. There is no guarantee that stock scikit-learn will
# work with such input data. The condition will be updated after DPNP.ndarray and
# DPCTL usm_ndarray enabling for conformance testing and these arrays supportance
# of the fallback cases.
# If `array_api_dispatch` enabled and array api is supported for the stock scikit-learn,
# then raw inputs are used for the fallback.
patching_status.write_log(transferred_to_host=False)
return branches[backend](obj, *args, **kwargs)
else:
patching_status.write_log()
return branches[backend](obj, *hostargs, **hostkwargs)
raise RuntimeError(
f"Undefined backend {backend} in " f"{obj.__class__.__name__}.{method_name}"
)
if not get_config()["use_raw_input"] == True:
q = _get_global_queue()
has_usm_data_for_args, q, hostargs = _transfer_to_host(q, *args)
has_usm_data_for_kwargs, q, hostvalues = _transfer_to_host(q, *kwargs.values())
hostkwargs = dict(zip(kwargs.keys(), hostvalues))

backend, q, patching_status = _get_backend(obj, q, method_name, *hostargs)
has_usm_data = has_usm_data_for_args or has_usm_data_for_kwargs
if backend == "onedal":
# Host args only used before onedal backend call.
# Device will be offloaded when onedal backend will be called.
patching_status.write_log(queue=q, transferred_to_host=False)
return branches[backend](obj, *hostargs, **hostkwargs, queue=q)
if backend == "sklearn":
if (
"array_api_dispatch" in get_config()
and get_config()["array_api_dispatch"]
and "array_api_support" in obj._get_tags()
and obj._get_tags()["array_api_support"]
and not has_usm_data
):
# USM ndarrays are also excluded for the fallback Array API. Currently, DPNP.ndarray is
# not compliant with the Array API standard, and DPCTL usm_ndarray Array API is compliant,
# except for the linalg module. There is no guarantee that stock scikit-learn will
# work with such input data. The condition will be updated after DPNP.ndarray and
# DPCTL usm_ndarray enabling for conformance testing and these arrays supportance
# of the fallback cases.
# If `array_api_dispatch` enabled and array api is supported for the stock scikit-learn,
# then raw inputs are used for the fallback.
patching_status.write_log(transferred_to_host=False)
return branches[backend](obj, *args, **kwargs)
else:
patching_status.write_log()
return branches[backend](obj, *hostargs, **hostkwargs)
raise RuntimeError(
f"Undefined backend {backend} in " f"{obj.__class__.__name__}.{method_name}"
)
else:
return branches["onedal"](obj, *args, **kwargs)


# TODO:
# wrap output.
def wrap_output_data(func):
"""
Converts and moves the output arrays of the decorated function
Expand Down
Loading