Last active
August 10, 2022 03:20
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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