In [3]:
%autosave 2
from threading import Thread
import numpy as np


Autosaving every 2 seconds

In [16]:
def f(x, a, b):
    return a * x + b

n = 1000001
n_threads = 8
x = np.linspace(0, 1, n)
A = np.vstack((x, np.ones_like(x))).T

In [19]:
%%timeit
a_ = []
b_ = []
for _ in range(n_threads):
    y = (f(x, np.pi, np.exp(1)) 
         + np.random.normal(scale=0.5, size=n))
    a, b = np.linalg.lstsq(A, y)[0]
    a_.append(a)
    b_.append(b)
print(np.mean(a_), np.mean(b_))


3.14220664203 2.71815634567
3.14069654484 2.71864064956
3.1426827339 2.71761093035
3.14249015067 2.71821100267
3.14177470172 2.71803291268
3.14181163949 2.71854866264
3.14275353473 2.7176756003
3.1408497011 2.71888592022
906 ms ± 4.81 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [26]:
%%timeit
a_ = []
b_ = []

def worker():
    y = (f(x, np.pi, np.exp(1)) 
         + np.random.normal(scale=0.5, size=n))
    a, b = np.linalg.lstsq(A, y)[0]
    a_.append(a)
    b_.append(b)

threads = []
for _ in range(n_threads):
    t = Thread(target=worker)
    t.start()
    threads.append(t)

for t in threads:
    t.join()
    
print(np.mean(a_), np.mean(b_))


3.1419662776 2.71820376126
3.14053027275 2.71877188493
3.1427158428 2.71770585038
3.14161738536 2.71829164475
3.14186456391 2.71831306611
3.14110026266 2.71852366228
3.14136275903 2.71849455803
3.14104486485 2.71822176794
500 ms ± 3.76 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [29]:
%%timeit
for _ in range(n_threads):
    y = np.random.normal(scale=0.5, size=n)


421 ms ± 589 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [30]:
%%timeit
def worker():
    y = np.random.normal(scale=0.5, size=n)

threads = []
for _ in range(n_threads):
    t = Thread(target=worker)
    t.start()
    threads.append(t)

for t in threads:
    t.join()


423 ms ± 929 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [ ]: