我目前正试图通过解决一些示例问题来提高我的python技能。其中之一是检查网格点是否位于障碍物后面。输出是没有在障碍物后面的所有网格点的数量。给定的提示是计算方向到点的角度,并将其与障碍物左右两侧的角度进行比较。我的代码工作并给出正确的结果,但是对于大型网格(1000x1000),它非常慢,所以我想知道是否有方法使代码更快。
耗时最长的部分是检查一个点是否在障碍物后面,所以我将在这里只包含代码的这一部分。如果您还需要其余的代码,我很乐意将其包含进来:)
import math
import numpy as np
def CheckIfObstacle(point, Obstacle):
for obs in Obstacle:
# condition for a point being behind a barrier that is on positive side of Grid
if obs[0]>0 and point[0] >= obs[0] and (obs[1] >= point[1] >= obs[2]):
return True
# condition for a point being behind a barrier that is on negative side of Grid
elif obs[0]<0 and point[0] <=obs[0] and (obs[1]>= point[1]>= obs[2]):
return True
return False
Obstacle = [] #[(y1,angle_big1,angle_small1),(y2,angle_big2,angle_small2),...]
for i in range(2,nObs+2):
some code that puts data in Obstacle
Grid = calcGrid(S) # [(y1,angle1),(y2,angle2),...]
count = 0
p=0
for point in Grid:
if p%10000==0:
print(round(p/len(Grid)*100,3),'%')
p+=1
if CheckIfObstacle(point, Obstacle) ==False:
count +=1
print(count)
这是我所有版本中最快的版本。我认为1000x1000的网格大约需要15分钟,但现在我有了一个更大的网格,它运行了一个小时,并且在5%左右。如果有人对如何改进代码有任何想法,我将很高兴得到一些反馈。
提前感谢!
如果您使用的是云软件,我建议您将这个等式拆分为16个不同的程序,这些程序分别运行。如果不是,让较小的方程连续运行。这样你就不会有一个必须一次渲染所有内容的庞大程序。
使用numba,您可以编译CheckIfObstacle并使其非常快速和内存高效。在我的例子中,你可以说我需要49000x12000的网格。所以使用numpy和numba对我来说是一种节省,你可以看到使用numba和使用numpy的速度比较。或者你可以使用Cython,相比numba
,它会有点复杂,并行性也很难实现。在函数顶部添加numba jit装饰器,包括适当的类型规范。这只是一个示例,不存储计算,但最好将numba添加到优化列表
@nb.njit((nb.float64[:], nb.float64[:, :]), parallel=True)
def CheckIfObstacle(point, Obstacle):
for i in nb.prange(Obstacle):
obs = Obstacle[i]
# condition for a point being behind a barrier that is on positive side of Grid
if obs[0]>0 and point[0] >= obs[0] and (obs[1] >= point[1] >= obs[2]):
return True
# condition for a point being behind a barrier that is on negative side of Grid
elif obs[0]<0 and point[0] <=obs[0] and (obs[1]>= point[1]>= obs[2]):
return True
return False
我有类似的问题,寻找性能和实现为什么是np。假设和np。减去。外的速度很快吗?