Сокращение накладных расходов на вызовы функций в 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 для многих роботов одновременно?

Другие вопросы по тегам