From 6b49210ec85fb7272f2c1330a22f2be6276ba50b Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Fri, 26 Jul 2024 19:46:33 -0500 Subject: [PATCH 1/3] Default int type queries behave based on NumPy version Introduced default_device_uint_type, parallel to default_device_int_type. For NumPy >= 2 (as checked at runtime), it returns "i8" (since dpctl is only supported on x86_64) or unsigned "u8", while for NumPy < 2 it returns long ("l"), or 'unsigned long' ("L"). --- .../source/device_support_queries.cpp | 49 +++++++++++++++++-- .../source/device_support_queries.hpp | 1 + .../tensor/libtensor/source/tensor_ctors.cpp | 8 ++- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/dpctl/tensor/libtensor/source/device_support_queries.cpp b/dpctl/tensor/libtensor/source/device_support_queries.cpp index 37d26512f3..b2a48b2e97 100644 --- a/dpctl/tensor/libtensor/source/device_support_queries.cpp +++ b/dpctl/tensor/libtensor/source/device_support_queries.cpp @@ -49,11 +49,48 @@ std::string _default_device_fp_type(const sycl::device &d) } } +int get_numpy_major_version() +{ + namespace py = pybind11; + + py::module_ numpy = py::module_::import("numpy"); + py::str version_string = numpy.attr("__version__"); + py::module_ numpy_lib = py::module_::import("numpy.lib"); + + py::object numpy_version = numpy_lib.attr("NumpyVersion")(version_string); + int major_version = numpy_version.attr("major").cast(); + + return major_version; +} + std::string _default_device_int_type(const sycl::device &) { - return "l"; // code for numpy.dtype('long') to be consistent - // with NumPy's default integer type across - // platforms. + const int np_ver = get_numpy_major_version(); + + if (np_ver >= 2) { + return "i8"; + } + else { + // code for numpy.dtype('long') to be consistent + // with NumPy's default integer type across + // platforms. + return "l"; + } +} + +std::string _default_device_uint_type(const sycl::device &) +{ + const int np_ver = get_numpy_major_version(); + + if (np_ver >= 2) { + return "u8"; + } + else { + // code for numpy.dtype('long') to be consistent + // with NumPy's default integer type across + // platforms. + return "L"; + } } std::string _default_device_complex_type(const sycl::device &d) @@ -108,6 +145,12 @@ std::string default_device_int_type(const py::object &arg) return _default_device_int_type(d); } +std::string default_device_uint_type(const py::object &arg) +{ + const sycl::device &d = _extract_device(arg); + return _default_device_uint_type(d); +} + std::string default_device_bool_type(const py::object &arg) { const sycl::device &d = _extract_device(arg); diff --git a/dpctl/tensor/libtensor/source/device_support_queries.hpp b/dpctl/tensor/libtensor/source/device_support_queries.hpp index 5092f47fb0..f5a10b9389 100644 --- a/dpctl/tensor/libtensor/source/device_support_queries.hpp +++ b/dpctl/tensor/libtensor/source/device_support_queries.hpp @@ -39,6 +39,7 @@ namespace py_internal extern std::string default_device_fp_type(const py::object &); extern std::string default_device_int_type(const py::object &); +extern std::string default_device_uint_type(const py::object &); extern std::string default_device_bool_type(const py::object &); extern std::string default_device_complex_type(const py::object &); extern std::string default_device_index_type(const py::object &); diff --git a/dpctl/tensor/libtensor/source/tensor_ctors.cpp b/dpctl/tensor/libtensor/source/tensor_ctors.cpp index 5387ffb0ae..c18220ee6c 100644 --- a/dpctl/tensor/libtensor/source/tensor_ctors.cpp +++ b/dpctl/tensor/libtensor/source/tensor_ctors.cpp @@ -331,7 +331,13 @@ PYBIND11_MODULE(_tensor_impl, m) m.def("default_device_int_type", dpctl::tensor::py_internal::default_device_int_type, - "Gives default integer type supported by device.", py::arg("dev")); + "Gives default signed integer type supported by device.", + py::arg("dev")); + + m.def("default_device_uint_type", + dpctl::tensor::py_internal::default_device_uint_type, + "Gives default unsigned integer type supported by device.", + py::arg("dev")); m.def("default_device_bool_type", dpctl::tensor::py_internal::default_device_bool_type, From d53c2fb209a6fc50c494b2cda27e0473f112d685 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Fri, 26 Jul 2024 19:50:03 -0500 Subject: [PATCH 2/3] Replace of use of upper to produce unsigned analog of default signed integral type with call to uint query --- dpctl/tensor/_type_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dpctl/tensor/_type_utils.py b/dpctl/tensor/_type_utils.py index 691f538336..a9c2b6f378 100644 --- a/dpctl/tensor/_type_utils.py +++ b/dpctl/tensor/_type_utils.py @@ -208,7 +208,7 @@ def _get_device_default_dtype(dt_kind, sycl_dev): elif dt_kind == "i": return dpt.dtype(ti.default_device_int_type(sycl_dev)) elif dt_kind == "u": - return dpt.dtype(ti.default_device_int_type(sycl_dev).upper()) + return dpt.dtype(ti.default_device_uint_type(sycl_dev)) elif dt_kind == "f": return dpt.dtype(ti.default_device_fp_type(sycl_dev)) elif dt_kind == "c": @@ -790,7 +790,7 @@ def _default_accumulation_dtype(inp_dt, q): if inp_dt.itemsize > res_dt.itemsize: res_dt = inp_dt elif inp_kind in "u": - res_dt = dpt.dtype(ti.default_device_int_type(q).upper()) + res_dt = dpt.dtype(ti.default_device_uint_type(q)) res_ii = dpt.iinfo(res_dt) inp_ii = dpt.iinfo(inp_dt) if inp_ii.min >= res_ii.min and inp_ii.max <= res_ii.max: From 00ecabe026879fd6a4a386d29d7e541300c17ede Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk Date: Fri, 26 Jul 2024 22:36:06 -0500 Subject: [PATCH 3/3] Fix test_pyx_capi_check_constants with NumPy 2.0 --- dpctl/tests/test_usm_ndarray_ctor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dpctl/tests/test_usm_ndarray_ctor.py b/dpctl/tests/test_usm_ndarray_ctor.py index d9ce0eff50..7216e2a615 100644 --- a/dpctl/tests/test_usm_ndarray_ctor.py +++ b/dpctl/tests/test_usm_ndarray_ctor.py @@ -1010,9 +1010,9 @@ def test_pyx_capi_check_constants(): assert uint_typenum == dpt.dtype(np.uintc).num long_typenum = _pyx_capi_int(X, "UAR_LONG") - assert long_typenum == dpt.dtype(np.int_).num + assert long_typenum == dpt.dtype("l").num ulong_typenum = _pyx_capi_int(X, "UAR_ULONG") - assert ulong_typenum == dpt.dtype(np.uint).num + assert ulong_typenum == dpt.dtype("L").num longlong_typenum = _pyx_capi_int(X, "UAR_LONGLONG") assert longlong_typenum == dpt.dtype(np.longlong).num