-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Fix PulseQobj converter name collision #8839
Conversation
Thank you for opening a new pull request. Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient. While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone. One or more of the the following people are requested to review this:
|
I confirmed new mechanism works properly with real backend. from qiskit import QuantumCircuit, transpile, schedule
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()
# chose qubit pair with DDCX,
# this is currently waveform instruction because of missing parametric pulse class.
# this is nice to debug pulse library reference mechanism.
bell_schedule = schedule(transpile(qc, backend, initial_layout=[3, 5]), backend)
job = backend.run(bell_schedule)
result = job.result()
result.get_counts() # {'00': 1929, '01': 557, '10': 88, '11': 1426} |
Pull Request Test Coverage Report for Build 3853489076
💛 - Coveralls |
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.
Overall this looks good to me, I didn't see anything that really stood out as an issue in reviewing this. However, I'm not the most familiar with this part of the code base. I've not really had any reason to work with pulse qobj converters directly before. I left some review comments inline on the release notes, but they're not really blocking (we can always fix that as part of the release prep PR)
"ch": instruction.channel.name, | ||
"frequency": instruction.frequency / 1e9, | ||
} | ||
return self._qobj_model(**command_dict) | ||
|
||
@bind_instruction(instructions.SetPhase) | ||
def convert_set_phase(self, shift, instruction): | ||
def _convert_SetPhase( |
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 surprised pylint doesn't complain about this being camel case.
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.
Yes, this was what I wanted to change. Since now we can use method dispatch in terra, I updated the implementation of these method in f1ad415
releasenotes/notes/fix-pulse-qobj-converter-name-collision-0b225af630f4a6c6.yaml
Outdated
Show resolved
Hide resolved
releasenotes/notes/fix-pulse-qobj-converter-name-collision-0b225af630f4a6c6.yaml
Outdated
Show resolved
Hide resolved
Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
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, thanks for the quick update.
* Update pulse qobj converter. Reimplemented with visitor pattern. * Add release note. * Review comments Co-authored-by: Matthew Treinish <mtreinish@kortar.org> * Use method dispatch * give descriptive method name
* Update pulse qobj converter. Reimplemented with visitor pattern. * Add release note. * Review comments Co-authored-by: Matthew Treinish <mtreinish@kortar.org> * Use method dispatch * give descriptive method name
Summary
This PR fixes name collision bug (edge case) of pulse qobj converter (
QobjToInstructionConverter
).Details and comments
In the pulse qobj model, instruction is managed by the unique string identifier, e.g.
ShiftPhase
:fc
, in the transfer layer. Only exception is thePlay
instruction, because this instruction takes two types of operands, namely, parametric pulse and waveform. When the backend doesn't support a parametric pulse form, this is converted into waveform and actual waveform samples are stored in the.pulse_library
field. Thus command.name
of the play instruction isparametric_pulse
or unique waveform name (such asCX_d10_u15
, which is a foreign key to refer to the pulse library), rather than "play".Currently,
QobjToInstructionConverter
manages these instructions with a dedicated method. This is sort of descriptor pattern, where dedicated method to parse each pulse library item (as well as other instructions) is dynamically generated. Note that this descriptor is directly attached to the class. Thus, when multiple converters are instantiated with different backends in the same thread, it could cause name collision when backend reports different waveforms under the same name. For example,sched_out_x
andsched_out_y
accidentally loads the same pulse from the pulse library of backend y (because this is the latest instance). Note that this doesn't happen in current Qiskit client, because converter is immediately discarded afterPulseDefaults
for a particular backend is instantiated. However, this mechanism doesn't stop developers to keep converter. Such converter is silently mutated when another backend is loaded.In this PR, descriptor-like pattern is replaced with visitor pattern, and class level cache is removed.
New test
test_instruction_name_collision
is also added.