-
Notifications
You must be signed in to change notification settings - Fork 358
Support Asynchronous Execution with Compatibility Layer #1331
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
Changes from 61 commits
ea20069
1dcb94f
52a1807
be0cf49
94ba3e6
0cba876
bda7d67
32a6315
23436fa
b56996f
b47187a
347e0f0
262f078
54ffa39
b7aed86
bf828dc
586155e
e0ee067
186ba0c
dded7b7
011d377
f13e684
f7fc111
7f6d46a
eb4f91a
fd2f3f5
60bd2d8
95bf9b4
0b071d7
b9f3d19
17f21a7
6aaa270
8124327
1c82890
85886a3
7822029
cbcb387
f68cae9
92875d3
4f210e8
54c47a7
271de7f
9de7c88
330f49d
38ffbbd
d2daf19
969d96d
3520812
f93c606
db1c94a
df6d355
1a4c323
f19354b
d3ae981
87ec006
f816171
50260b8
82fef98
091cef7
621c550
46d442d
24552ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,21 +35,21 @@ locally): | |
| Concurrency | ||
| ~~~~~~~~~~~ | ||
|
|
||
| Using pyQuil for concurrent programming is as simple as calling :py:func:`~pyquil.get_qc()` from within a given thread | ||
| or process, then using the returned :py:class:`~pyquil.api.QuantumComputer` as usual. While | ||
| :py:class:`~pyquil.api.QuantumComputer` objects as a whole are not safe to share between threads or processes (due to | ||
| state related to currently-running compilation or execution requests), some information they use is. Information related | ||
| to client configuration (:py:class:`~pyquil.api.QCSClientConfiguration`) and QPU auth | ||
| (:py:class:`~pyquil.api.EngagementManager`) can be safely extracted and shared among | ||
| :py:class:`~pyquil.api.QuantumComputer` instances, as shown below, to save your code from redundant disk reads and | ||
| auth-related HTTP requests. | ||
| :py:class:`~pyquil.api.QuantumComputer` objects are safe to share between threads or processes, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you completely sure this is true? What about the statefulness of the underlying Most of these look to be set in the constructor and not mutated after, so they're probably OK, but might be worth another pass to see if any of these, and others, are at risk for data races.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great point - I had missed that. I've now removed that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Although, to add onto that, you bring up a good point - they're safe for use across threads, but that doesn't mean they're truly stateless and "safe" in every sense of the way that people can use them. It's really only that you can call their methods in different threads and expect it to work. So, to answer your question, it was my intent with this PR to make this true, but I am still not completely sure, given how Python works.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, while much of the state is set in the ctor and is OK in most cases, users could still choose to mutate them in threads, even if our APIs don't do that naturally. If we wanted true thread safety, we'd need to put every property behind getters and setters that can lock/unlock appropriately. Moreover, that only works for non-mutable types, like ints, strings, etc. If you had a mutable property that wasn't naturally thread-safe, locking around a getter/setter would do no good if the item itself is getting mutated unsafely (i.e. |
||
| enabling you to execute and retrieve results for multiple programs or parameter values at once. | ||
| Note that :py:class`~pyquil.Program` and :py:class`~pyquil.api.EncryptedProgram` are **not** | ||
| thread-safe, and should be copied (with ``copy()``) before use in a concurrent context. | ||
|
|
||
| .. note:: | ||
| The QVM processes incoming requests in parallel, while a QPU may process them sequentially or in parallel | ||
| (depending on the qubits used). If you encounter timeouts while trying to run large numbers of programs against a | ||
| QPU, try increasing the ``execution_timeout`` parameter on calls to :py:func:`~pyquil.get_qc()` (specified in | ||
| seconds). | ||
|
|
||
| .. note:: | ||
| We suggest running jobs with a minimum of 2x parallelism, so that the QVM or QPU | ||
| is fully occupied while your program runs and no time is wasted in between jobs. | ||
|
|
||
| Using Multithreading | ||
| -------------------- | ||
|
|
||
|
|
@@ -58,16 +58,14 @@ Using Multithreading | |
| from multiprocessing.pool import ThreadPool | ||
|
|
||
| from pyquil import get_qc, Program | ||
| from pyquil.api import EngagementManager, QCSClientConfiguration | ||
|
|
||
| from pyquil.api import QCSClientConfiguration | ||
|
|
||
| configuration = QCSClientConfiguration.load() | ||
| engagement_manager = EngagementManager(client_configuration=configuration) | ||
| qc = get_qc("Aspen-8", client_configuration=configuration) | ||
|
|
||
|
|
||
| def run(program: Program): | ||
| qc = get_qc("Aspen-8", client_configuration=configuration, engagement_manager=engagement_manager) | ||
| return qc.run(qc.compile(program)) | ||
| return qc.run(qc.compile(program)).readout_data.get("ro") | ||
|
|
||
|
|
||
| programs = [Program("DECLARE ro BIT", "RX(pi) 0", "MEASURE 0 ro").wrap_in_numshots_loop(10)] * 20 | ||
|
|
@@ -86,16 +84,15 @@ Using Multiprocessing | |
| from multiprocessing.pool import Pool | ||
|
|
||
| from pyquil import get_qc, Program | ||
| from pyquil.api import EngagementManager, QCSClientConfiguration | ||
| from pyquil.api import QCSClientConfiguration | ||
|
|
||
|
|
||
| configuration = QCSClientConfiguration.load() | ||
| engagement_manager = EngagementManager(client_configuration=configuration) | ||
| qc = get_qc("Aspen-8", client_configuration=configuration) | ||
|
|
||
|
|
||
| def run(program: Program): | ||
| qc = get_qc("Aspen-8", client_configuration=configuration, engagement_manager=engagement_manager) | ||
| return qc.run(qc.compile(program)) | ||
| return qc.run(qc.compile(program)).readout_data.get("ro") | ||
|
|
||
|
|
||
| programs = [Program("DECLARE ro BIT", "RX(pi) 0", "MEASURE 0 ro").wrap_in_numshots_loop(10)] * 20 | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.