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 herm_matmul
to speed up mesolve
.
#2173
base: master
Are you sure you want to change the base?
Conversation
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'd like to take a more detailed look at this once the Data specialization PR is merged, but the concept looks good.
Would you mind pinging me for another review here once the other PR is done?
…into feature.herm_matmul
Co-authored-by: Simon Cross <hodgestar+github@gmail.com>
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 a couple more comments. On the whole I'm not wild about the extra QobjEvo class, but if this is a use case you'd like to support, what about the following suggestion:
We allow the user to supply the QobjEvo
class to use as an option, and allow them to specify either the class itself or a name for the class. E.g. qobjevo_cls=QobjEvoHerm
or qobjevo_cls=herm
.
That allows many different classes to be used without the solvers needing to have special support added each time.
Perhaps we should also not allow users to switch the class later by changing options? That might simplify the logic because we wouldn't need to modify the RHS when options are updated.
qutip/solver/brmesolve.py
Outdated
keys.add('method') | ||
|
||
if hasattr(self, "_rhs") and "use_herm_matmul" in keys: | ||
self._rhs = self._update_rhs() |
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.
Are these two lines meant to be duplicated here? It seems odd to call self._update_rhs()
twice.
qutip/solver/brmesolve.py
Outdated
@@ -274,6 +280,7 @@ def __init__(self, H, a_ops, c_ops=None, sec_cutoff=0.1, *, options=None): | |||
self._num_collapse = len(c_ops) | |||
self._num_a_ops = len(a_ops) | |||
self.rhs = self._prepare_rhs() | |||
self._rhs = self._update_rhs() |
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.
Duplicating the RHS here feels very messy. Could we just store a single RHS as self.rhs
and convert to and from QobjEvoHerm
as needed when options are updated?
I would prefer the user not needing to know how we do it, just that there an option that speed up the simulation by 40 % in normal cases. Knowing that we forced it in an alternative qobjevo class is not useful and I hope we won't be forced to add many kinds of qobjevo.
Since changing options does not change the physic, I would like them to be changeable. But the |
…into feature.herm_matmul
4585c69
to
afe7433
Compare
I removed the I also simplified the way options are updated so brmesolve no longer need to overwrite |
resultclass = Result | ||
|
||
def __init__(self, rhs, *, options=None): | ||
if isinstance(rhs, (QobjEvo, Qobj)): | ||
self.rhs = QobjEvo(rhs) | ||
else: | ||
elif rhs is not None: |
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.
All subclasses of Solver
should have one path for building the RHS. Having two paths makes the code much harder to reason about.
I think _build_rhs()
is a good idea, although I think we should implement it on all sub-classes of Solver
and have Solver
do self.rhs = self._build_rhs()
at the end of __init__
and when options are changed (if needed). That way .rhs
is always correct for the given options.
Description
Add a variant to
matmul
specialised for case where the right matrix is a column stacked hermitian matrix, and the output is the same. Such as formesolve
using super operators.Open solvers
mesolve
,brmesolve
,smesolve
andfmesolve
all have a new optionsuse_herm_matmul
to use this operation. The default isFalse
since we cannot easily check for exception (we can't test that a time dependant Hamiltonian is Hermitian, ...).With large enough systems, this result in a visible speed up:
This is a use case for the capacity to dispatch on
Data
added in #2157. Whenherm_matmul
is not available, it can be better to fallback onmatmul
using the same type than to do conversions between data types. For cupy, moving the data to the cpu to halves the work is probably not worth it.Related issues or PRs
This is build on top of #2157, it should be merged first.