In [11]:
%autosave 60
import numpy as np
from threading import Thread
from functools import partial
import multiprocessing
import multiprocessing.pool
Autosaving every 60 seconds
In [4]:
N_CPU = multiprocessing.cpu_count()
REPEAT = 16 * N_CPU
In [7]:
from time import sleep

def f():
    sleep(3)
    print('hello')
    
t = Thread(target=f)
t.start()
print('world')
t.join()
print('!')
world
hello
!
In [8]:
A = np.random.normal(0, 1, (64, 64, 5, 5))

%timeit np.linalg.eigvals(A)
35.9 ms ± 497 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [13]:
%%timeit A = np.random.normal(0, 1, (64, 64, 5, 5))
with multiprocessing.pool.ThreadPool() as pool:
    pool.map(lambda _: np.linalg.eigvals(A), range(REPEAT))
718 ms ± 35.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [16]:
class Eigen:
    def __init__(self):
        self.A = np.random.normal(0, 1, (64, 64, 5, 5))
    
    def __call__(self, x):
        A = self.A.copy()
        A[0, 0] += x
        vals = np.linalg.eigvals(A)
        return np.linalg.norm(vals)

f = Eigen()
In [18]:
%%timeit
with multiprocessing.pool.ThreadPool() as pool:
    pool.map(f, range(REPEAT))
1.38 s ± 43.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [19]:
%timeit [f(x) for x in range(REPEAT)]
4.61 s ± 31.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [21]:
def golden_ratio(n):
    s = 1.0
    for _ in range(n):
        s = 1.0 + 1.0 / s
    return s
Out[21]:
1.6179775280898876
In [25]:
%timeit [golden_ratio(100_000) for _ in range(REPEAT)]
884 ms ± 23.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [26]:
%%timeit
with multiprocessing.pool.ThreadPool() as pool:
    pool.map(lambda _: golden_ratio(100_000), range(REPEAT))
945 ms ± 29 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [27]:
# GIL
In [ ]: