Ускорение вызова Python -c - PullRequest
1 голос
/ 15 мая 2019

Я выполняю вызов командной строки python из моего веб-приложения PHP для выполнения некоторой аналитики sympy (затем я анализирую выходные данные sympy).

Эти вызовы занимают много времени, но я думаю, что это большеЗапуск python и анализ / компиляция кода, которые занимают много времени, а не решение самой системы неравенств.

Дело в том, что моя программа меняется с каждым вызовом: я всегда решаю другую систему неравенств.Нет статической структуры, чтобы я мог импортировать только, например, коэффициенты LSE.Это система разного размера и структуры.Поэтому (я думаю) я не могу использовать pyc-файлы.

Вот два примерных вызова:

/usr/bin/python -c "from sympy import Intersection; from sympy import solveset; from sympy import S; from sympy.abc import x; from sympy.functions.elementary.miscellaneous import Min, Max; print Intersection(*[solveset(p, x, S.Reals) for p in [(x > 4.0000), (x < 6.0000)]])" 2>&1


/usr/bin/python -c "from sympy import Intersection; from sympy import solveset; from sympy import S; from sympy.abc import x; from sympy.functions.elementary.miscellaneous import Min, Max; print Intersection(*[solveset(p, x, S.Reals) for p in [(x > 4.0000), (x < 6.0000), (((x) * 4.0000 + 5.0000) > 5.0000)]])" 2>&1

Система неравенств может стать большой и все время различаться.Вот один с нелинейными выражениями:

/usr/bin/python -c "from sympy import Intersection; from sympy import solveset; from sympy import S; from sympy.abc import x; from sympy.functions.elementary.miscellaneous import Min, Max; print Intersection(*[solveset(p, x, S.Reals) for p in [(x > 4.0000), (x < 6.0000), ((x * (Min(Max(x, 4.0000), 5.0000))) > 7.0000), ((Min(Max(x, 4.0000), 5.0000)) > 5.0000)]])" 2>&1

Есть ли какие-либо параметры командной строки или параметры конфигурации, которые могли бы ускорить эти программы?

Может быть, я смогу предварительно скомпилировать импорт sympy?

Редактировать: Может ли быть режим python, который демонизирует python, ожидающий моих запросов с импортированными библиотеками sympy?Тогда я бы только «отправил» ему команду print Intersection(...)?

Редактировать 2 :

Благодаря одному ответу я опробовал пакет pypy,Но, к сожалению, я не могу сообщить об улучшении времени выполнения.Со стандартным python 2.7 я получаю:

# time /usr/bin/python -c "from sympy import Intersection; from sympy import solveset; from sympy import S; from sympy.abc import x; from sympy.functions.elementary.miscellaneous import Min, Max; print Intersection(*[solveset(p, x, S.Reals) for p in [(x > 4.0000), (x < 6.0000), ((x * (Min(Max(x, 4.0000), 5.0000))) > 7.0000), ((Min(Max(x, 4.0000), 5.0000)) > 5.0000)]])"
EmptySet()

real    0m3.080s
user    0m2.920s
sys 0m0.050s

С pypy у меня есть:

# time pypy -c "from sympy import Intersection; from sympy import solveset; from sympy import S; from sympy.abc import x; from sympy.functions.elementary.miscellaneous import Min, Max; print Intersection(*[solveset(p, x, S.Reals) for p in [(x > 4.0000), (x < 6.0000), ((x * (Min(Max(x, 4.0000), 5.0000))) > 7.0000), ((Min(Max(x, 4.0000), 5.0000)) > 5.0000)]])"
EmptySet()

real    0m6.816s
user    0m6.660s
sys 0m0.080s

Ответы [ 2 ]

2 голосов
/ 23 мая 2019

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

Большую часть времени тратится на решение проблем, которое кажется ненужным для многих ваших простых отношений.Например, нет смысла вызывать resolset с x<4, когда вы можете просто использовать as_set

In [7]: (x<4).as_set()                                                                                                            
Out[7]: (-∞, 4)

. Вы также можете переписать другие условия в более простую форму, например,

In [11]: piecewise_fold(Min(Max(x, 4.0000), 5.0000).rewrite(Piecewise))                                                           
Out[11]: 
⎧5.0  for x ≥ 5.0
⎪                
⎨4.0  for x ≤ 4.0
⎪                
⎩ x    otherwise 

Я думаю, что вы могли бы собрать более эффективный решатель, который обрабатывает это дело, чем решает.Я предлагаю создать функцию, которая будет более эффективной, чем может эффективно отправлять простые случаи, такие как x<4, и вызывать resolset только в более сложных случаях.

1 голос
/ 16 мая 2019

Есть много способов ускорить программы на Python.Рекомендуемый способ - оптимизировать ваш алгоритм и код (попробуйте python -m cProfile yourfile.py), и самое простое - использовать PyPy (JIT-компилятор для долго выполняющегося кода). Другие опции включают Shed Skin (статический компилятор с использованием C ++), Numba (статический компилятор с использованием декораторов и LLVM), Cython (статический компиляториспользуя типы и C (++), рекомендуется) и Nuitka .

В вашем случае, по крайней мере, поместите код командной строки в файл .py и запустите python -m compileall . to скомпилируйте это в .pyc байт-код делает шаг разбора более быстрым, но это незначительно при использовании статического компилятора для полного пропуска интерпретатора.

Если вы создаете REST API, платформа Falcon является одним из самых быстрых серверов Python FastCGI в соответствии с этим тестом ;вот небольшой демонстрационный проект сервера SymPy REST API .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...