Python 3 Type Hints For Performance Optimizations
Solution 1:
The speed difference is not due to type-hinting. Python currently, and for the foreseeable future, just discards any hints you offer and continues executing dynamically as it always does.
It's due to the fact that in one case you use floating arithmetic throughout the code (which results in faster execution) while in the other case you don't.
Case in point: Change baselpi1
to the following:
def baselpi1(n : int) -> float:
n = float(n)
baselsum = 0
i = 1while i < n:
baselsum += 1.0 / (i * i)
i += 1return math.sqrt(6.0 * baselsum)
And take a look at the execution times now:
3.141591698659554
0.2511475086212158
3.141591698659554
0.4525010585784912
Yes, it is way slower.
Solution 2:
If you need to do large amounts of numerical computation then numpy
offers a good choice generally. Numpy works with lower level data types (such as fixed-width integers -- python's is unbounded). This gives you the sort of type-hinting you are interested in. As numpy is designed to work with large amounts of data in arrays with known types, it can efficiently perform the same operation on an entire array. This also allows numpy to work well with CPUs that SIMD instructions (I'm not aware of a modern CPU without SIMD).
I would normally rewrite your function as such:
import math
import numpy
def baselpi_numpy(n):
i = numpy.arange(1, n) # array of 1..n
baselsum = (1 / (i * i)).sum()
return math.sqrt(6 * baselsum)
However, for large n
you will not have enough memory. You'll have to add a bit of extra code to batch the the operation for you. That is:
def baselpi_numpy(n, batch_size=1<<16):
basel_sum =0
i =1for i inrange(1, n, batch_size):
j =min(n, i + batch_size)
basel_sum += baselsum_numpy(i, j)
return math.sqrt(6* basel_sum)
def baselsum_numpy(start, end):
# equivalent ->sum(1/ (i * i) for i inrange(start, end))
i = numpy.arange(start, end, dtype=float)
# this line and next are memory optimisations which double speed
# equivalent to i =1/ (i * i)
i *= i
i = numpy.divide(1, i, out=i)
basel_sum = i.sum()
return basel_sum
I get the result back in 5.2 seconds on my laptop. Though I haven't tested for the value of n
you use, for lower n
the numpy version is more than 20 times faster.
Post a Comment for "Python 3 Type Hints For Performance Optimizations"