mirror of
https://github.com/speice-io/release-the-gil
synced 2024-12-21 06:08:22 -05:00
Fibonacci and double-unlock examples
This commit is contained in:
commit
29edf9cc8f
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.c
|
||||
*.so
|
19
setup.py
Normal file
19
setup.py
Normal file
@ -0,0 +1,19 @@
|
||||
from setuptools import setup, find_packages
|
||||
from Cython.Build import cythonize
|
||||
|
||||
|
||||
setup(
|
||||
name="release-the-gil",
|
||||
version="0.1",
|
||||
author="Bradlee Speice",
|
||||
author_email="bradlee@speice.io",
|
||||
description="Basic examples of parallelism in Python",
|
||||
url="https://github.com/speice-io/release-the-gil",
|
||||
packages=find_packages(),
|
||||
ext_modules=cythonize("src/*.pyx"),
|
||||
install_requires=[
|
||||
"Cython",
|
||||
"numba",
|
||||
"texttable"
|
||||
],
|
||||
)
|
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
4
src/double_unlock.py
Normal file
4
src/double_unlock.py
Normal file
@ -0,0 +1,4 @@
|
||||
from double_unlock_cython import unlock
|
||||
|
||||
if __name__ == '__main__':
|
||||
unlock()
|
8
src/double_unlock_cython.pyx
Normal file
8
src/double_unlock_cython.pyx
Normal file
@ -0,0 +1,8 @@
|
||||
cdef void _unlock() nogil:
|
||||
with nogil:
|
||||
pass
|
||||
|
||||
|
||||
def unlock():
|
||||
with nogil:
|
||||
_unlock()
|
102
src/fibonacci.py
Normal file
102
src/fibonacci.py
Normal file
@ -0,0 +1,102 @@
|
||||
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)
|
24
src/fibonacci_cython.pyx
Normal file
24
src/fibonacci_cython.pyx
Normal file
@ -0,0 +1,24 @@
|
||||
cdef unsigned long fibonacci(unsigned long n) nogil:
|
||||
if n <= 1:
|
||||
return n
|
||||
|
||||
cdef unsigned long a = 0, b = 1, c = 0
|
||||
|
||||
c = a + b
|
||||
for _i in range(2, n):
|
||||
a = b
|
||||
b = c
|
||||
c = a + b
|
||||
|
||||
return c
|
||||
|
||||
|
||||
def cython_nogil(unsigned long n):
|
||||
with nogil:
|
||||
value = fibonacci(n)
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def cython_gil(unsigned long n):
|
||||
return fibonacci(n)
|
Loading…
Reference in New Issue
Block a user