Skip to content

Support for memmap in Quantity #13864

Closed
astropy/asdf-astropy
#125

Description

@WilliamJamieson

Description

I if possible, would like the Quantity object to support memmap arrays, meaning that given a memmap array, a quantity constructed from that array remains memory mapped.

Additional context

It is possible that Quantity supports this, but it remains unclear. Right now if I run:

import numpy as np
import astropy.units as u

a = np.memmap('test', mode="w+", shape=(3,4))
q1 = u.Quantity(a, u.kg)
q2 = u.Quantity(a, u.kg, copy=False)

print(f'{isinstance(a, np.memmap)=}')
print(f'{isinstance(q1, np.memmap)=}')
print(f'{isinstance(q1.value, np.memmap)=}')
print(f'{isinstance(q2, np.memmap)=}')
print(f'{isinstance(q2.value, np.memmap)=}')

It returns

isinstance(a, np.memmap)=True
isinstance(q1, np.memmap)=False
isinstance(q1.value, np.memmap)=False
isinstance(q2, np.memmap)=False
isinstance(q2.value, np.memmap)=False

Which from the memmap documentation indicates to me that the the data is no longer memmap.

Basically, I would like a way to pass a memmap array to a Quantity and that Quantity to use the array data through the memmap (ie the data on disk mapped via the memmap to the array gets updated when I update the Quantity). This includes a way to interrogate the Quantity to confirm it is or is not using a memmap.

Activity

  1. WilliamJamieson commented on Oct 20, 2022

    @WilliamJamieson
    ContributorAuthor

    @mhvk and @nstarman do you have any idea of the state of memmap support for Quantity?

  2. nstarman commented on Oct 20, 2022

    @nstarman
    Member

    That would be very useful. I don't believe it's possible with the current implementation of Quantity, which subclasses ndarray, not memmap.

  3. WilliamJamieson commented on Oct 20, 2022

    @WilliamJamieson
    ContributorAuthor

    My familiarity with the intricacies of numpy arrays is limited. I did notice this in the memmap documentation:

    This subclass of ndarray has some unpleasant interactions with some operations, because it doesn’t quite fit properly as a subclass. An alternative to using this subclass is to create the mmap object yourself, then create an ndarray with ndarray.new directly, passing the object created in its ‘buffer=’ parameter.

    I wonder if this indicates that it might be possible to make Quantity a mmap object? If so, how would I do this? Again not super familiar with the intricacies involved.

  4. mhvk commented on Oct 20, 2022

    @mhvk
    Contributor

    In principle, it should be possible to make this work, since np.memmap is an ndarray subclass, but right now our use of ndarray is perhaps a bit too much built in. The suggestion you got from the documentation does work:

    a = np.memmap('test', mode="w+", shape=(3,4), dtype='f8')
    # Avoid myself making a mmap (should be quite easy, but just testing)
    mm = np.ndarray(buffer=a.base, shape=(3, 4), dtype='f8')
    q = u.Quantity(a, u.m, copy=False)
    
    # Check state of a
    a
    memmap([[0., 0., 0., 0.],
            [0., 0., 0., 0.],
            [0., 0., 0., 0.]])
    # Set an element in q
    q[-1, -1] = 1*u.cm
    # Check whether this propagates to a.
    a
    memmap([[0.  , 0.  , 0.  , 0.  ],
            [0.  , 0.  , 0.  , 0.  ],
            [0.  , 0.  , 0.  , 0.01]])
    # Check it is written to disk by exiting and logging in again
    a = np.memmap('test', mode="r", shape=(3,4), dtype='f8')
    # result is recovered
    
  5. WilliamJamieson commented on Oct 20, 2022

    @WilliamJamieson
    ContributorAuthor

    I guess this means there isn't an "easy" test for if Quantity is doing this memmap behavior akin to the isinstance(q, np.memmap) suggested by numpy?

  6. mhvk commented on Oct 20, 2022

    @mhvk
    Contributor

    Indeed, not immediately. I briefly tried whether it would work to define a new class QuantityMemmap(u.Quantity, np.memmap) but that in itself did not seem good enough. I have not investigated why, though think in principle it should be possible to get it to work; it might need the kind of automatic class construction that was used for Distribution and Masked and which @nstarman has been wanting to generalize. With that, Quantity might also be able to wrap dask arrays, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions