ch20 files
This commit is contained in:
parent
07856d4f30
commit
a3bf91bc59
260
20-concurrency/primes/log-procs.txt
Normal file
260
20-concurrency/primes/log-procs.txt
Normal file
@ -0,0 +1,260 @@
|
||||
1 42.05
|
||||
2 22.81
|
||||
3 15.95
|
||||
4 13.28
|
||||
5 12.27
|
||||
6 10.38
|
||||
7 11.00
|
||||
8 11.41
|
||||
9 12.17
|
||||
10 12.69
|
||||
11 11.34
|
||||
12 11.35
|
||||
13 10.88
|
||||
14 11.63
|
||||
15 11.79
|
||||
16 11.49
|
||||
17 11.29
|
||||
18 10.78
|
||||
19 10.92
|
||||
20 11.07
|
||||
1 40.47
|
||||
2 22.93
|
||||
3 15.88
|
||||
4 13.25
|
||||
5 12.22
|
||||
6 10.95
|
||||
7 10.81
|
||||
8 11.26
|
||||
9 11.96
|
||||
10 12.43
|
||||
11 11.19
|
||||
12 10.91
|
||||
13 11.03
|
||||
14 10.56
|
||||
15 10.62
|
||||
16 11.73
|
||||
17 11.00
|
||||
18 12.81
|
||||
19 12.38
|
||||
20 11.28
|
||||
1 40.81
|
||||
2 22.79
|
||||
3 15.83
|
||||
4 13.27
|
||||
5 12.33
|
||||
6 10.65
|
||||
7 10.94
|
||||
8 11.48
|
||||
9 11.78
|
||||
10 12.78
|
||||
11 11.31
|
||||
12 10.97
|
||||
13 10.80
|
||||
14 10.93
|
||||
15 10.69
|
||||
16 10.57
|
||||
17 10.54
|
||||
18 10.55
|
||||
19 10.79
|
||||
20 10.64
|
||||
1 40.85
|
||||
2 22.67
|
||||
3 16.05
|
||||
4 13.21
|
||||
5 12.53
|
||||
6 10.84
|
||||
7 10.80
|
||||
8 11.31
|
||||
9 11.69
|
||||
10 12.51
|
||||
11 11.22
|
||||
12 11.35
|
||||
13 11.00
|
||||
14 10.64
|
||||
15 10.89
|
||||
16 10.49
|
||||
17 10.55
|
||||
18 10.76
|
||||
19 10.54
|
||||
20 10.75
|
||||
1 40.41
|
||||
2 22.75
|
||||
3 15.87
|
||||
4 13.19
|
||||
5 12.33
|
||||
6 10.50
|
||||
7 10.84
|
||||
8 11.55
|
||||
9 11.79
|
||||
10 12.53
|
||||
11 11.24
|
||||
12 11.13
|
||||
13 10.89
|
||||
14 10.52
|
||||
15 10.74
|
||||
16 10.68
|
||||
17 10.88
|
||||
18 10.61
|
||||
19 11.07
|
||||
20 10.71
|
||||
1 40.45
|
||||
2 22.73
|
||||
3 16.35
|
||||
4 13.09
|
||||
5 12.19
|
||||
6 10.39
|
||||
7 11.01
|
||||
8 11.30
|
||||
9 11.81
|
||||
10 12.24
|
||||
11 11.21
|
||||
12 11.13
|
||||
13 10.66
|
||||
14 10.56
|
||||
15 10.91
|
||||
16 10.49
|
||||
17 10.58
|
||||
18 10.61
|
||||
19 10.60
|
||||
20 10.69
|
||||
1 40.36
|
||||
2 22.64
|
||||
3 15.95
|
||||
4 13.20
|
||||
5 12.27
|
||||
6 10.34
|
||||
7 10.47
|
||||
8 11.34
|
||||
9 11.68
|
||||
10 12.30
|
||||
11 11.04
|
||||
12 10.85
|
||||
13 10.78
|
||||
14 10.64
|
||||
15 10.63
|
||||
16 10.58
|
||||
17 10.67
|
||||
18 10.64
|
||||
19 10.71
|
||||
20 10.68
|
||||
1 40.70
|
||||
2 22.71
|
||||
3 15.81
|
||||
4 13.10
|
||||
5 12.29
|
||||
6 10.34
|
||||
7 10.40
|
||||
8 11.40
|
||||
9 11.71
|
||||
10 12.56
|
||||
11 11.29
|
||||
12 10.99
|
||||
13 10.51
|
||||
14 10.69
|
||||
15 10.53
|
||||
16 11.04
|
||||
17 10.67
|
||||
18 10.71
|
||||
19 10.86
|
||||
20 10.78
|
||||
1 40.69
|
||||
2 22.80
|
||||
3 15.88
|
||||
4 13.13
|
||||
5 12.19
|
||||
6 10.36
|
||||
7 10.77
|
||||
8 11.32
|
||||
9 11.66
|
||||
10 12.29
|
||||
11 11.06
|
||||
12 10.89
|
||||
13 10.66
|
||||
14 10.61
|
||||
15 10.36
|
||||
16 10.57
|
||||
17 10.94
|
||||
18 10.57
|
||||
19 10.81
|
||||
20 10.72
|
||||
1 40.81
|
||||
2 22.76
|
||||
3 15.84
|
||||
4 13.10
|
||||
5 12.25
|
||||
6 10.33
|
||||
7 10.58
|
||||
8 11.51
|
||||
9 11.69
|
||||
10 12.45
|
||||
11 11.51
|
||||
12 11.53
|
||||
13 10.61
|
||||
14 10.52
|
||||
15 10.57
|
||||
16 10.57
|
||||
17 10.76
|
||||
18 10.60
|
||||
19 10.66
|
||||
20 10.73
|
||||
1 40.84
|
||||
2 22.83
|
||||
3 15.86
|
||||
4 13.27
|
||||
5 12.39
|
||||
6 10.45
|
||||
7 10.87
|
||||
8 11.42
|
||||
9 11.70
|
||||
10 12.55
|
||||
11 11.43
|
||||
12 10.98
|
||||
13 10.81
|
||||
14 10.69
|
||||
15 10.68
|
||||
16 10.71
|
||||
17 10.80
|
||||
18 10.76
|
||||
19 10.90
|
||||
20 11.02
|
||||
1 40.99
|
||||
2 22.99
|
||||
3 16.10
|
||||
4 13.46
|
||||
5 12.45
|
||||
6 10.47
|
||||
7 10.79
|
||||
8 11.74
|
||||
9 11.64
|
||||
10 12.37
|
||||
11 11.20
|
||||
12 11.09
|
||||
13 10.82
|
||||
14 10.61
|
||||
15 10.56
|
||||
16 10.53
|
||||
17 10.60
|
||||
18 10.81
|
||||
19 10.72
|
||||
20 10.62
|
||||
1 40.94
|
||||
2 23.09
|
||||
3 16.03
|
||||
4 13.40
|
||||
5 12.51
|
||||
6 10.38
|
||||
7 10.58
|
||||
8 11.37
|
||||
9 11.75
|
||||
10 12.87
|
||||
11 12.11
|
||||
12 11.37
|
||||
13 11.84
|
||||
14 11.30
|
||||
15 11.29
|
||||
16 11.36
|
||||
17 11.01
|
||||
18 11.37
|
||||
19 11.07
|
||||
20 10.94
|
@ -1,8 +1,9 @@
|
||||
# tag::PRIMES_PROC_TOP[]
|
||||
from time import perf_counter
|
||||
from typing import Tuple, List, NamedTuple
|
||||
from multiprocessing import Process, SimpleQueue # <1>
|
||||
from typing import Tuple, NamedTuple
|
||||
from multiprocessing import Process, SimpleQueue, cpu_count # <1>
|
||||
from multiprocessing import queues # <2>
|
||||
import sys
|
||||
|
||||
from primes import is_prime, NUMBERS
|
||||
|
||||
@ -10,33 +11,47 @@ class Result(NamedTuple): # <3>
|
||||
flag: bool
|
||||
elapsed: float
|
||||
|
||||
JobQueue = queues.SimpleQueue[Tuple[int, Result]] # <4>
|
||||
JobQueue = queues.SimpleQueue[int] # <4>
|
||||
ResultQueue = queues.SimpleQueue[Tuple[int, Result]] # <5>
|
||||
|
||||
def check(n: int) -> Result: # <5>
|
||||
def check(n: int) -> Result: # <6>
|
||||
t0 = perf_counter()
|
||||
res = is_prime(n)
|
||||
return Result(res, perf_counter() - t0)
|
||||
|
||||
def job(n: int, results: JobQueue) -> None: # <6>
|
||||
results.put((n, check(n))) # <7>
|
||||
def worker(jobs: JobQueue, results: ResultQueue) -> None: # <7>
|
||||
while n := jobs.get(): # <8>
|
||||
result = check(n) # <9>
|
||||
results.put((n, result)) # <10>
|
||||
# end::PRIMES_PROC_TOP[]
|
||||
|
||||
# tag::PRIMES_PROC_MAIN[]
|
||||
def main() -> None:
|
||||
if len(sys.argv) < 2: # <1>
|
||||
workers = cpu_count()
|
||||
else:
|
||||
workers = int(sys.argv[1])
|
||||
|
||||
t0 = perf_counter()
|
||||
results: JobQueue = SimpleQueue() # <1>
|
||||
workers: List[Process] = [] # <2>
|
||||
jobs: JobQueue = SimpleQueue() # <2>
|
||||
results: ResultQueue = SimpleQueue()
|
||||
|
||||
for n in NUMBERS:
|
||||
worker = Process(target=job, args=(n, results)) # <3>
|
||||
worker.start() # <4>
|
||||
workers.append(worker) # <5>
|
||||
print(f'Checking {len(NUMBERS)} numbers with {workers} processes:')
|
||||
|
||||
for _ in workers: # <6>
|
||||
for n in NUMBERS: # <3>
|
||||
jobs.put(n)
|
||||
|
||||
for _ in range(workers):
|
||||
proc = Process(target=worker, args=(jobs, results)) # <4>
|
||||
proc.start() # <5>
|
||||
jobs.put(0) # <6>
|
||||
|
||||
while True:
|
||||
n, (prime, elapsed) = results.get() # <7>
|
||||
label = 'P' if prime else ' '
|
||||
print(f'{n:16} {label} {elapsed:9.6f}s')
|
||||
|
||||
print(f'{n:16} {label} {elapsed:9.6f}s') # <8>
|
||||
if jobs.empty(): # <9>
|
||||
break
|
||||
|
||||
time = perf_counter() - t0
|
||||
print('Total time:', f'{time:0.2f}s')
|
||||
|
2
20-concurrency/primes/run_procs.sh
Executable file
2
20-concurrency/primes/run_procs.sh
Executable file
@ -0,0 +1,2 @@
|
||||
#/bin/bash
|
||||
for i in {1..20}; do echo -n $i; python3 procs.py $i | tail -1; done
|
40
20-concurrency/primes/spinner_prime_async_broken.py
Normal file
40
20-concurrency/primes/spinner_prime_async_broken.py
Normal file
@ -0,0 +1,40 @@
|
||||
# spinner_async_experiment.py
|
||||
|
||||
# credits: Example by Luciano Ramalho inspired by
|
||||
# Michele Simionato's multiprocessing example in the python-list:
|
||||
# https://mail.python.org/pipermail/python-list/2009-February/675659.html
|
||||
|
||||
import asyncio
|
||||
import itertools
|
||||
|
||||
import primes
|
||||
|
||||
async def spin(msg: str) -> None:
|
||||
for char in itertools.cycle(r'\|/-'):
|
||||
status = f'\r{char} {msg}'
|
||||
print(status, flush=True, end='')
|
||||
try:
|
||||
await asyncio.sleep(.1)
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
print('THIS WILL NEVER BE OUTPUT')
|
||||
|
||||
async def check(n: int) -> int:
|
||||
return primes.is_prime(n) # <4>
|
||||
|
||||
async def supervisor(n: int) -> int:
|
||||
spinner = asyncio.create_task(spin('thinking!')) # <1>
|
||||
print('spinner object:', spinner) # <2>
|
||||
result = await check(n) # <3>
|
||||
spinner.cancel() # <5>
|
||||
return result
|
||||
# end::SPINNER_ASYNC_EXPERIMENT[]
|
||||
|
||||
def main() -> None:
|
||||
n = 5_000_111_000_222_021
|
||||
result = asyncio.run(supervisor(n))
|
||||
msg = 'is' if result else 'is not'
|
||||
print(f'{n:,} {msg} prime')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
59
20-concurrency/primes/spinner_prime_async_nap.py
Normal file
59
20-concurrency/primes/spinner_prime_async_nap.py
Normal file
@ -0,0 +1,59 @@
|
||||
# spinner_async_experiment.py
|
||||
|
||||
# credits: Example by Luciano Ramalho inspired by
|
||||
# Michele Simionato's multiprocessing example in the python-list:
|
||||
# https://mail.python.org/pipermail/python-list/2009-February/675659.html
|
||||
|
||||
import asyncio
|
||||
import itertools
|
||||
import math
|
||||
|
||||
# tag::SPINNER_ASYNC_NAP[]
|
||||
async def is_prime(n):
|
||||
if n < 2:
|
||||
return False
|
||||
if n == 2:
|
||||
return True
|
||||
if n % 2 == 0:
|
||||
return False
|
||||
|
||||
sleep = asyncio.sleep # <1>
|
||||
root = int(math.floor(math.sqrt(n)))
|
||||
for i in range(3, root + 1, 2):
|
||||
if n % i == 0:
|
||||
return False
|
||||
if i % 100_000 == 1: # <2>
|
||||
await sleep(0)
|
||||
return True
|
||||
# end::SPINNER_ASYNC_NAP[]
|
||||
|
||||
|
||||
async def spin(msg: str) -> None:
|
||||
for char in itertools.cycle(r'\|/-'):
|
||||
status = f'\r{char} {msg}'
|
||||
print(status, flush=True, end='')
|
||||
try:
|
||||
await asyncio.sleep(.1)
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
blanks = ' ' * len(status)
|
||||
print(f'\r{blanks}\r', end='')
|
||||
|
||||
async def check(n: int) -> int:
|
||||
return await is_prime(n) # <4>
|
||||
|
||||
async def supervisor(n: int) -> int:
|
||||
spinner = asyncio.create_task(spin('thinking!')) # <1>
|
||||
print('spinner object:', spinner) # <2>
|
||||
result = await check(n) # <3>
|
||||
spinner.cancel() # <5>
|
||||
return result
|
||||
|
||||
def main() -> None:
|
||||
n = 5_000_111_000_222_021
|
||||
result = asyncio.run(supervisor(n))
|
||||
msg = 'is' if result else 'is not'
|
||||
print(f'{n:,} {msg} prime')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
44
20-concurrency/primes/spinner_prime_proc.py
Normal file
44
20-concurrency/primes/spinner_prime_proc.py
Normal file
@ -0,0 +1,44 @@
|
||||
# spinner_prime_proc.py
|
||||
|
||||
# credits: Adapted from Michele Simionato's
|
||||
# multiprocessing example in the python-list:
|
||||
# https://mail.python.org/pipermail/python-list/2009-February/675659.html
|
||||
|
||||
from multiprocessing import Process, Event
|
||||
from multiprocessing import synchronize
|
||||
import itertools
|
||||
import time
|
||||
|
||||
from primes import is_prime
|
||||
|
||||
def spin(msg: str, done: synchronize.Event) -> None: # <1>
|
||||
for char in itertools.cycle(r'\|/-'): # <2>
|
||||
status = f'\r{char} {msg}' # <3>
|
||||
print(status, end='', flush=True)
|
||||
if done.wait(.1): # <4>
|
||||
break # <5>
|
||||
blanks = ' ' * len(status)
|
||||
print(f'\r{blanks}\r', end='') # <6>
|
||||
|
||||
def check(n: int) -> int:
|
||||
return is_prime(n)
|
||||
|
||||
def supervisor(n: int) -> int: # <1>
|
||||
done = Event() # <2>
|
||||
spinner = Process(target=spin,
|
||||
args=('thinking!', done)) # <3>
|
||||
print('spinner object:', spinner) # <4>
|
||||
spinner.start() # <5>
|
||||
result = check(n) # <6>
|
||||
done.set() # <7>
|
||||
spinner.join() # <8>
|
||||
return result
|
||||
|
||||
def main() -> None:
|
||||
n = 5_000_111_000_222_021
|
||||
result = supervisor(n) # <9>
|
||||
msg = 'is' if result else 'is not'
|
||||
print(f'{n:,} {msg} prime')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
43
20-concurrency/primes/spinner_prime_thread.py
Normal file
43
20-concurrency/primes/spinner_prime_thread.py
Normal file
@ -0,0 +1,43 @@
|
||||
# spinner_prime_thread.py
|
||||
|
||||
# credits: Adapted from Michele Simionato's
|
||||
# multiprocessing example in the python-list:
|
||||
# https://mail.python.org/pipermail/python-list/2009-February/675659.html
|
||||
|
||||
from threading import Thread, Event
|
||||
import itertools
|
||||
import time
|
||||
|
||||
from primes import is_prime
|
||||
|
||||
def spin(msg: str, done: Event) -> None: # <1>
|
||||
for char in itertools.cycle(r'\|/-'): # <2>
|
||||
status = f'\r{char} {msg}' # <3>
|
||||
print(status, end='', flush=True)
|
||||
if done.wait(.1): # <4>
|
||||
break # <5>
|
||||
blanks = ' ' * len(status)
|
||||
print(f'\r{blanks}\r', end='') # <6>
|
||||
|
||||
def check(n: int) -> int:
|
||||
return is_prime(n)
|
||||
|
||||
def supervisor(n: int) -> int: # <1>
|
||||
done = Event() # <2>
|
||||
spinner = Thread(target=spin,
|
||||
args=('thinking!', done)) # <3>
|
||||
print('spinner object:', spinner) # <4>
|
||||
spinner.start() # <5>
|
||||
result = check(n) # <6>
|
||||
done.set() # <7>
|
||||
spinner.join() # <8>
|
||||
return result
|
||||
|
||||
def main() -> None:
|
||||
n = 5_000_111_000_222_021
|
||||
result = supervisor(n) # <9>
|
||||
msg = 'is' if result else 'is not'
|
||||
print(f'{n:,} {msg} prime')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
437
20-concurrency/primes/stats-procs.ipynb
Normal file
437
20-concurrency/primes/stats-procs.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -1,38 +1,55 @@
|
||||
from time import perf_counter
|
||||
from typing import Tuple, List, NamedTuple
|
||||
from typing import Tuple, NamedTuple
|
||||
from threading import Thread
|
||||
from queue import SimpleQueue
|
||||
import sys
|
||||
import os
|
||||
|
||||
from primes import is_prime, NUMBERS
|
||||
|
||||
class Result(NamedTuple): # <3>
|
||||
class Result(NamedTuple):
|
||||
flag: bool
|
||||
elapsed: float
|
||||
|
||||
JobQueue = SimpleQueue[Tuple[int, Result]] # <4>
|
||||
JobQueue = SimpleQueue[int]
|
||||
ResultQueue = SimpleQueue[Tuple[int, Result]]
|
||||
|
||||
def check(n: int) -> Result: # <5>
|
||||
def check(n: int) -> Result:
|
||||
t0 = perf_counter()
|
||||
res = is_prime(n)
|
||||
return Result(res, perf_counter() - t0)
|
||||
|
||||
def job(n: int, results: JobQueue) -> None: # <6>
|
||||
results.put((n, check(n))) # <7>
|
||||
def worker(jobs: JobQueue, results: ResultQueue) -> None:
|
||||
while n := jobs.get():
|
||||
result = check(n)
|
||||
results.put((n, result))
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) < 2: # <1>
|
||||
workers = os.cpu_count() or 1 # make mypy happy
|
||||
else:
|
||||
workers = int(sys.argv[1])
|
||||
|
||||
t0 = perf_counter()
|
||||
results: JobQueue = SimpleQueue() # <1>
|
||||
workers: List[Thread] = [] # <2>
|
||||
jobs: JobQueue = SimpleQueue() # <2>
|
||||
results: ResultQueue = SimpleQueue()
|
||||
|
||||
for n in NUMBERS:
|
||||
worker = Thread(target=job, args=(n, results)) # <3>
|
||||
worker.start() # <4>
|
||||
workers.append(worker) # <5>
|
||||
print(f'Checking {len(NUMBERS)} numbers with {workers} threads:')
|
||||
|
||||
for _ in workers: # <6>
|
||||
for n in NUMBERS: # <3>
|
||||
jobs.put(n)
|
||||
|
||||
for _ in range(workers):
|
||||
proc = Thread(target=worker, args=(jobs, results)) # <4>
|
||||
proc.start() # <5>
|
||||
jobs.put(0) # <6>
|
||||
|
||||
while True:
|
||||
n, (prime, elapsed) = results.get() # <7>
|
||||
label = 'P' if prime else ' '
|
||||
print(f'{n:16} {label} {elapsed:9.6f}s')
|
||||
if jobs.empty(): # <8>
|
||||
break
|
||||
|
||||
time = perf_counter() - t0
|
||||
print('Total time:', f'{time:0.2f}s')
|
||||
|
Loading…
Reference in New Issue
Block a user