2015-12-01 4 views
0

Я работаю над расширением python, которое выполняет некоторые специализированные древовидные структуры в большой (5GB +) структуре данных в памяти.Совместное использование распределенных распределенных структур данных в процессах python

Основная структура данных уже потокобезопасна (она использует блокировки RW), и я написал оболочку вокруг нее, которая предоставляет ее python. Он поддерживает несколько одновременных считывателей, только один писатель, и я использую pthread_rwlock для синхронизации доступа. Поскольку приложение очень читаемо, многие читатели должны обеспечить достойное повышение производительности (надеюсь).

Однако я не могу определить, какое правильное решение должно предоставить хранилище данных расширения для совместного доступа к нескольким процессам python, доступ к которым осуществляется через модуль multiprocessing.

В принципе, я хотел бы что-то похожее на текущую систему multiprocessing.Value/multiprocessing.Array, но здесь предостережение заключается в том, что мое расширение выделяет всю собственную память на C++.

Как разрешить нескольким процессам доступ к моей общей структуре данных?

Источники: here (библиотека только для чтения на С ++) и here (обертка Cython).

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

Traceback (most recent call last): 
    File "/usr/lib/python3.4/multiprocessing/queues.py", line 242, in _feed 
    obj = ForkingPickler.dumps(obj) 
    File "/usr/lib/python3.4/multiprocessing/reduction.py", line 50, in dumps 
    cls(buf, protocol).dump(obj) 
TypeError: cannot serialize '_io.TextIOWrapper' object 

(failing test-case)

Я в настоящее время выпуская GIL в моей библиотеке, но есть некоторые будущие задачи, которые в значительной степени выиграют от независимых процессов, и я бы хотел избежать использования RPC-системы для разговора с деревом BK.

+0

FYI, фактическая проблема заключается в том, что ваш класс, как представляется, включает в себя объект-файл, который не подбирается (пользовательское сопряжение '__reduce__' или' __getstate__'/'__setstate__' может использоваться для отправки только имени файла в его снова открыть с другой стороны). Тем не менее, даже если он был сорван, как только он был отправлен другому процессу, он потерял бы связь с объектом в первоначальном процессе; изменение одного не повлияет на другое, что, по-видимому, не является тем, что вам нужно. – ShadowRanger

+0

@ShadowRanger - У него нет файла нигде, посмотрите на источник. Я понятия не имею, что это такое. Может ли что-то обрабатывать мьютекс RW_lock как файл-подобный объект? –

+0

Похоже, что 'CPPBkHammingTree' имеет регистратор в качестве члена' self.log'. Будет ли задействовано его прикрепление к 'stdout' или файлу, будет задействована текстовая оболочка (для преобразования из Unicode в собственные байты кодирования). Это вероятная причина проблем. – ShadowRanger

ответ

1

Если данные расширения будут существовать как один логически изменяемый объект для нескольких процессов (так что изменение процесса A будет отражено в представлении в процессе B), вы не можете избежать какого-либо механизма IPC. Пространства памяти двух процессов разделены; Python не может волшебным образом делиться нераскрытыми данными.

Ближе всего вы можете получить (без явного использования разделяемой памяти на уровне С, который можно было бы использовать для сопоставления одной и той же памяти в каждом процессе) было бы использование пользовательского подкласса multiprocessing.BaseManager, который просто скроет IPC от вы (фактический объект будет жить в одном процессе, с другими процессами, проксимирующими этот оригинальный объект). Вы можете увидеть a really simple example in the multiprocessing docs.

Менеджмент подход прост, но с точки зрения производительности он, вероятно, не будет делать так жарко; разделяемая память на слое C позволяет избежать множества накладных расходов, которых механизм проксирования не может избежать. Тебе нужно проверить, чтобы что-то проверить. Полагаю, что использование C++ STL для совместной работы с памятью было бы королевской болью, что, вероятно, не стоит проблем, поэтому, если подход менеджера не слишком медленный, я бы даже не попытался оптимизировать.

+0

Я не знал, что совместное использование объектов STL (из чего состоит все дерево) было настолько хлопотно. Это раздражает. Наверное, я просто использую потоки и питаюсь раздражением, чтобы работать с GIL в вызовах, не связанных с библиотекой. –

+0

Если вы хотите попробовать использовать общую память STL, я бы предложил взглянуть на [эту статью] (http://www.drdobbs.com/creating-stl-containers-in-shared-memory/184401639). Охватывает основы. – ShadowRanger

Смежные вопросы