Разделение состояния между разветвленными рабочими процессами в высокопроизводительной среде

Это продолжение моего предыдущего вопроса . Как предложил Тим Петерс, использование Manager не всегда может быть лучшим подходом. К сожалению, у меня слишком много кода для создания SSCCE . Вместо этого я попытаюсь дать подробное объяснение моей проблемы. Пожалуйста, не стесняйтесь просматривать всю базу кода на Github , но сейчас это немного беспорядок.

Задний план

Я занимаюсь исследованиями в области обработки естественного языка, и я хотел бы сделать (что-то вроде) сглаживание на основе словаря для классификации документов. Идея обучения классификатора для правильного ответа слов и фраз. Например, документы, содержащие слово « socialist , скорее всего, касаются политики, а те, которые содержат фразу « lava temperature , скорее всего, связаны с геологией. Система подготовлена, просмотрев небольшое количество предварительно помеченных примеров. Поскольку язык настолько разнообразен, классификатор никогда не будет «знать» все возможные фразы, которые он может встретить в процессе производства.

  • Есть ли хороший и простой способ визуализации высокоразмерных данных?
  • Различие XGBoost в тренировочных и тестовых функциях после преобразования в DMatrix
  • Как прогнозировать временные ряды в scikit-learn?
  • градиентный спуск с использованием python и numpy
  • НОМЕР 1-hot массив
  • Проблемы, связанные с получением большинства информационных функций с помощью scikit?
  • Это то место, где приходит словарь. Предположим, у нас был дешевый и простой способ получить синонимы практически для любой фразы (я приведу сам, потому что это плохой вкус). Когда плохой классификатор сталкивается с фразой, о которой он не знает, мы могли бы найти его в указанном словаре и рассказать классификатору «Послушай, ты не знаешь о communism , но он вроде как socialist , и ты об этом знаешь! ». Если словарь является разумным, классификатор, как правило, будет работать лучше.

    Псевдокод

     data = Load training and testing documents (300MB on disk) dictionary = Load dictionary (200MB - 2GB on disk) and place into a `dict` for fast look-ups Repeat 25 times: do_work(data, dictionary) def do_work(data, dictionary) X = Select a random sample of data Train a classifier on X Y = Select a random sample of data Using dictionary, classify all documents in Y Write results to disk 

    Проблема

    Петля выше – идеальный кандидат для параллелизации. Я использую multiprocessing.Pool систему Python joblib.Parallel (через joblib.Parallel , потому что это легко и обеспечивает очень полезную трассировку, если все идет на юг). Все рабочие процессы требуют доступа только для чтения к словарю и коллекции документов. Сотрудникам не нужно общаться друг с другом или с родительским процессом – все, что они делают, порождается, совершает магию, записывает файл и умирает.

    Словарь должен поддерживать быстрый произвольный доступ. Я не знаю, какие документы будет содержать образец Y , поэтому я не могу легко подрезать словарь и передавать только ту часть, которая необходима каждому работнику. Словарь будет запрашиваться очень часто – типичные числа хитов за прогон составляют миллионы. В настоящее время мой код связан с памятью, поскольку (я считаю) копии коллекций документов и словаря создаются для каждого рабочего процесса. Когда анализируемые data и dictionary обычно используют несколько ГБ ОЗУ. Я попытался использовать multiprocessing.managers.BaseManager чтобы избежать копирования больших объектов, но это замедлило работу рабочих.

    Вопрос

    Какие еще существуют альтернативы для ускорения? Вещи, о которых я думал, включают:

    • MongoDB / CouchDB / memcached должен работать с одновременным доступом, но я беспокоюсь о пропускной способности. zeromq также был предложен в комментарии к моему предыдущему вопросу, не имел возможности заглянуть в него.
    • базы данных sqlite базе данных и соединения с базой данных не могут быть разделены между процессами, поэтому каждому работнику потребуется собственное подключение к базе данных на диске. Это означает, что во время ввода-вывода и использования большой памяти увеличивается количество операций ввода-вывода, поскольку кэш каждого рабочего растет.
    • отображение памяти
    • использование потоков вместо процессов

    Этот вопрос SO также предположил, что многие проблемы реального мира, которые выглядят так, как будто они нуждаются в доступе только для чтения к dict могут вызывать fork() 'copy-on-write', поэтому совершенно невозможно избежать копирования больших объектов.

  • Объединение пользовательских функций с помощью CountVectorizer
  • Как обрабатывать недостающие NaN для машинного обучения в python
  • Предсказание: прогнозирование будущих событий с использованием модуля SVR
  • Как я могу уменьшить использование памяти Scikit-Learn Vectorizers?
  • SKLearn, как получить вероятностные решения для классификатора LinearSVC
  • Как вычислить точность, отзыв, точность и f1-score для многоклассового футляра с помощью scikit?
  • One Solution collect form web for “Разделение состояния между разветвленными рабочими процессами в высокопроизводительной среде”

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

    Мне не нравится это говорить, но использование решения, отличного от Python (например, на C ++), может ускорить работу, потому что у вас нет проблемы с GIL. Затем вы можете использовать многопоточность, не нужно копировать вещи и т. Д. Чтение из большого словаря из нескольких потоков на самом деле не является проблемой, поэтому вам не нужно синхронизировать что-либо (что бы GIL всегда делал для вас без реальная потребность).

    Python - лучший язык программирования в мире.