release-the-gil/src/fibonacci.py

103 lines
2.4 KiB
Python

import argparse
from collections import defaultdict
from threading import Thread
from time import monotonic_ns
from typing import List, DefaultDict
from numba import jit
from texttable import Texttable
from fibonacci_cython import cython_gil, cython_nogil
@jit(nopython=True, nogil=True)
def numba_nogil(n: int) -> int:
if n <= 1:
return n
a = 0
b = 1
c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b
return c
@jit(nopython=True)
def numba_gil(n: int) -> int:
if n <= 1:
return n
a = 0
b = 1
c = a + b
for _i in range(2, n):
a = b
b = c
c = a + b
return c
def main(n: int = 1_000_000_000):
# Pre-compile the numba variants
numba_nogil(15)
numba_gil(15)
functions = [cython_gil, cython_nogil, numba_gil, numba_nogil]
names = ["cython_gil", "cython_nogil", "numba_gil", "numba_nogil"]
results_single: List[str] = []
results: DefaultDict[str, List[str]] = defaultdict(list)
for i, t1_function in enumerate(functions):
t1_name = names[i]
start = monotonic_ns()
t1_function(n)
end = monotonic_ns()
runtime = str((end - start) / float(1_000_000)) + "ms"
results_single.append(runtime)
for j, t2_function in enumerate(functions):
t1 = Thread(target=t1_function, args=[n])
t2 = Thread(target=t2_function, args=[n])
# While there's overhead in the thread start/join calls unrelated to
# actual runtime, it's pretty small relative to total runtime
start = monotonic_ns()
# The order in which we start threads matters!
t1.start()
t2.start()
t1.join()
t2.join()
end = monotonic_ns()
runtime = str((end - start) / float(1_000_000)) + "ms"
results[t1_name].append(runtime)
table = Texttable()
table.header(names)
table.add_row(results_single)
print(table.draw())
table = Texttable()
table.header([""] + names)
for main_name, results in results.items():
table.add_row([main_name] + results)
print(table.draw())
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-n', help='Fibonacci number to calculate', default=1_000_000_000)
cmdline = parser.parse_args()
main(cmdline.n)