Cython化用Python编写的类的特定方法

时间:2018-01-01 06:43:56

标签: python c++ c cython cythonize

我有一个纯粹用Python编写的A *规划算法(在路径规划中使用这个优秀的resource)。具有相关移动和成本方法的网格类定义如下:

class SquareGrid:
      def __init__(self, width, height):
          self.width = width
          self.height = height
          self.walls = []
          self.weights = []

      def in_bounds(self, id):
          (x, y) = id
          return 0 <= x < self.width and 0 <= y < self.height

      def passable(self, id):
          return id not in self.walls

      def neighbors(self, id):
          (x, y) = id
          results = [(x + 1, y), (x + 1, y - 1), (x, y - 1), (x - 1, y - 1), (x - 1, y), (x - 1, y + 1), (x, y + 1), (x + 1, y + 1)]
          if (x + y) % 2 == 0: results.reverse()  # aesthetics

          results = [r for r in results if self.in_bounds(r)]
          results = [r for r in results if self.passable(r)] # this is where things slow down
          return results

      def cost(self, from_node, to_node):
          return (to_node[0] - from_node[0])**2 + (to_node[1] - from_node[1])**2

现在,我想使用Cython的静态编译器优点加快执行速度。一种选择是在Cython中使用静态类型重写整个事物。我使用cProfiler分析纯Python代码以查看瓶颈在哪里,并且不足为奇的是,大约70%的总执行时间进入neighbors方法(计算当前节点周围的有效邻居节点)。更具体地说,对于给定的玩具示例,neighbors中的列表理解行调用passable超过33,000次。 passable检查其参数中给出的节点是否标记为&#34;障碍&#34;或者不通过搜索SquareGrid的障碍知识(SquareGrid.walls,位置元组列表)并相应地返回布尔值。在我看来,仅仅通过优化这种特殊方法,我就可以获得显着的速度提升。所以我开始在Cython中重写passable

我在Cython和C / C ++中一般都是一个完整的菜鸟,所以如果有任何关于理解这个东西是如何运作的错误,我会很感激。我创建了一个pyrex文件passable_cy.pyx,希望使用Cython / GCC ++编译它然后将它绑定到主脚本中的SquareGrid对象就足够了。这就是我定义passable_cy.pyx

的方式
cpdef bint passable(object self, tuple id):
    return id not in self.walls

随附的setup.py文件:

from distutils.core import setup
from Cython.Build import cythonize

setup(name="cynthonized_passable", ext_modules=cythonize(['passable_cy.pyx']),)

这就是我在主要的A * python脚本中将新的cynthonized方法绑定到SquareGrid的方法:

 g = SquareGrid(100, 100) # create grid with dimensions 100x100
 g.passable = types.MethodType(passable_cy.passable, g)

一切正确编译,整个事情没有问题。没有任何速度提升,我有点期待(看起来太简单了)。我该如何从这里开始?这种绑定方法的东西是最好的方法吗?我确信可以在passable_cy.pyx中完成更多工作,但我不熟悉C / C ++以了解该怎么做。

0 个答案:

没有答案