forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bpo-29842: Introduce a prefetch parameter to Executor.map to handle l…
…arge iterators
- Loading branch information
Showing
4 changed files
with
53 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
__author__ = 'Brian Quinlan ([email protected])' | ||
|
||
import collections | ||
import itertools | ||
import logging | ||
import threading | ||
import time | ||
|
@@ -580,7 +581,7 @@ def submit(self, fn, /, *args, **kwargs): | |
""" | ||
raise NotImplementedError() | ||
|
||
def map(self, fn, *iterables, timeout=None, chunksize=1): | ||
def map(self, fn, *iterables, timeout=None, chunksize=1, prefetch=None): | ||
"""Returns an iterator equivalent to map(fn, iter). | ||
Args: | ||
|
@@ -592,6 +593,8 @@ def map(self, fn, *iterables, timeout=None, chunksize=1): | |
before being passed to a child process. This argument is only | ||
used by ProcessPoolExecutor; it is ignored by | ||
ThreadPoolExecutor. | ||
prefetch: The number of chunks to queue beyond the number of | ||
workers on the executor. If None, all chunks are queued. | ||
Returns: | ||
An iterator equivalent to: map(func, *iterables) but the calls may | ||
|
@@ -604,25 +607,42 @@ def map(self, fn, *iterables, timeout=None, chunksize=1): | |
""" | ||
if timeout is not None: | ||
end_time = timeout + time.monotonic() | ||
if prefetch is not None and prefetch < 0: | ||
raise ValueError("prefetch count may not be negative") | ||
|
||
fs = [self.submit(fn, *args) for args in zip(*iterables)] | ||
all_args = zip(*iterables) | ||
if prefetch is None: | ||
fs = collections.deque(self.submit(fn, *args) for args in all_args) | ||
else: | ||
fs = collections.deque() | ||
for idx, args in enumerate(all_args): | ||
if idx >= self._max_workers + prefetch: | ||
break | ||
fs.append(self.submit(fn, *args)) | ||
|
||
# Yield must be hidden in closure so that the futures are submitted | ||
# before the first iterator value is required. | ||
def result_iterator(): | ||
def result_iterator(all_args=None): | ||
try: | ||
# reverse to keep finishing order | ||
fs.reverse() | ||
while fs: | ||
# Careful not to keep a reference to the popped future | ||
if timeout is None: | ||
yield _result_or_cancel(fs.pop()) | ||
yield _result_or_cancel(fs.popleft()) | ||
else: | ||
yield _result_or_cancel(fs.pop(), end_time - time.monotonic()) | ||
yield _result_or_cancel(fs.popleft(), end_time - time.monotonic()) | ||
|
||
# Submit the next task | ||
if all_args: | ||
try: | ||
args = next(all_args) | ||
except StopIteration: | ||
all_args = None | ||
else: | ||
fs.append(self.submit(fn, *args)) | ||
finally: | ||
for future in fs: | ||
future.cancel() | ||
return result_iterator() | ||
return result_iterator(all_args) | ||
|
||
def shutdown(self, wait=True, *, cancel_futures=False): | ||
"""Clean-up the resources associated with the Executor. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters