Nano Hash - криптовалюты, майнинг, программирование

Многопроцессорность в Python с общей памятью только для чтения?

У меня есть однопоточная программа Python, и я хотел бы изменить ее, чтобы использовать все 32 процессора на сервере, на котором она работает. Как я себе это представляю, каждый рабочий процесс будет получать задание из очереди и отправлять свои выходные данные в очередь. Однако для завершения своей работы каждому рабочему процессу потребуется доступ только для чтения к сложной структуре данных в памяти — многим гигабайтам словарей и объектов, которые связаны друг с другом. Есть ли в python простой способ поделиться этой структурой данных, не создавая ее копию для каждого рабочего процесса?

Спасибо.


  • Вы используете реализацию Python на CPython? 14.10.2013
  • Да, сейчас я использую CPython, работающий под Linux. Я имел в виду использование многопроцессорного модуля. 14.10.2013

Ответы:


1

Если вы используете реализацию Python CPython (или PyPy), то глобальная блокировка интерпретатора (GIL) предотвратит одновременную работу с объектами Python более чем одного потока.

Поэтому, если вы используете такую ​​реализацию, вам нужно будет использовать несколько процессов вместо нескольких потоков, чтобы воспользоваться преимуществами ваших 32 процессоров.

Вы можете использовать стандартную библиотеку многопроцессорность или concurrent.futures для порождения рабочих процессов. Существует также множество сторонних опций. Руководство Дуга Хеллмана — отличное введение в модуль многопроцессорной обработки.

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

Когда вы порождаете процесс, глобальные переменные из вызывающего модуля копируются в порожденный процесс. Однако в Linux с копированием при записи та же самая структура данных используется порожденными процессами, поэтому дополнительная память не требуется. Только когда процесс изменяет структуру данных, он копируется в новое место.

В Windows, поскольку нет fork, каждый порожденный процесс вызывает python и повторно импортирует вызывающий модуль, поэтому каждому процессу требуется память для своей отдельной копии огромной структуры данных. Должен быть какой-то другой способ обмена структурами данных в Windows, но я не знаю подробностей. (Правка: POSH может быть решением проблемы с общей памятью, но я сам не пробовал.)

14.10.2013
  • Это здорово, так как я использую Linux. Прочитав документацию по пакету multiprocessing, я подумал, что мне нужно использовать multiprocessing.Value или multiprocessing.Array для совместного использования памяти. Но из ваших комментариев кажется, что это необходимо только в том случае, если я хочу писать в общую память. Это правильно? 14.10.2013
  • @Джефф: Верно. Здесь есть некоторый код, который демонстрирует, что с помощью копирования при записи большие объекты могут использоваться совместно только для чтения не требуя дополнительной памяти. 14.10.2013
  • Как насчет проблемы, описанной здесь: llvllatrix.wordpress. com/2016/02/19/python-vs-copy-on-write 20.10.2020

  • 2

    Чтобы добавить демонстрацию ответа unutbu выше, вот код, показывающий, что на самом деле это общая память COW (CPython 3.6, Mac OS)

    main_shared.py

    import multiprocessing
    from time import sleep
    
    
    my_global = None
    
    
    def test():
        global my_global
        read_only_secs = 3
        while read_only_secs > 0:
            sleep(1)
            print(f'child proc global: {my_global} at {hex(id(my_global))}')
            read_only_secs -= 1
        print('child proc writing to copy-on-write...')
        my_global = 'something else'
        while True:
            sleep(1)
            print(f'child proc global: {my_global} at {hex(id(my_global))}')
    
    
    def set_func():
        global my_global
        my_global = [{'hi': 1, 'bye': 'foo'}]
    
    if __name__ == "__main__":
        print(f'main proc global: {my_global} at {hex(id(my_global))}')
        set_func()
        print(f'main proc global: {my_global} at {hex(id(my_global))}')
        p1 = multiprocessing.Process(target=test)
        p1.start()
    
        while True:
            sleep(1)
            print(f'main proc global: {my_global} at {hex(id(my_global))}')
    

    Вывод

    $ python main_shared.py 
    main proc global: None at 0x101b509f8
    main proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    child proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    main proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    child proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    main proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    child proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    child proc writing to copy-on-write...
    main proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    child proc global: something else at 0x1022ea3b0
    main proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    child proc global: something else at 0x1022ea3b0
    main proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    child proc global: something else at 0x1022ea3b0
    main proc global: [{'hi': 1, 'bye': 'foo'}] at 0x102341708
    
    22.02.2020
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..