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

[bug] fix to_table for a non-array input when a low-precision queue is used #2271

Merged
merged 16 commits into from
Jan 27, 2025
7 changes: 1 addition & 6 deletions onedal/basic_statistics/basic_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,7 @@ def fit(self, data, sample_weight=None, queue=None):

is_single_dim = data.ndim == 1

data_table = to_table(data, queue=queue)
weights_table = (
to_table(sample_weight, queue=queue)
if sample_weight is not None
else to_table(None)
)
data_table, weights_table = to_table(data, sample_weight, queue=queue)

dtype = data_table.dtype
raw_result = self._compute_raw(data_table, weights_table, policy, dtype, is_csr)
Expand Down
15 changes: 9 additions & 6 deletions onedal/datatypes/data_conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,16 @@ inline csr_table_t convert_to_csr_impl(PyObject *py_data,

dal::table convert_to_table(py::object inp_obj, py::object queue) {
dal::table res;

PyObject *obj = inp_obj.ptr();

if (obj == nullptr || obj == Py_None) {
return res;
}

#ifdef ONEDAL_DATA_PARALLEL
if (!queue.is(py::none()) && !queue.attr("sycl_device").attr("has_aspect_fp64").cast<bool>()) {
if (!queue.is(py::none()) && !queue.attr("sycl_device").attr("has_aspect_fp64").cast<bool>() &&
hasattr(inp_obj, "dtype")) {
// If the queue exists, doesn't have the fp64 aspect, and the data is float64
// then cast it to float32
int type = reinterpret_cast<PyArray_Descr *>(inp_obj.attr("dtype").ptr())->type_num;
Expand All @@ -173,11 +181,6 @@ dal::table convert_to_table(py::object inp_obj, py::object queue) {
}
#endif // ONEDAL_DATA_PARALLEL

PyObject *obj = inp_obj.ptr();

if (obj == nullptr || obj == Py_None) {
return res;
}
if (is_array(obj)) {
PyArrayObject *ary = reinterpret_cast<PyArrayObject *>(obj);

Expand Down
41 changes: 41 additions & 0 deletions onedal/datatypes/tests/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,44 @@ class DummySyclDevice:
assert X_table.dtype == np.float32
if dtype == np.float32 and not sparse:
assert_allclose(X, from_table(X_table))


@pytest.mark.parametrize("X", [None, 5, "test", True, [], np.pi, lambda: None])
@pytest.mark.parametrize("queue", get_queues())
def test_non_array(X, queue):
# Verify that to and from table doesn't raise errors
# no guarantee is made about type or content
err_str = ""

if np.isscalar(X):
if np.atleast_2d(X).dtype not in [np.float64, np.float32, np.int64, np.int32]:
err_str = "Found unsupported array type"
elif not (X is None or isinstance(X, np.ndarray)):
err_str = r"\[convert_to_table\] Not available input format for convert Python object to onedal table."

if err_str:
with pytest.raises(ValueError, match=err_str):
to_table(X)
else:
X_table = to_table(X, queue=queue)
from_table(X_table)


@pytest.mark.skipif(
not _is_dpc_backend, reason="Requires DPC backend for dtype conversion"
)
@pytest.mark.parametrize("X", [None, 5, "test", True, [], np.pi, lambda: None])
def test_low_precision_non_array(X):
# Use a dummy queue as fp32 hardware is not in public testing

class DummySyclQueue:
"""This class is designed to act like dpctl.SyclQueue
to force dtype conversion"""

class DummySyclDevice:
has_aspect_fp64 = False

sycl_device = DummySyclDevice()

queue = DummySyclQueue()
test_non_array(X, queue)
Loading