-
Notifications
You must be signed in to change notification settings - Fork 354
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
Add AerStatevector #1590
Add AerStatevector #1590
Conversation
Add chunk distribution support
2d70b7f
to
9d5ecec
Compare
Co-authored-by: Jake Lishman <jake@binhbar.com>
ec9e56d
to
d5288b4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left quite a few comments (sorry) - since this is the actual user-facing interface, I had a bit more to say about structure and things like that.
I'm excited to see this in Aer, since it really starts making it easier to work with massive qubit systems from Python space. Do you happen to have any short benchmarks to hand about the performance of this compared to Terra's implementation?
A couple of top-level points:
- There's a few places where you call
<ExplicitSuperClass>.<method>
directly, or override stuff to do the same thing - just a reminder that all methods in Python are virtually dispatch, soself.<method>
orsuper().<method>
are usually what you want in those cases. - There's a lot of faff around memory moving, and passing an underlying
AerState
instance around secretly toAerStatevector.__init__
, which doesn't actually seem to accept that in its arguments. If you're constructing the Numpy arrays using the C API at some point, you might consider usingPyArray_SetBaseObject
to point to the owningAerState
, then it'll always be accessible asdata.base
, and you won't need the "moved" status inAerState
-AerState
will always be responsible for freeing its underlying Numpy array (allndarray
s that view this one set theirbase
to the same object, so the refcount of theAerState
can't ever become 0 while there's activendarray
views).
def __del__(self): | ||
""""destructor. Call close() if not called.""" | ||
if self._state in (_STATE.ALLOCATED, _STATE.MOVED): | ||
self.close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__del__
in Python isn't guaranteed to be called at all, even when the Python interpreter exits. It usually gets called, but it's not for sure. A reliable way to ensure the finaliser always gets called is weakref.finalize
- you'd call that immediately after allocating the memory in C++ space, I imagine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To call self.close()
in a callback, weakref.finalize()
needs to take self
as an argument for the callback. However, taking self
means self
will never be collected. I guess that another way is necessary.
However, AerState
is a private class. AerStatevector
will not keep AerState
as _STATE.ALLOCATED
. I believe that __del__
is not necessary.
class TestAerStatevector(common.QiskitAerTestCase): | ||
"""AerState tests""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to provide some more stress tests of the memory allocation, moving and de-allocation routines, since there's quite a lot of complexity in there.
Returned ndarray can be huge and it should be freed as early as possible. I think its lifecycle may be shorter than owning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of minor comments, but nothing that hugely needs to hold anything up.
def __copy__(self): | ||
ret = AerStatevector(self._data.copy(), **self._configs) | ||
ret._op_shape = self._op_shape | ||
ret._rng_generator = self._rng_generator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line looks dangerous - it'll cause two objects to hold references to the same rng instance, so they'll both be advancing state of the same thing. I don't know what's most appropriate here, but I'd expect maybe a copy of this?
def __eq__(self, other): | ||
return (isinstance(other, AerStatevector) and self.dims() == other.dims() and | ||
np.allclose(self._data, other._data, rtol=self.rtol, atol=self.atol)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The isinstance
check here is likely too strict - it'll cause equality not to be commutative when comparing with a raw Statevector
instance. Statevector.__eq__(AerStatevector)
(for the same data) will be true (because issubclass(AerStatevector, Statevector)
, but AerStatevector.__eq__(Statevector)
will be false.
That said, the fuzzy np.allclose
already breaks equality transitivity (a == b
and b == c
doesn't imply a == c
), but that's the fault of the base class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found that custom __eq__
does not need. The updated version uses __eq__
of the super class.
…__ in AerStatevector
…to add_aer_statevector
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last change squashed the last couple of major issues I had seen, thanks. I'm not ideally placed to evaluate whether the interface satisfies exactly what you need, and I don't want to hold this up any further. Let's move to merge and get Aer 0.11 out soon.
Summary
Add a new class
AerStatevector
that supportsq.i.s.Statevector
interface.Details and comments
By using
AerState
(#1586),AerStatevector
generatesndarray
of a statevector.