-
Notifications
You must be signed in to change notification settings - Fork 51
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
QFxp: use integer values for classical sim instead of fxpmath.Fxp
#1204
QFxp: use integer values for classical sim instead of fxpmath.Fxp
#1204
Conversation
What's the motivation here? Is it faster? |
Yeah, Fxp is some quite slow, about 2-5x. And The current simulator uses ints for QFxp as well (as it always uses |
Can / should we remove the fxpmath dependency? |
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'm a little worried about this change, although I understand the frustration with Fxp. One of the primary motivations of the classical simulation protocol is to write classical programs that look like classical programs. This is super useful for a) unit testing, where one needs to inspect one side of the assertion and deem it obviously correct and b) looking at what a bloq does.
Let me think some more about this
Can you describe the motivations, consequences, and potential alternatives for this change? |
MotivationCurrently, the library mostly uses All existing bloqs assume the input values are integers for QFxp registers, e.g. Phase Gradient: Qualtran/qualtran/bloqs/rotations/phase_gradient.py Lines 312 to 325 in 15cb661
This PR
Consequences
Potential Alternatives
|
Thanks for the write-up!
If this is true, then this removes some of my concern about the current PR as a near-term solution to the problem(s). Can you add some text to the classical sim docs and classical sim docstrings that explains the behavior? Do we want to say what the integers are? The to_fixed_width_int says "re-interpret the bits as an int" but how are the bits laid out in Fxp? A more robust approach could be to create a lightweight wrapper around ints that at least makes the user call the classical functions correctly rather than having to convert to int and back class FxpVal:
_as_int: int
total_bits: int
frac_bits: int
def __add__(self, other):
return self._as_int + other._as_int
# etc |
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.
preliminary lgtm, but some documentation suggestions
|
||
We can specify a fixed point real number by the tuple bitsize, num_frac and | ||
signed, with num_int determined as `(bitsize - num_frac - n_sign)`. | ||
signed, with num_int determined as `(bitsize - num_frac)`. |
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.
There's some docstrings and comments hiding around the code. Can you add one or two short paragraphs to the class docstring for QFxp to describe the relationship to the classical simulation protocol and how we'll use these "raw ints" in the classical simulation protocol.
Comments don't show up in the docs and may be missed, and docstrings on private methods may be missed. You can also add a line to the docstrings of the public methods that says something like 'see the class docstring for details on the classical simulation format'
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.
Updated the class docstring
qualtran/_infra/data_types.py
Outdated
"""The corresponding integer type used to represent raw values of this type. | ||
|
||
This raw integer value is used in the classical simulator to represent values | ||
of QFxp registers. | ||
|
||
For example, QFxp(6, 2) has 2 int bits and 4 frac bits, and the corresponding | ||
int type is QUInt(6). So a true classical value of `10.0011` will have a raw | ||
integer representation of `100011`. | ||
""" |
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.
might be worth moving the bulk of this discussion to the class docstring and then just saying "the dtype in accordance with the format described in the class docstring"
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.
Moved to class docstring
qualtran/_infra/data_types.py
Outdated
def to_fixed_width_int(self, x: Union[float, Fxp], *, require_exact: bool = False) -> int: | ||
"""Returns the interpretation of the binary representation of `x` as an integer.""" |
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.
Refer to a description of the format. Do we want users to know what the classical format is? Yes, probably.
|
||
@property | ||
def _fxp_dtype(self) -> Fxp: | ||
return Fxp(None, dtype=self.fxp_dtype_str) | ||
def fxp_dtype_template(self) -> Fxp: |
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.
why are we using the word "template" here? because it doesn't actually have a value associated with it?
"""Prepare an empty `fxpmath.Fxp` value container for experimental fixed point support.
This constructs a `Fxp` object with no value. To assign the returned object a fixed point value,
use ... [idk, exaplain how to use it].
Fxp support is experimental and doesn't hook into the classical simulator protocol etc etc
This corresponds to the Fxp constructor arguments:
- op sizing, etc etc
"""
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 also make this a method instead of a property
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 used the term from the fxpmath readme: https://github.com/francof2a/fxpmath#:~:text=It%20is%20a%20good%20idea%20create%20Fxp%20objects%20like%20template%3A
This is used to type-cast Fxp values, instead of being an empty container, hence a property.
Example usage: some_fxp_value.like(QFxp(...).fxp_dtype_template)
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've updated the docstring to explain how to use this function
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.
you're never going to want to plumb through any of the options?
@mpharrigan ptal! I've updated the docstrings, and added a brief explanation in the |
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.
lgtm after docstring formatting fixes. you can use the scripts in dev_tools to preview how the api reference docs get rendered
fxpmath
based functionality in QFxp to private functionsTo pass inputs to the classical simulator, one should use
QFxp.to_fixed_width_int
to convert a float to the correct int for simulation.(part of #1142)
In a follow-up I will remove the classical_sim.py
ints_to_bits
andbits_to_ints
and update all bloqs to use qdtype features.