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

Implemented dpnp.frombuffer, dpnp.fromfile and dpnp.fromstring #1727

Merged
merged 2 commits into from
Feb 22, 2024
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
275 changes: 264 additions & 11 deletions dpnp/dpnp_iface_arraycreation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1399,23 +1399,114 @@ def eye(
)


def frombuffer(buffer, **kwargs):
"""
def frombuffer(
buffer,
dtype=float,
count=-1,
offset=0,
*,
like=None,
device=None,
usm_type="device",
sycl_queue=None,
):
r"""
Interpret a buffer as a 1-dimensional array.

For full documentation refer to :obj:`numpy.frombuffer`.

Parameters
----------
buffer : buffer_like
An object that exposes the buffer interface.
dtype : data-type, optional
Data-type of the returned array.
Default is the default floating point data type for the device where
the returned array is allocated.
count : int, optional
Number of items to read. ``-1`` means all data in the buffer.
offset : int, optional
Start reading the buffer from this offset (in bytes); default: 0.
device : {None, string, SyclDevice, SyclQueue}, optional
An array API concept of device where the output array is created.
The `device` can be ``None`` (the default), an OneAPI filter selector
string, an instance of :class:`dpctl.SyclDevice` corresponding to
a non-partitioned SYCL device, an instance of :class:`dpctl.SyclQueue`,
or a `Device` object returned by
:obj:`dpnp.dpnp_array.dpnp_array.device` property.
usm_type : {"device", "shared", "host"}, optional
The type of SYCL USM allocation for the output array.
Default is "device".
sycl_queue : {None, SyclQueue}, optional
A SYCL queue to use for output array allocation and copying.

Returns
-------
out : dpnp.ndarray
A 1-dimensional array created from input buffer object.

Limitations
-----------
Only float64, float32, int64, int32 types are supported.
Parameter `like` is supported only with default value ``None``.
Otherwise, the function raises `NotImplementedError` exception.

"""
Notes
-----
This uses :obj:`numpy.frombuffer` and coerces the result to a DPNP array.

return call_origin(numpy.frombuffer, buffer, **kwargs)
See also
--------
:obj:`dpnp.fromfile` : Construct array from data in a text or binary file.
:obj:`dpnp.fromiter` : Construct array from an iterable object.
:obj:`dpnp.fromstring` : Construct array from the text data in a string.

Examples
--------
>>> import dpnp as np
>>> s = b'\x01\x02\x03\x04'
>>> np.frombuffer(s, dtype=np.int32)
array([67305985], dtype=int32)
>>> np.frombuffer(b'\x01\x02\x03\x04\x05', dtype='u1', count=3)
array([1, 2, 3], dtype=uint8)

Creating an array on a different device or with a specified usm_type

>>> x = np.frombuffer(s, dtype=np.int32) # default case
>>> x.device, x.usm_type
(Device(level_zero:gpu:0), 'device')

>>> y = np.frombuffer(s, dtype=np.int32, device='cpu')
>>> y.device, y.usm_type
(Device(opencl:cpu:0), 'device')

>>> z = np.frombuffer(s, dtype=np.int32, usm_type="host")
>>> z.device, z.usm_type
(Device(level_zero:gpu:0), 'host')

def fromfile(file, **kwargs):
"""

_check_limitations(like=like)
return asarray(
numpy.frombuffer(buffer, dtype=dtype, count=count, offset=offset),
device=device,
usm_type=usm_type,
sycl_queue=sycl_queue,
)


def fromfile(
file,
dtype=float,
count=-1,
sep="",
offset=0,
*,
like=None,
device=None,
usm_type="device",
sycl_queue=None,
):
r"""
Construct an array from data in a text or binary file.

A highly efficient way of reading binary data with a known data-type,
Expand All @@ -1424,13 +1515,107 @@ def fromfile(file, **kwargs):

For full documentation refer to :obj:`numpy.fromfile`.

Parameters
----------
file : file or str or Path
Open file object or filename.
dtype : data-type, optional
Data type of the returned array.
For binary files, it is used to determine the size and byte-order
of the items in the file.
Default is the default floating point data type for the device where
the returned array is allocated.
count : int, optional
Number of items to read. ``-1`` means all items (i.e., the complete
file).
sep : str, optional
Separator between items if `file` is a text file.
Empty ("") separator means the file should be treated as binary.
Spaces (" ") in the separator match zero or more whitespace characters.
A separator consisting only of spaces must match at least one
whitespace.
offset : int, optional
The offset (in bytes) from the file's current position. Defaults to 0.
Only permitted for binary files.
device : {None, string, SyclDevice, SyclQueue}, optional
An array API concept of device where the output array is created.
The `device` can be ``None`` (the default), an OneAPI filter selector
string, an instance of :class:`dpctl.SyclDevice` corresponding to
a non-partitioned SYCL device, an instance of :class:`dpctl.SyclQueue`,
or a `Device` object returned by
:obj:`dpnp.dpnp_array.dpnp_array.device` property.
usm_type : {"device", "shared", "host"}, optional
The type of SYCL USM allocation for the output array.
Default is "device".
sycl_queue : {None, SyclQueue}, optional
A SYCL queue to use for output array allocation and copying.

Returns
-------
out : dpnp.ndarray
A 1-dimensional array created from data in a text or binary file.

Limitations
-----------
Only float64, float32, int64, int32 types are supported.
Parameter `like` is supported only with default value ``None``.
Otherwise, the function raises `NotImplementedError` exception.

Notes
-----
This uses :obj:`numpy.fromfile` and coerces the result to a DPNP array.

See also
--------
:obj:`dpnp.frombuffer` : Construct array from the buffer data.
:obj:`dpnp.fromiter` : Construct array from an iterable object.
:obj:`dpnp.fromstring` : Construct array from the text data in a string.
:obj:`dpnp.load` : Load arrays or pickled objects from files.
:obj:`dpnp.save` : Save an array to a binary file.
:obj:`dpnp.ndarray.tofile` : Write array to a file as text or binary.
:obj:`dpnp.loadtxt` : More flexible way of loading data from a text file.

Examples
--------
Save the data to a temporary file:

>>> import tempfile
>>> fh = tempfile.TemporaryFile()
>>> fh.write(b"\x00\x01\x02\x03\x04")
>>> fh.flush()
>>> fh.seek(0)

Construct an array:

>>> import dpnp as np
>>> np.fromfile(fh, dtype="u1")
array([0, 1, 2, 3, 4], dtype=uint8)

Creating an array on a different device or with a specified usm_type

>>> fh.seek(0)
>>> x = np.fromfile(fh, dtype="u1") # default case
>>> x.device, x.usm_type
(Device(level_zero:gpu:0), 'device')

>>> fh.seek(0)
>>> y = np.fromfile(fh, dtype="u1", device='cpu')
>>> y.device, y.usm_type
(Device(opencl:cpu:0), 'device')

>>> fh.seek(0)
>>> z = np.fromfile(fh, dtype="u1", usm_type="host")
>>> z.device, z.usm_type
(Device(level_zero:gpu:0), 'host')

"""

return call_origin(numpy.fromfile, file, **kwargs)
_check_limitations(like=like)
return asarray(
numpy.fromfile(file, dtype=dtype, count=count, sep=sep, offset=offset),
device=device,
usm_type=usm_type,
sycl_queue=sycl_queue,
)


def fromfunction(function, shape, **kwargs):
Expand Down Expand Up @@ -1466,19 +1651,87 @@ def fromiter(iterable, dtype, count=-1):
return call_origin(numpy.fromiter, iterable, dtype, count)


def fromstring(string, **kwargs):
def fromstring(
string,
dtype=float,
count=-1,
*,
sep,
like=None,
device=None,
usm_type="device",
sycl_queue=None,
):
"""
A new 1-D array initialized from text data in a string.

For full documentation refer to :obj:`numpy.fromstring`.

Parameters
----------
string : str
A string containing the data.
dtype : data-type, optional
The data type of the array.
For binary input data, the data must be in exactly this format.
Default is the default floating point data type for the device where
the returned array is allocated.
count : int, optional
Read this number of `dtype` elements from the data. If this is negative
(the default), the count will be determined from the length of the data.
sep : str, optional
The string separating numbers in the data; extra whitespace between
elements is also ignored.
device : {None, string, SyclDevice, SyclQueue}, optional
An array API concept of device where the output array is created.
The `device` can be ``None`` (the default), an OneAPI filter selector
string, an instance of :class:`dpctl.SyclDevice` corresponding to
a non-partitioned SYCL device, an instance of :class:`dpctl.SyclQueue`,
or a `Device` object returned by
:obj:`dpnp.dpnp_array.dpnp_array.device` property.
usm_type : {"device", "shared", "host"}, optional
The type of SYCL USM allocation for the output array.
Default is "device".
sycl_queue : {None, SyclQueue}, optional
A SYCL queue to use for output array allocation and copying.

Returns
-------
out : dpnp.ndarray
The constructed array.

Limitations
-----------
Only float64, float32, int64, int32 types are supported.
Parameter `like` is supported only with default value ``None``.
Otherwise, the function raises `NotImplementedError` exception.

Notes
-----
This uses :obj:`numpy.fromstring` and coerces the result to a DPNP array.

See also
--------
:obj:`dpnp.frombuffer` : Construct array from the buffer data.
:obj:`dpnp.fromfile` : Construct array from data in a text or binary file.
:obj:`dpnp.fromiter` : Construct array from an iterable object.

Examples
--------
>>> import dpnp as np
>>> np.fromstring('1 2', dtype=int, sep=' ')
array([1, 2])
>>> np.fromstring('1, 2', dtype=int, sep=',')
array([1, 2])

"""

return call_origin(numpy.fromstring, string, **kwargs)
_check_limitations(like=like)
return asarray(
numpy.fromstring(string, dtype=dtype, count=count, sep=sep),
device=device,
usm_type=usm_type,
sycl_queue=sycl_queue,
)


def full(
Expand Down
17 changes: 5 additions & 12 deletions tests/test_arraycreation.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def test_exception_order(func, args):
pytest.param("asfortranarray", [2]),
pytest.param("empty", [(2,)]),
pytest.param("eye", [2]),
pytest.param("frombuffer", [b"\x01\x02\x03\x04"]),
pytest.param("full", [(2,), 4]),
pytest.param("identity", [2]),
pytest.param("ones", [(2,)]),
Expand Down Expand Up @@ -208,21 +209,14 @@ def test_eye(N, M, k, dtype, order):
assert_array_equal(func(numpy), func(dpnp))


@pytest.mark.usefixtures("allow_fall_back_on_numpy")
@pytest.mark.parametrize(
"dtype",
get_all_dtypes(
no_float16=False, no_none=False if has_support_aspect64() else True
),
)
@pytest.mark.parametrize("dtype", get_all_dtypes(no_float16=False))
def test_frombuffer(dtype):
buffer = b"12345678ABCDEF00"
func = lambda xp: xp.frombuffer(buffer, dtype=dtype)
assert_allclose(func(dpnp), func(numpy))
assert_dtype_allclose(func(dpnp), func(numpy))


@pytest.mark.usefixtures("allow_fall_back_on_numpy")
@pytest.mark.parametrize("dtype", get_all_dtypes())
@pytest.mark.parametrize("dtype", get_all_dtypes(no_float16=False))
def test_fromfile(dtype):
with tempfile.TemporaryFile() as fh:
fh.write(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08")
Expand All @@ -236,7 +230,7 @@ def test_fromfile(dtype):
fh.seek(0)
dpnp_res = func(dpnp)

assert_almost_equal(dpnp_res, np_res)
assert_dtype_allclose(dpnp_res, np_res)


@pytest.mark.usefixtures("allow_fall_back_on_numpy")
Expand All @@ -260,7 +254,6 @@ def test_fromiter(dtype):
assert_array_equal(func(dpnp), func(numpy))


@pytest.mark.usefixtures("allow_fall_back_on_numpy")
@pytest.mark.parametrize("dtype", get_all_dtypes(no_float16=False))
def test_fromstring(dtype):
string = "1 2 3 4"
Expand Down
Loading
Loading