Skip to content

Array's dtype asarray(np_float32_array, device=Device("device1")) #222

Closed

Description

@betatim

Another change between 2.5 and 2.6. In 2.6 the dtype of an array can be changed when you array_api_strict.asarray(x, device=Device("device1"))

With v2.5 this snippet prints array_api_strict.float32, with v2.6 you get float64.

import numpy as np
import array_api_strict as xp

x = np.ones((2,3), dtype=np.float32)
y = xp.asarray(x, device=xp.Device("device1"))

print(y.dtype)

I think preserving the dtype (if it is supported on the target device) is what should happen (aka behaviour of v2.5). I think the default dtype is something to look at for functions like ones() and friends. For those there is no hint from the user what the type should be.

A fix could be to use:

    # numpy default dtype may differ; if so, adjust the dtype.
    # Only do this for inputs whose dtype was inferred by NumPy (Python
    # scalars / sequences). Inputs that carry their own dtype (arrays and
    # buffer-protocol objects) must have that dtype preserved.
    if dtype is None and device is not None and not _supports_buffer_protocol(obj):
        res_dtype = DType(res.dtype)

Activity

  1. lucascolley commented on Jul 10, 2026

    @lucascolley
    Member

    A fix could be to use:

    Or perhaps more simply — mimicking the existing:

        if isinstance(obj, Array) and device is None:
            device = obj.device

    we could have

        if isinstance(obj, np.ndarray) and dtype is None:
            _np_dtype = obj.dtype
  2. betatim commented on Jul 10, 2026

    @betatim
    MemberAuthor

    I think we need _supports_buffer_protocol(obj) to catch other inputs that have a dtype attached, like numpy scalars or torch arrays (on the CPU).

  3. ev-br commented on Jul 10, 2026

    @ev-br
    Member

    Grr. _supports_buffer_protocol won't suffice, sadly, because torch does not support it, even on CPU.

    In [1]: import array_api_strict as xp
    
    In [2]: xp.__version__
    Out[2]: '2.5'
    
    In [3]: import torch
    
    In [4]: xp._creation_functions._supports_buffer_protocol(torch.ones(3))    # oops
    Out[4]: False
    
    In [5]: xp.asarray(torch.ones(3))
    Out[5]: Array([1., 1., 1.], dtype=array_api_strict.float32)
    
    In [6]: torch.ones(3).device
    Out[6]: device(type='cpu')
    
  4. ev-br commented on Jul 10, 2026

    @ev-br
    Member

    Special-casing np.ndarray won't do either as a bugfix because In[5] above: xp.asarray(torch.ones(3)) succeeds in 2.5.
    ATM the only way around I see is to branch on hasattr(obj, "dtype"). Any better ideas?

    Unless of course, we declare the 2.5 behavior a bug and declare that array-api-strict does not really support xp.asarray from alternative array libraries?

  5. lucascolley commented on Jul 10, 2026

    @lucascolley
    Member

    Unless of course, we declare the 2.5 behavior a bug and declare that array-api-strict does not really support xp.asarray from alternative array libraries?

    If it is indeed the case that PyTorch does not support the buffer protocol (is memoryview(obj) the correct test for that?), then yes, it seems better for array-api-strict to not support whatever makes np.asarray work (that is presumably absent from the spec).

  6. ev-br commented on Jul 10, 2026

    @ev-br
    Member

    Here's what I believe is a backwards compatible fix: #223
    Please do review / test / poke holes in it!

    If it is indeed the case that PyTorch does not support the buffer protocol (is memoryview(obj) the correct test for that?), then yes, it seems better for array-api-strict to not support whatever makes np.asarray work (that is presumably absent from the spec).

    I believe that yes and yes (pytorch does not support buffer protocol, and memoryview is the appropriate check for it).

    That said, let's maybe consider making array-api-strict stricter in a regular release (and consider this together with __array__). Meanwhile I think gating the dtype adjustment dance on obj.dtype is makes it backwards compatible: we first call np.array(obj), that either succeeded or failed. If it failed, there's no change in 2.6 or here; if it succeeded, then two options: obj is a python object (then we adjust the dtype) or it's an array (and then numpy did the work already and res.dtype matches obj.dtype).

  7. added this to the 2.6.1 milestone on Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions