【问题标题】:Don't know how to optimize the code with Cython不知道如何用 Cython 优化代码
【发布时间】:2020-10-08 19:12:18
【问题描述】:

我是尝试使用 cython 优化的新手,我需要一些帮助,因为我知道我可以优化更多但我不知道如何。

首先我做的是在C中声明变量,但是其中很多是对象,我不知道如何声明。

然后我有了类,在 HTML 中,每次代码想要获取类的对象时我都可以看到它很慢,所以我也想优化它,但我不知道该怎么做:(

import math
import random

def class City:
  def __init__(self, city_name='NoName', posx=0, posy=0):
    self.name = city_name
    self.x = posx
    self.y = posy

def distance_between_cities( object C1, object C2 ):
    """Compute distance between two cities"""
    dx = C1.x - C2.x
    dy = C1.y - C2.y
    return math.sqrt( dx*dx + dy*dy )

def read_cities_from_file ( str filename ):
    """Read list of Cities from text file"""
    cdef list Cities= [] # List of Empty Cities
    cdef list R = []
    with open(filename) as file:
        for line in file:
            R= line.split()
            Cities.append ( City( R[0], float(R[1]), float(R[2]) ) )
    return Cities

def path_distance( object Cities ):
    """Compute total distance of the path traversing all cities in order"""
    cdef int i = 0
    cdef double D = 0
    for i in range( len(Cities) ):
        D = D + distance_between_cities ( Cities[i],
                                          Cities[i+1 if i+1<len(Cities) else 0])
    return D

cdef int closerCity( object City, object Cities ):
    """Compute position of the city C in the list of Cities that is closer to City"""
    cdef float minDist = 2*1000*1000
    cdef int minIndex= 0
    cdef int i = 0
    cdef double dx = 0
    cdef double dy = 0
    cdef double dist = 0
    for i in range(len(Cities)):
        c = Cities[i]
        dx = City.x - c.x
        dy = City.y - c.y
        dist = dx*dx + dy*dy
        if dist < minDist:
            minDist = dist
            minIndex= i
    return minIndex

def GoodPath( object Cities ):
    """Generate a path with small total distance using greedy algorithm"""
    cdef list NotVisited = []
    cdef int len_C = len(Cities)
    cdef int i = 0
    for i in range(len_C):
      NotVisited.append(Cities[i])
    Path= [ Cities[0] ] # Start path with first city
    del NotVisited[0]
    while len(NotVisited) > 0:
        pos = closerCity( Path[-1], NotVisited )
        Path.append( NotVisited[pos] )
        del NotVisited[pos]
    return Path

if __name__ == "__main__":
  import argparse as arg
  parser = arg.ArgumentParser(prog='ARGUMENTS', usage='%(prog)s [options]')
  parser.add_argument("input",  type=str, help="File containing list of Cities")
  args = parser.parse_args()
  
  ListOfCities= read_cities_from_file ( str(args.input) )
  GoodList    = GoodPath( ListOfCities )
  print ( "Initial Distance =", path_distance( ListOfCities ),
          "  Good Distance =",  path_distance( GoodList) )

这是我在 cythonize 时从 HTML 中得到的: Part 1 of the HTML Part 2

任何帮助将不胜感激

谢谢!

【问题讨论】:

    标签: python optimization cython cythonize


    【解决方案1】:

    你的算法的复杂度是O(n^2)n是城市的数量)。实际上,您遍历所有城市,并且对于每个城市,您再次遍历大多数城市(O(n)city)。另请注意,项目删除是在O(n) 时间执行的。可以使用更高效的 O(n log n) 算法计算结果:

    您可以在O(n log n) 时间建造一个K-d tree 结构,或者更具体地说是Quad-tree 结构,然后使用此结构在O(log n) 时间找到任何其他城市最近的城市。此外,最好将 NotVisited 的类型更改为 set 而不是 list 以避免缓慢的列表项删除。

    除此之外,我建议您将object-typed 变量替换为低级类型(例如数组或 double/int 元组),以便 Cython 可以生成更快的 C 代码.

    请注意,您的方法通常不会找到整体最短路径,甚至可能找不到相当小的路径。有better algorithms,不过比较贵。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-30
      • 2020-03-09
      • 1970-01-01
      相关资源
      最近更新 更多