<p>如果速度是您所需要的,并且额外的依赖性不是问题,那么您可能会发现<a href="http://numba.pydata.org/" rel="noreferrer">^{<cd1>}</a>非常有用(现在在任何平台上都很容易安装)。通过使用<code>numba @jit</code>装饰器并将多边形投射到numpy数组,您提出的经典<code>ray_tracing</code>方法可以很容易地移植到<code>numba</code>。代码应该如下所示:</p>
<pre><code>@jit(nopython=True)
def ray_tracing(x,y,poly):
n = len(poly)
inside = False
p2x = 0.0
p2y = 0.0
xints = 0.0
p1x,p1y = poly[0]
for i in range(n+1):
p2x,p2y = poly[i % n]
if y > min(p1y,p2y):
if y <= max(p1y,p2y):
if x <= max(p1x,p2x):
if p1y != p2y:
xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
if p1x == p2x or x <= xints:
inside = not inside
p1x,p1y = p2x,p2y
return inside
</code></pre>
<p>第一次执行将比任何后续调用花费稍长的时间:</p>
<pre><code>%%time
polygon=np.array(polygon)
inside1 = [numba_ray_tracing_method(point[0], point[1], polygon) for
point in points]
CPU times: user 129 ms, sys: 4.08 ms, total: 133 ms
Wall time: 132 ms
</code></pre>
<p>在汇编之后,将减少到:</p>
<pre><code>CPU times: user 18.7 ms, sys: 320 µs, total: 19.1 ms
Wall time: 18.4 ms
</code></pre>
<p>如果在第一次调用函数时需要速度,那么可以使用<code>pycc</code>在模块中预编译代码。将函数存储在src.py中,如下所示:</p>
<pre><code>from numba import jit
from numba.pycc import CC
cc = CC('nbspatial')
@cc.export('ray_tracing', 'b1(f8, f8, f8[:,:])')
@jit(nopython=True)
def ray_tracing(x,y,poly):
n = len(poly)
inside = False
p2x = 0.0
p2y = 0.0
xints = 0.0
p1x,p1y = poly[0]
for i in range(n+1):
p2x,p2y = poly[i % n]
if y > min(p1y,p2y):
if y <= max(p1y,p2y):
if x <= max(p1x,p2x):
if p1y != p2y:
xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
if p1x == p2x or x <= xints:
inside = not inside
p1x,p1y = p2x,p2y
return inside
if __name__ == "__main__":
cc.compile()
</code></pre>
<p>用<code>python src.py</code>构建它并运行:</p>
<pre><code>import nbspatial
import numpy as np
lenpoly = 100
polygon = [[np.sin(x)+0.5,np.cos(x)+0.5] for x in
np.linspace(0,2*np.pi,lenpoly)[:-1]]
# random points set of points to test
N = 10000
# making a list instead of a generator to help debug
points = zip(np.random.random(N),np.random.random(N))
polygon = np.array(polygon)
%%time
result = [nbspatial.ray_tracing(point[0], point[1], polygon) for point in points]
CPU times: user 20.7 ms, sys: 64 µs, total: 20.8 ms
Wall time: 19.9 ms
</code></pre>
<p>在我使用的numba代码中:
'b1(f8,f8,f8[:,:])'</p>
<p>为了用<code>nopython=True</code>编译,需要在<code>for loop</code>之前声明每个变量。</p>
<p>在预构建src代码中,行:</p>
<pre><code>@cc.export('ray_tracing' , 'b1(f8, f8, f8[:,:])')
</code></pre>
<p>用于将函数名及其I/O变量类型、布尔输出<code>b1</code>、两个浮点<code>f8</code>和一个二维浮点数组<code>f8[:,:]</code>声明为输入。</p>