Python runtime: перекомпиляция и повторное использование библиотеки C - PullRequest
3 голосов
/ 16 июля 2011

Я разрабатываю инструмент для некоторого численного анализа пользовательских функций.Идея состоит в том, чтобы создать удобный пользовательский интерфейс в Python, где пользователь может войти в функцию C, затем нажать кнопку - и получить некоторые выходные данные.Вычисления могут занимать минуты или часы, поэтому производительность только в Numpy неприемлема.

Я попробовал следующий подход: пользовательский интерфейс на основе Python вызывает gcc, компилирует dll из пользовательских функций, которые используются моим ядром Cалгоритмы в обертках Cython.Это работает, но, поскольку полностью выгрузить модуль python невозможно, я не могу перекомпилировать пользовательскую функцию, пока вся программа пользовательского интерфейса не закроется и не запустится снова.

Единственный способ, который я вижу сейчас, - это разделитьвычислительное ядро ​​и пользовательский интерфейс, а затем заставляют их взаимодействовать через общую память / обмен сообщениями.Когда пользователь хочет обновить свою функцию, программа завершает работу ядра, перекомпилирует dll и снова запускает ядро.

Можете ли вы предложить какие-либо обычные практики в таких случаях?

Спасибо!

Ответы [ 3 ]

4 голосов
/ 16 июля 2011

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

2 голосов
/ 17 июля 2011

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

Со временем это, конечно, приведет к загрузке большого количества модулей.Если пользователи не запускают слишком много функций за один сеанс, это может сойти с рук.В качестве альтернативы вы можете скомпилировать функцию в простой DLL вместо модуля Python и загрузить ее с помощью ctypes.Когда вы закончите работу с DLL, просто откажитесь от любых ссылок на нее - когда дескриптор ctypes в конечном итоге gced, он должен выгрузить DLL (см. Как я могу выгрузить DLL, используя ctypes в Python? ).

Возможно, вы также захотите удалить свои библиотеки DLL с диска.Если вы используете Windows, это может быть сложно, так как трудно предсказать, когда ctypes его разгрузит, и Windows не позволит вам удалить его, если он будет использоваться.

1 голос
/ 16 июля 2011

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

Они могут автоматически компилировать и кэшировать код c во время выполнения из строки.Я только когда-либо использовал Instant для встроенного C, но я уверен, что это или weave будет работать так же хорошо для компиляции пользовательского ввода.

Вот пример того, как использовать weave, из учебника .

>>> a = 'string'
>>> def protected_printf(a):
...     assert(type(a) == type(1))
...     weave.inline(r'printf("%d\n",a);',['a'])
>>> protected_printf(1)
 1
>>> protected_printf('string')
AssertError...
...