Created
November 27, 2018 23:15
-
-
Save arrieta/1f453781ef0bcec864998bd10ac0bbc1 to your computer and use it in GitHub Desktop.
Basic benchmark polynomial evaluation using Horner's Method
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
"""Simple re-arrangement can yield significant performance improvements in | |
naive, low-order polynomial evaluation. The interested reader may wish to read | |
about "Horner's method." | |
(C) 2018 Nabla Zero Labs | |
MIT License | |
""" | |
import time | |
def p0(a, x): | |
"""First strategy: naively calculate the polynomial. | |
Three additions, three multiplications, one pow(2), one pow(3).""" | |
for xi in x: | |
y = a[0] + a[1] * xi + a[2] * xi**2 + a[3] * xi**3 | |
return y | |
def p1(a, x): | |
"""Second strategy: save multiplications at the cost of memory. | |
Three additions, five multiplications, two extra variables""" | |
for xi in x: | |
xi2 = xi * xi | |
xi3 = xi2 * xi | |
y = a[0] + a[1] * xi + a[2] * xi2 + a[3] * xi3 | |
return y | |
def p2(a, x): | |
"""Third strategy: save multiplication with no cost. | |
Three additions, three multiplications. | |
""" | |
for xi in x: | |
y = a[0] + xi * (a[1] + xi * ( a[2] + a[3] * xi)) | |
return y | |
def cpu(fun, *args): | |
a, x = args | |
tbeg = time.perf_counter() | |
y = fun(a, x) | |
tend = time.perf_counter() | |
elap = tend - tbeg | |
thro = len(x) / elap | |
print(f"{fun.__name__}: {elap:.6f} sec ({thro:.0f} eval/sec)", | |
f"last value: {y:23.16e}", sep=" ") | |
if __name__ == "__main__": | |
import random | |
a = [random.uniform(-10, 10) for _ in range(4)] | |
x = [random.uniform(-1, 1) for _ in range(1000000)] | |
for _ in range(10): | |
cpu(p0, a, x) | |
cpu(p1, a, x) | |
cpu(p2, a, x) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Result: