_multiprocessing.SemLock не реализован при работе на AWS Lambda

У меня есть короткий код, который использует пакет multiprocessing и отлично работает на моем локальном компьютере.

Когда я загрузился в AWS Lambda и запустил там, я получил следующую ошибку (stacktrace trimmed):

[Errno 38] Function not implemented: OSError
Traceback (most recent call last):
  File "/var/task/recorder.py", line 41, in record
    pool = multiprocessing.Pool(10)
  File "/usr/lib64/python2.7/multiprocessing/__init__.py", line 232, in Pool
    return Pool(processes, initializer, initargs, maxtasksperchild)
  File "/usr/lib64/python2.7/multiprocessing/pool.py", line 138, in __init__
    self._setup_queues()
  File "/usr/lib64/python2.7/multiprocessing/pool.py", line 234, in _setup_queues
    self._inqueue = SimpleQueue()
  File "/usr/lib64/python2.7/multiprocessing/queues.py", line 354, in __init__
    self._rlock = Lock()
  File "/usr/lib64/python2.7/multiprocessing/synchronize.py", line 147, in __init__
    SemLock.__init__(self, SEMAPHORE, 1, 1)
  File "/usr/lib64/python2.7/multiprocessing/synchronize.py", line 75, in __init__
    sl = self._semlock = _multiprocessing.SemLock(kind, value, maxvalue)
OSError: [Errno 38] Function not implemented

Может ли быть, что часть базовых пакетов python не реализована? Я понятия не имею, что я запускаю под ним, поэтому я не могу войти туда и отлаживать.

Любые идеи, как я могу запустить multiprocessing на Lambda?

Ответ 1

Насколько я могу судить, многопроцессорная обработка не будет работать в AWS Lambda, поскольку отсутствует среда выполнения/контейнер /dev/shm - см. Https://forums.aws.amazon.com/thread.jspa?threadID=219962 (вход в систему). может потребоваться).

Нет слов (которые я могу найти), если/когда Amazon изменит это. Я также посмотрел на другие библиотеки, например, https://pythonhosted.org/joblib/parallel.html откатится на /tmp (который, как мы знаем, существует), если он не может найти /dev/shm, но на самом деле это не решает проблема.

Ответ 2

Вы можете запускать подпрограммы параллельно на AWS Lambda с помощью модуля многопроцессорной обработки Python, но вы не можете использовать пулы или очереди, как отмечено в других ответах. Реальным решением является использование Process и Pipe, как описано в этой статье https://aws.amazon.com/blogs/compute/parallel-processing-in-python-with-aws-lambda/

Несмотря на то, что статья определенно помогла мне найти решение (см. Ниже), есть несколько вещей, о которых нужно знать. Во-первых, решение, основанное на процессах и каналах, не такое быстрое, как встроенная функция отображения в пуле, хотя я видел почти линейное ускорение при увеличении доступных ресурсов памяти/ЦП в своей функции Lambda. Во-вторых, при разработке многопроцессорных функций таким образом требуется немало управления. Я подозреваю, что это, по крайней мере, частично, почему мое решение медленнее, чем встроенные методы. Если у кого-то есть предложения по его ускорению, я бы хотел их услышать! Наконец, хотя в статье отмечается, что многопроцессорность полезна для разгрузки асинхронных процессов, есть и другие причины для использования многопроцессорности, такие как много интенсивных математических операций, что я и пытался сделать. В итоге я был достаточно доволен улучшением производительности, так как оно было намного лучше, чем последовательное выполнение!

Код:

# Python 3.6
from multiprocessing import Pipe, Process

def myWorkFunc(data, connection):
    result = None

    # Do some work and store it in result

    if result:
        connection.send([result])
    else:
        connection.send([None])


def myPipedMultiProcessFunc():

    # Get number of available logical cores
    plimit = multiprocessing.cpu_count()

    # Setup management variables
    results = []
    parent_conns = []
    processes = []
    pcount = 0
    pactive = []
    i = 0

    for data in iterable:
        # Create the pipe for parent-child process communication
        parent_conn, child_conn = Pipe()
        # create the process, pass data to be operated on and connection
        process = Process(target=myWorkFunc, args=(data, child_conn,))
        parent_conns.append(parent_conn)
        process.start()
        pcount += 1

        if pcount == plimit: # There is not currently room for another process
            # Wait until there are results in the Pipes
            finishedConns = multiprocessing.connection.wait(parent_conns)
            # Collect the results and remove the connection as processing
            # the connection again will lead to errors
            for conn in finishedConns:
                results.append(conn.recv()[0])
                parent_conns.remove(conn)
                # Decrement pcount so we can add a new process
                pcount -= 1

    # Ensure all remaining active processes have their results collected
    for conn in parent_conns:
        results.append(conn.recv()[0])
        conn.close()

    # Process results as needed

Ответ 3

multiprocessing.Pool, как представляется, не поддерживается изначально (из-за проблемы с SemLock), но multiprocessing.Process, multiprocessing.Queue, multiprocessing.Pipe и т.д. корректно работают в AWSLambda.

Это позволит вам создать обходное решение путем ручного создания/форматирования процессов и использования multiprocessing.Pipe для связи между родительским и дочерним процессами. Надеюсь, что поможет