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
reduce multiprocessing.Queue contention #61227
Comments
Here's an implementation of the idea posted on python-ideas (http://mail.python.org/pipermail/python-ideas/2013-January/018846.html). The principle is really simple, we just serialize/unserialize the objects before/after holding the locks. This leads to reduced contention. Here are the results of a benchmark using from 1 reader/1 writer up to 4 readers/4 writers, on a 8-cores box: without patch: with patch:
$ ./python /tmp/multi_queue.py
took 0.7945001125335693 seconds with 1 workers
took 0.7428359985351562 seconds with 2 workers
took 0.7897098064422607 seconds with 3 workers
took 1.1860828399658203 seconds with 4 workers I tried Richard's suggestion of serializing the data inside put(), but this reduces performance quite notably: Although I didn't analyse it further, I guess one reason could be that if the serializing is done in put(), the feeder thread has nothing to do but keep waiting for data to be available from the buffer, send it, and block until there's more to do: basically, it almost doesn't use its time-slice, and spends its time blocking and doing context switches. |
I would like to suggest again my idea of doing it in Connection instead, |
I intended to do this initially, but then it turned out to be much While it's probably a good idea to implement it in Connection, I don't
So basically, I think the right way to do it would be to define an |
For the record, I tried the Connection approach and here is what I ended up with. |
I don't really like the API. |
So, what do you think? I find the performance gain quite appreciable (basically queue didn't |
IMHO the simple version is good enough. |
It looks like queues_contention.diff has the line obj = pickle.dumps(obj) in both _feed() and put(). Might that be why the third set of benchmarks was slower than the second? |
_feed() is a Queue method, put() its SimpleQueue() counterpart. Am I |
On 04/03/2013 8:01pm, Charles-François Natali wrote:
No. I only looked at the diff and assumed both changes were for Queue. Since you marked bpo-10886 as superceded, do you intend to do the |
OK, great.
Actually no, I'll reopen it. |
By the way, I forgot to mention it previously, but multiprocessing.connection uses a custom pickler (ForkingPickler). By replacing it with plain pickle.dumps() calls, you may produce regressions since some types won't be sendable anymore (although the test suite might not check for this). |
Thanks, I didn't know. I did a bit of refactoring to move the pickling code from |
I'm splitting the patches:
I'd like to commit them soon. |
The old code deleted the obj in the feeder thread as soon as it was sent at lines 247 and 253 -- see Issue bpo-16284. I think that should be retained. Apart from that LGTM. |
The object is overwritten by the pickled data, so it's not necessary |
On 24/03/2013 12:16pm, Charles-François Natali wrote:
Yes, you are right. |
New changeset bedb4cbdd311 by Charles-François Natali in branch 'default': |
New changeset 5022ee7e13a2 by Charles-François Natali in branch 'default': |
Committed, thanks! |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: