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

Common API: Concurrency / async calls #7

Open
campagnola opened this issue Jan 27, 2020 · 9 comments
Open

Common API: Concurrency / async calls #7

campagnola opened this issue Jan 27, 2020 · 9 comments

Comments

@campagnola
Copy link
Contributor

How should we handle concurrency and asynchronous operation in a common API? Specifically:

(1) Should method calls be thread-safe? Pro: it is often much easier to implement thread safety at a low level when interacting with the device, rather than as an afterthought in a higher layer. Con: implementing thread safety correctly can be a challenge, makes the code more complex, could impact performance if done incorrectly, etc.

(2) Should method calls return futures? (all method calls, or just ones that are more likely to take a long time?) Pro: can make the common API much easier to use. Especially true for systems that need to coordinate action between multiple devices, and even more if you want to do that over IPC. Con: more work to write, more complex code.

@HazenBabcock
Copy link
Contributor

Would this mean we have to make a choice about what particular libraries would be used? Threads for example are implemented in multiple different ways and it isn't clear that they all play nicely. For example will Python's threading library work with in the same process as PyQt threads?

@campagnola
Copy link
Contributor Author

If we want to implement thread safety, I would be more inclined to use Python's threading module (I can't think of a good reason for hardware control to depend on Qt at all). This is totally compatible with Qt's threads, though (and should be compatible with any other threads, as far as I know).

@HazenBabcock
Copy link
Contributor

If you wrote the GUI in PyQt then it might seem like a good reason, which isn't to say that it is a good reason.

@HazenBabcock
Copy link
Contributor

Perhaps the choice of which threads library to use could be left to the end user? So rather than directly using threading for example we'd call it indirectly through an intermediary, which should let the user could specify which thread library they wanted to use. This assumes that the different implementations of the threads all work basically the same, or similar enough that their differences could be abstracted out.

@campagnola
Copy link
Contributor Author

I can think of good reasons to use a threading intermediary (in acq4, for example, I use a custom mutex class for debugging deadlocks). However I think thread safety should be an internal implementation detail; I can't think of a reason that they should care how that works under the hood.

@edbarnard
Copy link
Contributor

My experience with Qt threads and python threading threads seem to work together without a problem. Thus using the threading Locks might be a good base

@campagnola
Copy link
Contributor Author

I'd like to point at Lantz as an interesting example of building in asynchronous device calls: https://lantz.readthedocs.io/en/0.3/overview.html#effortless-asynchronous-get-and-set

One immediate benefit is that you can squeeze more performance out of situations where you have multiple ongoing and interdependent device tasks. Another benefit is that an asynchronous API lends itself much more easily to multiprocessing--ideally you can call the same method on either a local device object or a proxy to a remote device object and expect the same behavior. That said, it might be better to keep the low-level drivers as simple as possible and implement async calls at a higher level.

@bilderbuchi
Copy link

bilderbuchi commented May 2, 2020

👍 to Lantz's approach using concurrent futures, from some previous high-level reading that approach is also what I would try to use first, as it seems most elegant/simple to use.

@aquilesC
Copy link

aquilesC commented May 3, 2020

Violating any kind of lean approach to problem solving, I, personally, would go one step further and think about multi-processing safety. If you are acquiring at high-framerates (GigE cameras, for example), threads are going to become a bottleneck very soon. I wouldn't rely on Qt for this, since it is a complex machinery that data acquisition does not need per-se, and would keep Qt just at the highest level, for building a GUI.

Since drivers are sometimes already given, I build a model on them, the model is multi-processing safe, and the methods are thread-safe within that process. I use ZMQ to broadcast information in/out of the encapsulated models. The advantage is that I foresee a future where I can have a daemonic experiment running, and control it from a Jupyter notebook, another programming language, or, why not, another computer, through the network.

PS: Now that I think about this out loud, the concurrent futures would be a nice way of simplifying my job...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants