<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 numpy.vectorize
Step1:  Multi-core processing
Step2:  Single core
Step3:  Threads
```python
%%time
args = [(x, i) for i, x in enumerate(data)]
def plot_one_(arg)
Step4:  Parallel comprehensions with joblib
Step5:  Blocking and non-blocking calls
<ASSISTANT_TASK:>
Python Code:
def in_unit_circle(x, y):
    if x**2 + y**2 < 1:
        return 1
    else:
        return 0
@numba.vectorize('int64(float64, float64)',target='cpu')
def in_unit_circle_serial(x, y):
    if x**2 + y**2 < 1:
        return 1
    else:
        return 0
@numba.vectorize('int64(float64, float64)',target='parallel')
def in_unit_circle_multicore(x, y):
    if x**2 + y**2 < 1:
        return 1
    else:
        return 0
n = int(1e7)
xs, ys = np.random.random((2, n))
%%time
4 * np.sum(in_unit_circle(x, y) for x, y in zip(xs, ys))/n
%%time
4 * np.sum(in_unit_circle_serial(xs, ys))/n
%%time
4 * np.sum(in_unit_circle_multicore(xs, ys))/n
Explanation: numpy.vectorize
End of explanation
def plot_one(data, name):
    xs, ys = data.T
    plt.scatter(xs, ys, s=1, edgecolor=None)
    plt.savefig('%s.png' % name)
    return name
data = np.random.random((10, 10000, 2))
Explanation: Multi-core processing
End of explanation
%%time
for i, M in enumerate(data):
    plot_one(M, i)
Explanation: Single core
End of explanation
%%time
args = [(x, i) for i, x in enumerate(data)]
with mp.Pool() as pool:
    pool.starmap(plot_one, args)
%%time
args = [(x, i) for i, x in enumerate(data)]
with mp.Pool() as pool:
    results = pool.starmap_async(plot_one, args)
Explanation: Threads
```python
%%time
args = [(x, i) for i, x in enumerate(data)]
def plot_one_(arg):
    return plot_one(*arg)
with ThreadPoolExecutor() as pool:
    pool.map(plot_one_, args)
```
Processes
End of explanation
%%time
Parallel(n_jobs=-1)(delayed(plot_one)(x, i) for i, x in enumerate(data))
pass
Explanation: Parallel comprehensions with joblib
End of explanation
def f(x):
    import time
    
    time.sleep(np.random.randint(0, 5))
    return x
%%time
with mp.Pool(processes=4) as pool:
    result = pool.map(f, range(10))
result
%%time
pool = mp.Pool(processes=4)
result = pool.map_async(f, range(10))
if result.ready() and result.successful():
    print(result.get())
else:
    print(result.wait())
Explanation: Blocking and non-blocking calls
End of explanation
<END_TASK>