У меня есть список примерно из 800000 элементов (небольших строк), которые загружаются в очередь, которая затем используется различными рабочими процессами из многопроцессорного пула. Я обнаружил, что как в PyPy, так и в Python (2.7 и 3.6 соответственно), хотя я явно установил максимальный размер очереди равным 0, очередь в обоих случаях ограничена 32768 элементами в любой момент времени и, следовательно, блокирует на 32768 элементе.
Почему это происходит? Я думал, что они должны быть бесконечными, если maxsize <= 0? Я рассмотрел этот вопрос StackOverflow Python Queue поднимает Full, даже если он бесконечен, но он единственный такого рода. Есть ли что-то еще, что я могу упустить?
Я пробовал реализации многопроцессорной очереди, где я загружаю миллион целых чисел, а метод queue.put(val) всегда блокируется на 32768-м значении.
from multiprocessing import Queue
q = Queue(maxsize=0)
for i in range(int(1e7)):
q.put(i)
print(i)
Я ожидал, что смогу вставить в очередь все 1 миллион целых чисел, но, как оказалось, она не может удержать их все, так как блокирует 32768-е целое число. Я хотел бы пролить свет на особенности того, почему это может происходить, на что, возможно, уже был дан ответ в другом вопросе StackOverflow, указанном выше, но похоже, что пользователь, давший ответ, спросил, используем ли мы 32-битный Дистрибутив Python, который не является моим случаем, так как я использую 64-битный дистрибутив Python в обоих случаях, как видно здесь (для PyPy с 2.7.13, который я использую в своем проекте):
Python 2.7.13 (990cef41fe11, Mar 21 2019, 12:15:10)
[PyPy 7.1.0 with GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>> import sys;print("%x" % sys.maxsize, sys.maxsize > 2**32)
('7fffffffffffffff', True)
ОБНОВИТЬ:
Я заметил кое-что очень интересное. Это произошло при запуске Queue в MacOS, но я запустил код в контейнере докеров с Linux, и очередь была эффективно загружена полностью со всеми 800000 элементами одновременно! Кажется, это как-то связано с MacOS.
Многопроцессорность Зависание очереди означает, что вы, скорее всего, превысили максимальное количество семафоров; то есть OSX не может считать так много и неявно ограничивает вас до 2 ^ 15 - 1.
Я не уверен, насколько надежен / актуален источник, но он соответствует, по-видимому, максимальному значению для osx (https://github.com/st3fan/osx-10.9/blob/master/xnu-2422.1.72/bsd/sys/semaphore.h)
Редактировать/проверить:
Явная попытка использовать большее ограничение, чем 2 ^ 15 - 1, терпит неудачу:
>>> Queue(maxsize=2**15)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/context.py", line 102, in Queue
return Queue(maxsize, ctx=self.get_context())
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/queues.py", line 48, in __init__
self._sem = ctx.BoundedSemaphore(maxsize)
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/context.py", line 87, in BoundedSemaphore
return BoundedSemaphore(value, ctx=self.get_context())
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/synchronize.py", line 145, in __init__
SemLock.__init__(self, SEMAPHORE, value, value, ctx=ctx)
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/synchronize.py", line 59, in __init__
unlink_now)
OSError: [Errno 22] Invalid argument
В вашем случае вы пытались неявно создать очередь бесконечного размера (<=0), однако на самом деле это не так, и применяются ограничения OSX: https://github.com/python/cpython/blob/master/Lib/multiprocessing/queues.py#L37
Я предполагаю, что предел Linux просто выше, что имеет смысл, поскольку предел OSX кажется очень низким. И нет, у вас есть только один семафор для всей очереди, однако он не может считать более 2 ^ 15 - 1 из-за ограничения OSX, поэтому он заблокирован до этого размера. вы можете увидеть это здесь: github.com/python/cpython/blob/master/Lib/multiprocessing/…
Это имеет большой смысл, Леон, большое спасибо за разъяснение.
То, чем вы делитесь, имеет большой смысл, но как это применимо к Linux? Кажется, нет проблем с загрузкой всех значений в очередь. Более того, означает ли это, что у каждого элемента в очереди есть семафор?