减少python中的函数调用开销

时间:2014-01-01 14:45:06

标签: python performance numpy cython overhead-minimization

我开发了一个应用程序,它模拟在网格中移动的 N 机器人,这些机器人试图在有限的步骤中最大化访问的网格单元的数量,以达到目标点。这一切都正常,但是很慢。它目前是python + numpy + mathplotlib。

那里的最大机器人可以有100的软限制(如果它可以变高,那么很高兴。)

为此,我执行以下操作,简化:

while steps > 0:
    for robot in robots:
        agent.calc(robot,steps)

机器人是一个1x2的numpy数组(x和y坐标)。

此处的代理商决定该怎么做。由于我需要动态切换策略和策略,我无法改变这种逻辑。

agent.calc 一个接一个地更新机器人。

cProfiling它返回following。提取顶部

         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)

我为机器人实施了不同的环境,最重要的是 squaregird 。每个环境都有自己的距离函数,因为我打算使用不同的指标,即曼哈顿/出租车和欧几里德。我将距离函数提取到一个自己的 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

问题是,如何减少调用函数的开销?我强烈考虑使用pythons c extensibility,cython,更具体。它会起作用吗?还有其他原因导致它如此缓慢吗?

2 个答案:

答案 0 :(得分:4)

首先,我将其重写为:

def taxicab_distance(u, v):
     return np.sum(np.abs(u - v))

您可以同时为多个机器人计算taxicab_distance吗?

答案 1 :(得分:2)

我用内联对它进行了基准测试,它起飞了〜15秒。最后,我重写了C ++中的数字运算并使用cython进行集成。之后,只花了1秒钟。

编辑:cpython - >用Cython