Сокращение накладных расходов на вызовы функций в Python
Я разработал приложение, которое моделирует N роботов, движущихся в сетке, которые пытаются максимизировать количество посещенных ячеек сетки за ограниченное количество шагов, встречаясь в целевой точке. Все работает правильно, но ужасно медленно. В настоящее время это python+numpy+mathplotlib.
Максимальное количество роботов может быть мягким, равным 100 (если оно может быть выше, это хорошо).
Для этого я делаю следующее упрощенно:
while steps > 0:
for robot in robots:
agent.calc(robot,steps)
Робот представляет собой массив nxy 1x2 (координаты x и y).
Агент здесь решает, что делать. Поскольку мне нужно на ходу менять тактику и стратегию, я не могу изменить эту логику.
agent.calc обновляет робота на месте, один за другим.
c Профилирование возвращает следующее. Извлечение вершины
39014272 function calls (39010490 primitive calls) in 150.314 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
12417735 62.807 0.000 62.807 0.000 distance.py:8(taxicab_distance)
124596 36.882 0.000 36.882 0.000 {numpy.core.multiarray.array}
113657 30.204 0.000 100.800 0.001 logical_agent.py:16(choose_max_distance_to...)
12417013 6.579 0.000 69.384 0.000 squaregrid.py:30(distance)
113700 2.900 0.000 109.769 0.001 logical_agent.py:73(calc)
11652363 2.625 0.000 2.625 0.000 {method 'append' of 'list' objects}
161849 1.653 0.000 1.653 0.000 distance.py:11(euclidean_distance)
113664 1.632 0.000 1.632 0.000 {sorted}
114834 1.185 0.000 1.185 0.000 {method 'keys' of 'dict' objects}
113700 0.695 0.000 1.134 0.000 squaregrid.py:19(neighbours)
Я реализовал разные среды для роботов, самое главное - это квадратная птица. У каждой среды есть своя функция расстояния, так как я намеревался использовать разные метрики, например Манхэттен / Таксикаб и Евклид. Я извлек функцию расстояния в собственный файл distance.py, так как использую его несколько раз.
Можно видеть, что taxicab_distance называется много, так как агент должен оценить расстояния робота четырех соседей и себя до точки цели, чтобы увидеть, может ли следующая позиция все еще достичь цели и максимизировать расстояние до всех других роботов как оптимизация эвристики.
Функция не делает ничего особенного, просто
def taxicab_distance(u, v):
return np.abs(u[0] - v[0]) + np.abs(u[1] - v[1])
Я знаю, что у python довольно высокие издержки при вызове функций, и я предполагаю, что это сказывается на производительности. {Numpy.core.multiarray.array} можно игнорировать, я думаю, я знаю, что я делаю там неправильно.
Цепочка удаленных вызовов: агент -> environment.distance -> taxicab_distance
Вопрос в том, как я могу уменьшить накладные расходы при вызове функции? Я настоятельно подумал об использовании Python с расширяемостью, Cython, чтобы быть более конкретным. Это будет работать? может ли быть другая причина, почему это так медленно?
2 ответа
Я сравнил его со встроенным, и это заняло ~15 секунд. В конце я переписал сокращение чисел в C++ и использовал Cython для интеграции. После этого прошло всего 1 секунду.
РЕДАКТИРОВАТЬ: cpython -> Cython
Во-первых, я бы переписал это в:
def taxicab_distance(u, v):
return np.sum(np.abs(u - v))
Вы можете вычислить taxicab_distance
для многих роботов одновременно?