Skip to content
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 use_symengine option to qpy.dump #10820

Merged
merged 20 commits into from
Sep 27, 2023
Merged

Conversation

ElePT
Copy link
Contributor

@ElePT ElePT commented Sep 12, 2023

Summary

This is a proposal to fix #10705 by adding the use_symengine flag to qpy.dump(). This will improve the serialization performance for both circuits containing unbound ParameterExpressions and pulse schedules that rely on custom symbolic expressions.

Details and comments

The use_symengine flag is now stored as part of the file header, as it is a global option used by both circuit and schedule payloads. I have updated the documentation accordingly. I am not that familiar with the schedule "side" of QPY, so let me know if you can think of more cases I can add to the test, or whether I am missing anything (@nkanazawa1989).

qiskit/qpy/binary_io/value.py Outdated Show resolved Hide resolved
qiskit/qpy/binary_io/value.py Outdated Show resolved Hide resolved
@jakelishman
Copy link
Member

Did you consider modifying the header of the QPY file to include information on which symbolic library was used? Feels to me like we could avoid a lot of try-it-and-see decoding, which is a bit at the whims of Sympy/Symengine changing their encodings, but I didn't think it through hugely.

@mtreinish mtreinish added this to the 0.45.0 milestone Sep 12, 2023
@mtreinish mtreinish added performance Changelog: New Feature Include in the "Added" section of the changelog mod: qpy Related to QPY serialization labels Sep 12, 2023
@ElePT
Copy link
Contributor Author

ElePT commented Sep 12, 2023

Did you consider modifying the header of the QPY file to include information on which symbolic library was used? Feels to me like we could avoid a lot of try-it-and-see decoding, which is a bit at the whims of Sympy/Symengine changing their encodings, but I didn't think it through hugely.

Yes, it did cross my mind after all of those very specific try-catches (but for some reason was too reluctant to change it). I think that we could include the encoding in the PARAMETER_EXPR header:

    struct {
        uint64_t map_elements;
        uint64_t expr_size;
        _Bool uses_symengine;
    }

@jakelishman
Copy link
Member

Does it need to be in PARAMETER_EXPR? use_symengine is a global option to qpy.dump, so could the field be specified only once in the general QPY header rather than per-parameter?

qiskit/qpy/__init__.py Show resolved Hide resolved
qiskit/qpy/__init__.py Outdated Show resolved Hide resolved
qiskit/qpy/__init__.py Outdated Show resolved Hide resolved
qiskit/qpy/binary_io/schedules.py Outdated Show resolved Hide resolved
qiskit/qpy/formats.py Outdated Show resolved Hide resolved
qiskit/qpy/__init__.py Outdated Show resolved Hide resolved
@ElePT ElePT marked this pull request as ready for review September 14, 2023 16:47
@ElePT ElePT requested a review from a team as a code owner September 14, 2023 16:48
@qiskit-bot
Copy link
Collaborator

One or more of the the following people are requested to review this:

  • @Qiskit/terra-core
  • @mtreinish
  • @nkanazawa1989

Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, thanks for tackling this. I just had two small inline comments (although they likely apply in more places than where I commented). But aside from those I think this is basically ready.

qiskit/qpy/binary_io/schedules.py Outdated Show resolved Hide resolved

expr_txt = zlib.decompress(expr_bytes).decode(common.ENCODE)
expr = parse_expr(expr_txt)
expr = load_basic(zlib.decompress(expr_bytes))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need to zlib compress the symengine binary serialization? Maybe @nkanazawa1989 or @wshanks has some insight here, but I was thinking this was done for the sympy path because the string representation from sympy will get pretty verbose for some of the more involved pulse functions. But I'm not sure how large the symengine cereal serialization is and whether spending cpu time on inline compression here is worth it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm I think it is probably still worth it. I checked for the schedule in the unit tests. And I get that the uncompressed string vs compressed string sizes are:

use_symengine=False: 161 bytes uncompressed -> 101 bytes compressed (dump = 2.8 s)
use_symengine=True: 429 bytes uncompressed -> 143 bytes compressed (dump = 0.00256 s)

and the dump operation is 0.00005s slower with compression vs without.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, I guess I was worried about nothing since the data sizes we're talking about are sufficiently small zlib is sufficiently fast.

@@ -524,3 +524,21 @@ def assign(cls, obj):
@classmethod
def retrieve(cls, type_key):
raise NotImplementedError


class Encoding(TypeKeyBase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should name this SymExprEncoding or something a bit more descriptive. I'm just worried the name Encoding is too generic because if I saw that without the context of this PR I'd think it was like UTF-16.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being more specific with the class name would surely not hurt (especially if we wanted to add another encoding type in the future), so changed in b479cf0.

Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM, thanks for the quick updates.

@mtreinish mtreinish added this pull request to the merge queue Sep 27, 2023
Merged via the queue into Qiskit:main with commit b8b3d58 Sep 27, 2023
13 checks passed
rupeshknn pushed a commit to rupeshknn/qiskit that referenced this pull request Oct 9, 2023
* Add use-symengine option

* Fix lint

* Improve error message

* Apply feedback

* Update docs

* Move option to file header, add schedule block

* Add example to docs

* Fix lint

* Apply second round of feedback

* Fix lint, update tests

* Update docs

* Fix use of require_now

* Fix compatibility test

* Make tests optional

* Fix lint

* Add release note

* Update exception message

Co-authored-by: Matthew Treinish <[email protected]>

* Update other message

* Rename Encoding to SymExprEncoding

---------

Co-authored-by: Matthew Treinish <[email protected]>
mtreinish added a commit to mtreinish/qiskit-core that referenced this pull request Oct 26, 2023
In Qiskit#10820 a test qpy file from the development of the PR accidentally got
merged as part of the PR. This shouldn't have been committed and was a
mistake. This commit just removes the stray file so we're not continuing
to carry it around (although it will remain in the git history forever).
github-merge-queue bot pushed a commit that referenced this pull request Oct 26, 2023
In #10820 a test qpy file from the development of the PR accidentally got
merged as part of the PR. This shouldn't have been committed and was a
mistake. This commit just removes the stray file so we're not continuing
to carry it around (although it will remain in the git history forever).
mergify bot pushed a commit that referenced this pull request Oct 26, 2023
In #10820 a test qpy file from the development of the PR accidentally got
merged as part of the PR. This shouldn't have been committed and was a
mistake. This commit just removes the stray file so we're not continuing
to carry it around (although it will remain in the git history forever).

(cherry picked from commit 1bb219d)
github-merge-queue bot pushed a commit that referenced this pull request Oct 27, 2023
In #10820 a test qpy file from the development of the PR accidentally got
merged as part of the PR. This shouldn't have been committed and was a
mistake. This commit just removes the stray file so we're not continuing
to carry it around (although it will remain in the git history forever).

(cherry picked from commit 1bb219d)

Co-authored-by: Matthew Treinish <[email protected]>
Co-authored-by: Jake Lishman <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog mod: qpy Related to QPY serialization performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add symengine only mode to qpy
4 participants