简体   繁体   English

Python:我怎样才能使这个 function 更快地计算距离?

[英]Python: How can I make this function for calculating distances faster?

I am making a simple car game with Python and PyGame to experiment with neural nets and especially the NEAT algorithm.我正在用 Python 和 PyGame 制作一个简单的汽车游戏,以试验神经网络,尤其是 NEAT 算法。 The player is supposed to drive the car through a track and must not touch the border.玩家应该驾驶汽车通过赛道,并且不得触及边界。 In order to make the neural nets "see", there are a couple of "sensors" which the net can use to get position information.为了让神经网络“看到”,网络可以使用几个“传感器”来获取 position 信息。 They calculate the distances to the border, which is defined by a mask, in various degrees.他们以不同的程度计算到边界的距离,边界由掩码定义。

Works fine for a couple of cars but when 20 or more are on the track, things slow down a lot.对于几辆车来说效果很好,但是当 20 辆或更多车在赛道上时,事情就会慢很多。

A part of cProfile output: cProfile output 的一部分:

         38382471 function calls in 52.762 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.001    0.001   52.762   52.762 <string>:1(<module>)
    26435    0.158    0.000    1.086    0.000 cargame.py:113(draw)
    26435    0.045    0.000    0.045    0.000 cargame.py:121(drawRadars)
    26435   14.103    0.001   22.550    0.001 cargame.py:128(checkRadars)
    26435    0.129    0.000   24.262    0.001 cargame.py:149(update)
    26435    0.060    0.000    0.282    0.000 cargame.py:157(checkColliding)
      273    0.001    0.000    0.011    0.000 cargame.py:169(drawOnMouse)

As far as I understand those lines, my checkRadars() is bottlenecking quite a bit.据我了解这些行,我的 checkRadars() 有点瓶颈。 It gets called for every car (when they are updated, which happens every frame).每辆车都会调用它(当它们更新时,每帧都会发生这种情况)。

   def checkRadars(self, mask):
        xcenter, ycenter = self.rect.center
        #self.radars.clear()
        v = (180-180*self.blindspot)/(self.radarCount-1)
        w = (90-90*self.blindspot)
        # dont mind these weird calculations
        for n in range(self.radarCount):
            length = 1
            x, y = xcenter, ycenter

            rangle = v*n-w
            rad = -math.radians(self.angle+rangle)


            while isInBound(x, y) and not mask.get_at((x, y)) and length < 100:
                length += 1
                x = int(xcenter + math.sin(rad) * length)
                y = int(ycenter - math.cos(rad) * length)
            if length == 100:
                length = length*10

I have optimized that method as far as I can, moving some calculations out of the loops, and so on, but it is still not fast enough.我已尽我所能优化该方法,将一些计算移出循环,等等,但它仍然不够快。 Lowering the length is not an option since it's already too low for my taste.降低长度不是一种选择,因为它对我的口味来说已经太低了。

Well, I tried to implement this function in other ways and managed to make it a little more efficient.好吧,我尝试以其他方式实现这个 function 并设法让它更有效率。

Turns out, there were more calculations than necessary and for range loops are better than while loops.事实证明,计算量超出了必要的范围,并且 for range 循环比 while 循环更好。

new code:新代码:

def checkRadars(self, mask):
        xcenter, ycenter = self.rect.center
        startd = -90+self.blindspot
        stopd = 90-self.blindspot
        dg = 180-self.blindspot*2

        self.radars.clear()
        for d in range(startd, stopd+1, int(dg/(self.radarCount-1))):
            x, y = xcenter, ycenter
            rad = math.radians(360 - (self.angle + d + 90))
            xvector = math.cos(rad)
            yvector = math.sin(rad)
            length = 1
            for length in range(1,200,5):
                if(not isInBound(x, y) or mask.get_at((x,y))):
                    break
                x = int(xcenter + xvector * length)
                y = int(ycenter + yvector * length)
            else: # nobreak
                length = 2000

            self.radars.append(((x, y),length))

new cProfile output:新 cProfile output:

         65266150 function calls in 49.991 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.002    0.002   49.991   49.991 <string>:1(<module>)
   215157    0.619    0.000    4.604    0.000 cargame.py:112(draw)
   215157   18.651    0.000   27.422    0.000 cargame.py:131(checkRadars)
   215157    0.449    0.000   34.656    0.000 cargame.py:156(update)

checkRadars() now clearly takes less time. checkRadars() 现在显然需要更少的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM