-
Notifications
You must be signed in to change notification settings - Fork 342
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 quilc_client property to QVMCompiler, improve timeout documentation #1273
Conversation
Add a client property to QPUCompiler so that it has better feature parity with QVMCompiler. Generally we tell folks that 1. QVMCompiler and QPUCompiler should be largely interchangeable, meaning that you can swap `qc = get_qc("Aspen-8", as_qvm=True)` with `qc = get_qc("Aspen-8", as_qvm=False)`, and things should Just Work. And 2. To set the timeout on a QVMCompiler one does `qc.compiler.client.rpc_timeout = ...` but on a QPUCompiler `qc.compiler.quilc_client.rpc_timeout = ...`. This change brings 1 and 2 into alignment, so that the method for configuring the compiler timeout is the same between the compiler classes.
docs/source/compiler.rst
Outdated
|
||
.. code:: python | ||
qc = get_qc(..., as_qvm=False) | ||
qc.compiler.quilc_client.rpc_timeout = 100 # 100 seconds |
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.
Is it? The instructions I've always used / given is:
On QVM, you need "qc.compiler.client.timeout";
On QPU it is just "qc.compiler.timeout".
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 timeout is most relevant to the Client
object that is created. In both QVMCompiler
and QPUCompiler
the (quilc) client is instantiated in __init__
and so immediately uses the timeout
arg given to __init__
(this is the same value that is assigned to self.timeout
in both classes). Therefore if you want to modify the timeout that is used specifically in quilc, then you have to change qc.compiler.{client,quilc_client}.rpc_timeout
. QPUCompiler
has a second client to the translation service, which also uses self.timeout
but is deferred until the client is requested. I think that means that you probably got it to work by using qc.compiler.timeout
because the client hadn't yet been created, and so used the new timeout value.
All that to say, this PR doesn't modify the translation service timeout. Should it?
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.
Yeah, unless there was a separate well-documented path for the translation service, I'd apply this one timeout in both locations (and say that it applies to both the compiler timeout for quil_to_native_quil, and translation timeout for native_quil_to_executable).
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.
Note that a commit I just added now does modify the translation service timeout. That one is set on a per-call basis to the current value of QPUCompiler#timeout
.
pyquil/api/_compiler.py
Outdated
@property | ||
def client(self) -> Client: | ||
"""Return the `Client` for the compiler (i.e. quilc, not translation service).""" | ||
# TODO(notmgsk): This was introduced around 2.25 to provide |
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 should be in the docstring, and not version-specific. While that seems like important information within the context of the PR, it becomes irrelevant as more information comes out.
Also, this might be worth having as an @abstractmethod
on the AbstractCompiler
with the documentation note there instead. That's the intent behind abstract methods in any case - parity among subclasses.
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 removed the comment entirely, and have chosen to not take the abstract method route just because at this point I'm not sure how much it gives us, but if you feel strongly about it I will add it.
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.
well, now that the methods are identical, I think it's wise to make it a non-abstract method on the parent class for de-duplication
@@ -182,7 +182,7 @@ def __init__( | |||
quilc_endpoint: Optional[str], | |||
qpu_compiler_endpoint: Optional[str], | |||
device: AbstractDevice, | |||
timeout: int = 10, | |||
timeout: float = 10, |
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.
Should we also support this in get_qc
, maybe as compiler_timeout
? That's the "tutorial" way of constructing this in any 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.
Donezo. I have refrained from adding a timeout option to QuantumComputer#compile
, because (1) I think the options available now are sufficient, and (2) we could probably find a million places to add a timeout flag to (gotta draw the line somewhere).
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.
agreed
@@ -338,7 +338,9 @@ def native_quil_to_executable(self, nq_program: Program) -> Optional[BinaryExecu | |||
) | |||
response: BinaryExecutableResponse = cast( | |||
BinaryExecutableResponse, | |||
self.qpu_compiler_client.call("native_quil_to_binary", request), | |||
self.qpu_compiler_client.call( | |||
"native_quil_to_binary", request, rpc_timeout=self.timeout |
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 flubbed this in #1246 , should have been included there
docs/source/compiler.rst
Outdated
|
||
.. code:: python | ||
qc = get_qc(..., as_qvm=False) | ||
qc.compiler.quilc_client.rpc_timeout = 100 # 100 seconds |
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.
Note that a commit I just added now does modify the translation service timeout. That one is set on a per-call basis to the current value of QPUCompiler#timeout
.
Needs a changelog entry also. |
Hopefully all comments are addressed. Please take another look |
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.
Since lgtmset_timeout
is now identical between the two compilers, it should be hoisted to a concrete method on the parent class. Otherwise,
Add a client property to QPUCompiler so that it has better feature
parity with QVMCompiler. Generally we tell folks that
QVMCompiler and QPUCompiler should be largely interchangeable,
meaning that you can swap
qc = get_qc("Aspen-8", as_qvm=True)
withqc = get_qc("Aspen-8", as_qvm=False)
, and things should JustWork. And
To set the timeout on a QVMCompiler one does
qc.compiler.client.rpc_timeout = ...
but on a QPUCompilerqc.compiler.quilc_client.rpc_timeout = ...
.This change brings 1 and 2 into alignment, so that the method for
configuring the compiler timeout is the same between the compiler
classes.
Further, it adds a
set_timeout
method for both classes, and updatesthe documentation.