Комментарии 12
Если формулы — полиномы, возможно вам стоит numexpr
попрбовать. Будет в 10 раз проще и в 100 раз быстрее.
>>ValueError: bytes must be in range(0, 256)
#это на фоне KeyError: ('8.348841409877572e-… длинная ошибка, до которой руки не дошли. Есть идеи как правильно пользовать?
Попробуйте сгенерить формулу без явных констант в тексте — может с парсингом что-то не так.
…
subs cycle (1000): lambdify Elapsed time: 0.482 sec (против numpy 0.026 sec)
…
redis_get + cloudpickle_loads_lambdifyed_expr + subs cycle (1000): Elapsed time: 2.396 sec (против numpy 1,721)
Вероятно, с учетом ограничений и результатов тестов, придется отказаться от numexpr.
Я не знаю, что и как вы делаете, но ваша формула (укороченная на 3 члена) считается за 30 микросекунд в 1 строчку numexpr.evaluate(long_formula_as_a_string)
. A numexpr.re_evaluate()
вообще отрабатывает за 22 микросекунды.
Что в 1000 раз быстрее вашего текущего подхода с лямбда-функциями, на создание которых уходит еще в 10 тысяч раз больше времени.
Так я привел код. Все, что вам нужно — это:
x1_, x2_, x3_, x4_, x5_, x6_, x7_ = ... # значения переменных
numexpr.evaluate(long_formula_as_a_string)
или можно чуть иначе:
variables_dict = dict(zip(variables_names, variables_values))
numexpr.evaluate(long_formula_as_a_string, local_dict=variables_dict)
numexpr (1000): cycle Elapsed time: 0.535 sec (против subs cycle (1000): lambdify Elapsed time: 0.026 sec).
Факт — штука упрямая…
Упрямы обычно криворукие необразованые дилетанты… а факты бывают разные.
Ваш подход:
- сначала надо откомпилировать выражение, это занимает 426 миллисек на 1 итерацию
expr = sympify(expr_txt)
- затем создать лямдба-функцию, на это уйдет 114 миллисек на 1 итерацию
func = lambdify(tuple(symbols_list), expr, 'numpy')
- и только после этого выполнять расчеты, 26 микросек на 1 итерацию
func(*[1 for i in range(len(symbols_set))])
Все это вместе отнимает 540 миллисек.
Или можно взять numexpr
, тогда потребуется только одна операция
- скопилировать и вычислить выражение за 30 микросекунд
numexpr.evaluate(long_formula_as_a_string, local_dict=variables_dict)
Все это вместе отнимает 30 микросекунд.
Теперь рассчитаем, во сколько раз быстрее numexpr
:
540 миллисекунд / 30 микросекунд = 18000
numexpr быстрее в 18 тысяч раз!
Вы, видимо, не слишком внимательно читали статью. Первые два пункта, которые вы обозначили, рассчитываются лишь однажды. Критично время самих расчетов (п.3). И прекращайте вводить людей в заблуждение — нет там 30 микросекунд. Вот с какого потолка вы эти результаты берете? Не бывает чудес. Разве что вы на мейнфрейме считаете. У меня полсек ВАШ код отработал (1000 итераций).
Профилирование и оптимизация символьных вычислений для будущего сервера