[Async-sig] async executors

Christoph Groth christoph at grothesque.org
Mon Jun 6 08:38:19 EDT 2016


Hi,

A few days ago I posted a message [1] on python-ideas to which no 
one replied except Brett who suggested re-posting it here, which I 
do now.  The following is a complete rewrite/update of the 
original message.  I promise: I will stop the spamming if no one 
replies this time!

Async programming with executors seems to be a useful approach for 
number-crunching problems where the main algorithm (the one 
launching the futures) is quite complicated and possibly 
concurrent, but light enough to run on a single core (the heavy 
lifting is done “inside” the futures).

This use case is addressed by asyncio's run_in_executor that uses 
the executors provided by the concurrent.futures package.  There 
is, however, a lot of duplication of functionality between 
concurrent.futures and asyncio.  (The main difference is that 
concurrent.futures relies on threading and locks.)  If one is 
going to use concurrent.futures only from coroutines that run 
under the control of the asyncio event loop, it should be possible 
to replace the concurrent.futures executors by async versions of 
them.

Why could such an async executor be interesting?

• It can be a lot simpler (and thus easier to understand and 
  extend) because it builds on top of asyncio.  There have been 
  already discussions on unifying the Future type from 
  concurrent.futures with that of asyncio [2].

• Performance is better, especially when many worker processes are 
  involved, because of the simpler code that uses less locking 
  (the only locking that remains is inside the multiprocessing 
  module).

As far as I can see the original 
concurrent.futures.ProcessPoolExecutor has no advantage when used 
in asyncio-based programs except when some coroutine blocks for 
long enough for the call queue to become empty.  (But hey, async 
programming is about non-blocking coroutines!)

Are there other possible advantages or disadvantages?

Based on concurrent.futures.ProcessPoolExecutor, I’ve made a 
proof-of-concept implementation [3] that demonstrates that the 
idea works.  (There have been some improvements compared to the 
version that I posted on python-ideas.)

Christoph


PS.

I would be grateful if any asyncio experts could have a look at 
the part of the main loop of the process management coroutine 
where the coroutine awaits new data [4].  Currently, I am using an 
asyncio.Event that is set by a callback via asyncio’s 
add_reader().  Is this the most natural way to do it currently? 
I’m particularly puzzled by the fact that reader.poll(0) is not 
always true after the event has been set.

If there is no better way to combine asyncio and 
multiprocessing.Process, perhaps this is a thing that could be 
improved in a future version of the Python stdlib?


[1] http://thread.gmane.org/gmane.comp.python.ideas/40709
[2] 
http://thread.gmane.org/gmane.comp.python.ideas/24551/focus=24557
[3] https://gitlab.kwant-project.org/cwg/aexecutor
[4] 
https://gitlab.kwant-project.org/cwg/aexecutor/blob/9290504e779c543d9ee93adcb1de36390a69eaad/aexecutor/process.py#L298
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/async-sig/attachments/20160606/5e88d6b4/attachment-0001.sig>


More information about the Async-sig mailing list