inpoly-python
inpoly-python copied to clipboard
Performance
Hey Darren,
I used line_profiler
with a decorator above the kernel _inpoly()
to see if there were any hotspots we could improve...Overall great. Below is the output from line_profiler
running example.py
. Doesn't look like it could be improved much. As you can see, the continue
if catch appears to occupy 14% of the total time.
(base) keiths-MacBook-Pro:inpoly-python Keith$ kernprof -l -v example.py INPOLY2: 2.289767026901245 Wrote profile results to example.py.lprof Timer unit: 1e-06 s
Total time: 1.26219 s File: /Users/Keith/junk/inpoly-python/inpoly/inpoly2.py Function: _inpoly at line 131
Line # Hits Time Per Hit % Time Line Contents
131 @profile
132 def inpoly(vert, node, edge, ftol, lbar):
133 """
134 INPOLY: the local pycode version of the crossing-number
135 test. Loop over edges; do a binary-search for the first
136 vertex that intersects with the edge y-range; crossing-
137 number comparisons; break when the local y-range is met.
138
139 """
140
141 1 11.0 11.0 0.0 feps = ftol * (lbar ** +2)
142 1 2.0 2.0 0.0 veps = ftol * (lbar ** +1)
143
144 1 27.0 27.0 0.0 stat = np.full(vert.shape[0], False, dtype=np.bool)
145 1 12.0 12.0 0.0 bnds = np.full(vert.shape[0], False, dtype=np.bool)
146
147 # ----------------------------------- compute y-range overlap
148 1 47.0 47.0 0.0 XONE = node[edge[:, 0], 0]
149 1 42.0 42.0 0.0 XTWO = node[edge[:, 1], 0]
150 1 86.0 86.0 0.0 YONE = node[edge[:, 0], 1]
151 1 80.0 80.0 0.0 YTWO = node[edge[:, 1], 1]
152
153 1 66.0 66.0 0.0 XMIN = np.minimum(XONE, XTWO)
154 1 83.0 83.0 0.0 XMAX = np.maximum(XONE, XTWO)
155
156 1 62.0 62.0 0.0 XMAX = XMAX + veps
157 1 10.0 10.0 0.0 YMIN = YONE - veps
158 1 46.0 46.0 0.0 YMAX = YTWO + veps
159
160 1 51.0 51.0 0.0 YDEL = YTWO - YONE
161 1 44.0 44.0 0.0 XDEL = XTWO - XONE
162
163 1 750.0 750.0 0.1 ione = np.searchsorted(vert[:, 1], YMIN, "left")
164 1 826.0 826.0 0.1 itwo = np.searchsorted(vert[:, 1], YMAX, "right")
165
166 # ----------------------------------- loop over polygon edges
167 11000 7184.0 0.7 0.6 for epos in range(edge.shape[0]):
168
169 10999 9413.0 0.9 0.7 xone = XONE[epos]
170 10999 8909.0 0.8 0.7 xtwo = XTWO[epos]
171 10999 8982.0 0.8 0.7 yone = YONE[epos]
172 10999 8884.0 0.8 0.7 ytwo = YTWO[epos]
173
174 10999 8760.0 0.8 0.7 xmin = XMIN[epos]
175 10999 8695.0 0.8 0.7 xmax = XMAX[epos]
176
177 10999 8706.0 0.8 0.7 xdel = XDEL[epos]
178 10999 8821.0 0.8 0.7 ydel = YDEL[epos]
179
180 # ------------------------------- calc. edge-intersection
181 264806 186197.0 0.7 14.8 for jpos in range(ione[epos], itwo[epos]):
182
183 253807 182977.0 0.7 14.5 if bnds[jpos]:
184 87497 55301.0 0.6 4.4 continue
185
186 166310 147738.0 0.9 11.7 xpos = vert[jpos, 0]
187 166310 144366.0 0.9 11.4 ypos = vert[jpos, 1]
188
189 166310 117233.0 0.7 9.3 if xpos >= xmin:
190 90503 66346.0 0.7 5.3 if xpos <= xmax:
191 # ------------------- compute crossing number
192 25671 24757.0 1.0 2.0 mul1 = ydel * (xpos - xone)
193 25671 23340.0 0.9 1.8 mul2 = xdel * (ypos - yone)
194
195 25671 71918.0 2.8 5.7 if feps >= np.abs(mul2 - mul1):
196 # ------------------- BNDS -- approx. on edge
197 21998 17140.0 0.8 1.4 bnds[jpos] = True
198 21998 20768.0 0.9 1.6 stat[jpos] = True
199
200 3673 2657.0 0.7 0.2 elif (ypos == yone) and (xpos == xone):
201 # ------------------- BNDS -- match about ONE
202 bnds[jpos] = True
203 stat[jpos] = True
204
205 3673 2516.0 0.7 0.2 elif (ypos == ytwo) and (xpos == xtwo):
206 # ------------------- BNDS -- match about TWO
207 bnds[jpos] = True
208 stat[jpos] = True
209
210 3673 2889.0 0.8 0.2 elif (mul1 < mul2) and (ypos >= yone) and (ypos < ytwo):
211 # ------------------- advance crossing number
212 1819 1829.0 1.0 0.1 stat[jpos] = not stat[jpos]
213
214 75807 57239.0 0.8 4.5 elif (ypos >= yone) and (ypos < ytwo):
215 # ----------------------- advance crossing number
216 66373 56383.0 0.8 4.5 stat[jpos] = not stat[jpos]
217
218 1 1.0 1.0 0.0 return stat, bnds