I have a function that is being called in a tight loop. I've profiled my code and this is where my largest bottleneck is. The function is fairly simple: it checks if a point in (x,y) form is above a line in (slope, intercept) form.
The problem is, it also has to deal with the case where the slope is positive infinity, and the intercept gives the x-intercept. In this case, the function should return True
if the point is to the right of the line.
Here's the function written out how it was when I noticed the bottleneck:
def point_over(point, line):
"""Return true if the point is above the line.
"""
slope, intercept = line
if slope != float("inf"):
return point[0] * slope + intercept < point[1]
else:
return point[0] > intercept
On my machine, this is how fast it runs:
>>> timeit("point_over((2.412412,3.123213), (-1.1234,9.1234))",
"from __main__ import point_over", number = 1000000)
1.116534522825532
Since this function is being called a lot, I've inlined it to avoid the function call overhead. The inlined version is fairly simple:
point[0] * line[0] + line[1] < point[1] if line[0] != float('inf') else point[0] > line[1]
And performs similarly in timeit
:
>>> timeit("point[0] * line[0] + line[1] < point[1] if line[0] != float('inf') else point[0] > line[1]",
"point, line = ((2.412412,3.123213), (-1.1234,9.1234))", number = 1000000)
0.9410096389594945
However, this one line of code is still hogging the largest proportion of execution time in my code, even after being inlined.
Why does the comparison to float('inf')
take longer than a number of calculations as well as a comparison? Is there any way to make this faster?
As an example of what I'm claiming, here are the speeds of two parts of my ternary statement separated and timed:
>>> timeit("line[0] != float('inf')",
"point, line = ((2.412412,3.123213), (-1.1234,9.1234))", number = 1000000)
0.528602410095175
>>> timeit("point[0] * line[0] + line[1] < point[1]",
"point, line = ((2.412412,3.123213), (-1.1234,9.1234))", number = 1000000)
0.48756339706397966
My primary question is why it takes so long to do the comparison to infinity. Secondary is any tips on how to speed these up. Ideally there exists some magical (even if incredibly hacky) way to half the execution time of this line, without dropping down to C. Otherwise, tell me I need to drop down to C.