Skip to content

Instantly share code, notes, and snippets.

@WarrenWeckesser
Last active August 10, 2022 03:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WarrenWeckesser/1cd81b1e64d302c727d2fb0d870b62e5 to your computer and use it in GitHub Desktop.
Save WarrenWeckesser/1cd81b1e64d302c727d2fb0d870b62e5 to your computer and use it in GitHub Desktop.
Timing comparison for various ways to make a predefined dictionary available in the skew_norm_gen class.
import timeit
s0 = """
@lru_cache
def _get_skewnorm_odd_moments():
_skewnorm_odd_moments = {
1: Polynomial([1]),
3: Polynomial([3, -1]),
5: Polynomial([15, -10, 3]),
7: Polynomial([105, -105, 63, -15]),
9: Polynomial([945, -1260, 1134, -540, 105]),
11: Polynomial([10395, -17325, 20790, -14850, 5775, -945]),
13: Polynomial([135135, -270270, 405405, -386100, 225225, -73710,
10395]),
15: Polynomial([2027025, -4729725, 8513505, -10135125, 7882875,
-3869775, 1091475, -135135]),
17: Polynomial([34459425, -91891800, 192972780, -275675400, 268017750,
-175429800, 74220300, -18378360, 2027025]),
19: Polynomial([654729075, -1964187225, 4714049340, -7856748900,
9166207050, -7499623950, 4230557100, -1571349780,
346621275, -34459425]),
}
return _skewnorm_odd_moments
class Foo0:
def _munp(self, order, a):
if order & 1:
if order > 19:
raise NotImplementedError("skewnorm noncentral moments not "
"implemented for odd orders greater "
"than 19.")
# Use the precomputed polynomials that were derived from the
# moment generating function.
delta = a/np.sqrt(1 + a**2)
return (delta * _get_skewnorm_odd_moments()[order](delta**2)
* _SQRT_2_OVER_PI)
foo0 = Foo0()
"""
s1 = """
class Foo1:
odd_moments = {
1: Polynomial([1]),
3: Polynomial([3, -1]),
5: Polynomial([15, -10, 3]),
7: Polynomial([105, -105, 63, -15]),
9: Polynomial([945, -1260, 1134, -540, 105]),
11: Polynomial([10395, -17325, 20790, -14850, 5775, -945]),
13: Polynomial([135135, -270270, 405405, -386100, 225225, -73710,
10395]),
15: Polynomial([2027025, -4729725, 8513505, -10135125, 7882875,
-3869775, 1091475, -135135]),
17: Polynomial([34459425, -91891800, 192972780, -275675400, 268017750,
-175429800, 74220300, -18378360, 2027025]),
19: Polynomial([654729075, -1964187225, 4714049340, -7856748900,
9166207050, -7499623950, 4230557100, -1571349780,
346621275, -34459425]),
}
def _munp(self, order, a):
if order & 1:
if order > 19:
raise NotImplementedError("skewnorm noncentral moments not "
"implemented for odd orders greater "
"than 19.")
# Use the precomputed polynomials that were derived from the
# moment generating function.
delta = a/np.sqrt(1 + a**2)
return (delta * self.odd_moments[order](delta**2)
* _SQRT_2_OVER_PI)
foo1 = Foo1()
"""
s2 = """
class Foo2:
def _get_skewnorm_odd_moments(self):
_skewnorm_odd_moments = {
1: Polynomial([1]),
3: Polynomial([3, -1]),
5: Polynomial([15, -10, 3]),
7: Polynomial([105, -105, 63, -15]),
9: Polynomial([945, -1260, 1134, -540, 105]),
11: Polynomial([10395, -17325, 20790, -14850, 5775, -945]),
13: Polynomial([135135, -270270, 405405, -386100, 225225, -73710,
10395]),
15: Polynomial([2027025, -4729725, 8513505, -10135125, 7882875,
-3869775, 1091475, -135135]),
17: Polynomial([34459425, -91891800, 192972780, -275675400, 268017750,
-175429800, 74220300, -18378360, 2027025]),
19: Polynomial([654729075, -1964187225, 4714049340, -7856748900,
9166207050, -7499623950, 4230557100, -1571349780,
346621275, -34459425]),
}
return _skewnorm_odd_moments
def _munp(self, order, a):
if order & 1:
if order > 19:
raise NotImplementedError("skewnorm noncentral moments not "
"implemented for odd orders greater "
"than 19.")
# Use the precomputed polynomials that were derived from the
# moment generating function.
delta = a/np.sqrt(1 + a**2)
return (delta * self._get_skewnorm_odd_moments()[order](delta**2)
* _SQRT_2_OVER_PI)
foo2 = Foo2()
"""
s3 = """
class Foo3:
@lru_cache
def _get_skewnorm_odd_moments(self):
_skewnorm_odd_moments = {
1: Polynomial([1]),
3: Polynomial([3, -1]),
5: Polynomial([15, -10, 3]),
7: Polynomial([105, -105, 63, -15]),
9: Polynomial([945, -1260, 1134, -540, 105]),
11: Polynomial([10395, -17325, 20790, -14850, 5775, -945]),
13: Polynomial([135135, -270270, 405405, -386100, 225225, -73710,
10395]),
15: Polynomial([2027025, -4729725, 8513505, -10135125, 7882875,
-3869775, 1091475, -135135]),
17: Polynomial([34459425, -91891800, 192972780, -275675400, 268017750,
-175429800, 74220300, -18378360, 2027025]),
19: Polynomial([654729075, -1964187225, 4714049340, -7856748900,
9166207050, -7499623950, 4230557100, -1571349780,
346621275, -34459425]),
}
return _skewnorm_odd_moments
def _munp(self, order, a):
if order & 1:
if order > 19:
raise NotImplementedError("skewnorm noncentral moments not "
"implemented for odd orders greater "
"than 19.")
# Use the precomputed polynomials that were derived from the
# moment generating function.
delta = a/np.sqrt(1 + a**2)
return (delta * self._get_skewnorm_odd_moments()[order](delta**2)
* _SQRT_2_OVER_PI)
foo3 = Foo3()
"""
s4 = """
class Foo4:
def __init__(self):
self._skewnorm_odd_moments = {
1: Polynomial([1]),
3: Polynomial([3, -1]),
5: Polynomial([15, -10, 3]),
7: Polynomial([105, -105, 63, -15]),
9: Polynomial([945, -1260, 1134, -540, 105]),
11: Polynomial([10395, -17325, 20790, -14850, 5775, -945]),
13: Polynomial([135135, -270270, 405405, -386100, 225225, -73710,
10395]),
15: Polynomial([2027025, -4729725, 8513505, -10135125, 7882875,
-3869775, 1091475, -135135]),
17: Polynomial([34459425, -91891800, 192972780, -275675400, 268017750,
-175429800, 74220300, -18378360, 2027025]),
19: Polynomial([654729075, -1964187225, 4714049340, -7856748900,
9166207050, -7499623950, 4230557100, -1571349780,
346621275, -34459425]),
}
def _munp(self, order, a):
if order & 1:
if order > 19:
raise NotImplementedError("skewnorm noncentral moments not "
"implemented for odd orders greater "
"than 19.")
# Use the precomputed polynomials that were derived from the
# moment generating function.
delta = a/np.sqrt(1 + a**2)
return (delta * self._skewnorm_odd_moments[order](delta**2)
* _SQRT_2_OVER_PI)
foo4 = Foo4()
"""
s5 = """
class Foo5:
@cached_property
def _skewnorm_odd_moments(self):
skewnorm_odd_moments = {
1: Polynomial([1]),
3: Polynomial([3, -1]),
5: Polynomial([15, -10, 3]),
7: Polynomial([105, -105, 63, -15]),
9: Polynomial([945, -1260, 1134, -540, 105]),
11: Polynomial([10395, -17325, 20790, -14850, 5775, -945]),
13: Polynomial([135135, -270270, 405405, -386100, 225225, -73710,
10395]),
15: Polynomial([2027025, -4729725, 8513505, -10135125, 7882875,
-3869775, 1091475, -135135]),
17: Polynomial([34459425, -91891800, 192972780, -275675400, 268017750,
-175429800, 74220300, -18378360, 2027025]),
19: Polynomial([654729075, -1964187225, 4714049340, -7856748900,
9166207050, -7499623950, 4230557100, -1571349780,
346621275, -34459425]),
}
return skewnorm_odd_moments
def _munp(self, order, a):
if order & 1:
if order > 19:
raise NotImplementedError("skewnorm noncentral moments not "
"implemented for odd orders greater "
"than 19.")
# Use the precomputed polynomials that were derived from the
# moment generating function.
delta = a/np.sqrt(1 + a**2)
return (delta * self._skewnorm_odd_moments[order](delta**2)
* _SQRT_2_OVER_PI)
foo5 = Foo5()
"""
setup = """
import numpy as np
from numpy.polynomial import Polynomial
from functools import lru_cache, cached_property
_SQRT_2_OVER_PI = 0.7978845608028654
"""
stmts = [s0, s1, s2, s3, s4, s5]
n = 20000
creation_times = []
for k, stmt in enumerate(stmts):
t = timeit.timeit(stmt, setup, number=n)/n
creation_times.append(t)
# print(f"t{k} = {1e6*t:10.3f} μs")
with open('generated_code.py', 'w') as f:
f.write(setup)
for stmt in stmts:
f.write(stmt)
f.write('\n')
from generated_code import foo0, foo1, foo2, foo3, foo4, foo5
instances = [foo0, foo1, foo2, foo3, foo4, foo5]
n = 200000
call_times = []
for k, foo in enumerate(instances):
t = timeit.timeit('foo._munp(3, 0.5)', globals={'foo': foo}, number=n)/n
call_times.append(t)
print("Method Creation Call (times in microseconds)")
for k, (tcreate, tcall) in enumerate(zip(creation_times, call_times)):
print(f'{k:3d} {1e6*tcreate:9.2f} {1e6*tcall:9.2f}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment