Как сохранить объект KeyedVectors от gensim в глобальной переменной внутри работника Redis Queue - PullRequest
0 голосов
/ 11 ноября 2019

Я пытаюсь сохранить данные в глобальной переменной внутри работника Redis Queue (RQ), чтобы эти данные оставались предварительно загруженными, то есть их не нужно загружать для каждого задания RQ.

В частности, я работаю с векторами Word2Vec и загружаю их, используя KeyedVectors от gensim.

Мое приложение в Python Flask, работает на сервере Linux, в контейнере использует Docker.

Моя цель состоит в том, чтобысократить время обработки, постоянно сохраняя в памяти несколько файлов больших векторов.

Сначала я попытался сохранить их в глобальных переменных во Flask, но затем каждый из 8 моих рабочих-оружейников загружает векторы, что поглощает много оперативной памяти.

IДля хранения определенного файла векторов нужен один рабочий.

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

Вот что у меня есть:

RQ_worker.py

from rq import Worker, Connection
from gensim.models.keyedvectors import KeyedVectors
from my_common_methods import get_redis

W2V = KeyedVectors.load_word2vec_format('some_path/vectors.bin', binary=True)

def rq_task(some_args):
    # use some_args and W2V to do some processing, e.g.:
    with open(some_args_filename, 'w') as f_out:
        f_out.write(str(W2V['word']))

if __name__ == '__main__':
    with Connection(get_redis()):
        worker = Worker(['default'])
        worker.work()

app.py

from rq import Queue, Connection
from RQ_worker import rq_task

@app.route("/someroute", methods=['POST'])
def some_route():
    # test Redis Queue
    with Connection(get_redis()):
        q = Queue()
        task = q.enqueue(rq_task, some_args)

docker-stack.yml

version: '3.7'

services:
  nginx:
    image: nginx:mainline-alpine
    deploy: ...
    configs: ...
    networks: ...

  flask:
    image: ...
    deploy: ...
    environment: ...
    networks: ...
    volumes: ...

  worker:
    image: ...
    command: python2.7 RQ_worker.py
    deploy:
      replicas: 1
    networks: ...
    volumes:
      - /some_path/data:/some_path/data

configs:
  nginx.conf:
    external: true
    name: nginx.conf

networks:
  external:
    external: true
  database:
    external: true

(я отредактировал кучу вещей из Docker, но могупредоставьте более подробную информацию, если это уместно.)

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

Я что-то упустил? Должен ли я настроить его по-другому?

Мне сказали, что, возможно, можно использовать mmap для загрузки файла векторов в глобальную переменную, в которой находится RQ-работник, но я не уверен, как это будет работать с KeyedVectors.

Любой совет будет высоко ценится!

1 Ответ

0 голосов
/ 11 ноября 2019

Если вы используете load_word2vec_format(), код всегда будет анализировать формат слов (не родной для gensim-или-Python) и выделять новые объекты / память для хранения результатов.

Вместо этого вы можете использовать нативный .save() gensim для хранения в более удобном формате для последующих нативных .load() операций. Большие массивы векторов будут храниться в отдельных готовых файлах карты памяти. Затем, когда вы .load(..., mmap='r') эти файлы, даже несколько раз из разных потоков или процессов в одном и том же контейнере, они будут использовать одну и ту же оперативную память.

(Обратите внимание, что для этого даже не требуются общие глобальные переменные. ОС заметит, что каждый процесс запрашивает один и тот же файл, отображаемый только для чтения, и автоматически предоставит доступ к этим страницам ОЗУ. Единственное дублирование будетизбыточный Python dict, помогающий каждому отдельному .load() знать индексы в разделяемом массиве.)

При выполнении операций подобия над векторами, которые модель будет хотеть неоднократно объединять, необходимо учитывать некоторые дополнительные складки. норма - см. этот старый ответ для получения дополнительной информации о том, как обойти это:

Как ускорить время загрузки модели Gensim Word2vec?

(Обратите внимание, что syn0 и syn0_norm были переименованы в vectors и vectors_norm в более поздних gensim версиях, но старые имена еще могут работать с предупреждениями об устаревании еще некоторое время.)

...