Какие факторы определяют оптимальный аргумент chunksize для таких методов, как multiprocessing.Pool.map()? Метод .map() кажется, использует произвольную эвристику для размера по умолчанию (объяснено ниже); что мотивирует этот выбор и есть ли более продуманный подход, основанный на конкретной ситуации/настройке?
Пример - скажи, что я
- Передача
iterableв.map(), содержащего ~ 15 миллионов элементов; - Работа на машине с 24 ядрами и использование
processes = os.cpu_count()по умолчаниюprocesses = os.cpu_count()вmultiprocessing.Pool().
Мое наивное мышление состоит в том, чтобы дать каждому из 24 работников одинаковый размер, то есть 15_000_000/24 или 625 000. Большие куски должны уменьшить текучесть кадров/накладные расходы при полном использовании всех работников. Но, похоже, что в нем отсутствуют некоторые потенциальные недостатки предоставления больших партий каждому работнику. Это неполная картина, и что мне не хватает?
Часть моего вопроса проистекает из логики по умолчанию для if chunksize=None: оба .map() и .starmap() вызывают .map_async(), который выглядит следующим образом:
def _map_async(self, func, iterable, mapper, chunksize=None, callback=None,
error_callback=None):
# ... (materialize 'iterable' to list if it an iterator)
if chunksize is None:
chunksize, extra = divmod(len(iterable), len(self._pool) * 4) # ????
if extra:
chunksize += 1
if len(iterable) == 0:
chunksize = 0
Какая логика стоит за divmod(len(iterable), len(self._pool) * 4)? Это означает, что размер фрагмента будет ближе к 15_000_000/(24 * 4) == 156_250. Каково намерение умножить len(self._pool) на 4?
Это делает полученный размер фрагмента в 4 раза меньше, чем моя "наивная логика" сверху, которая состоит из простого деления длины итерируемого на количество работников в pool._pool.
Наконец, есть еще один фрагмент из документации Python по .imap() который еще больше .imap() мое любопытство:
Аргумент
chunksizeаргументом, используемым методомmap(). Для очень длинных итераций использование большого значения дляchunksizeможет сделать задание намного быстрее, чем использование значения по умолчанию 1.
Соответствующий ответ, который полезен, но слишком высокоуровневый: многопроцессорность Python: почему большие куски медленнее?,





















