ch20: minor edits
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@ PRIME_FIXTURE = [
|
|||||||
NUMBERS = [n for n, _ in PRIME_FIXTURE]
|
NUMBERS = [n for n, _ in PRIME_FIXTURE]
|
||||||
|
|
||||||
# tag::IS_PRIME[]
|
# tag::IS_PRIME[]
|
||||||
def is_prime(n) -> bool:
|
def is_prime(n: int) -> bool:
|
||||||
if n < 2:
|
if n < 2:
|
||||||
return False
|
return False
|
||||||
if n == 2:
|
if n == 2:
|
||||||
@@ -35,7 +37,7 @@ def is_prime(n) -> bool:
|
|||||||
if n % 2 == 0:
|
if n % 2 == 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
root = math.floor(math.sqrt(n))
|
root = math.isqrt(n)
|
||||||
for i in range(3, root + 1, 2):
|
for i in range(3, root + 1, 2):
|
||||||
if n % i == 0:
|
if n % i == 0:
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -1,28 +1,35 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
procs.py: shows that multiprocessing on a multicore machine
|
||||||
|
can be faster than sequential code for CPU-intensive work.
|
||||||
|
"""
|
||||||
|
|
||||||
# tag::PRIMES_PROC_TOP[]
|
# tag::PRIMES_PROC_TOP[]
|
||||||
from time import perf_counter
|
from time import perf_counter
|
||||||
from typing import Tuple, NamedTuple
|
from typing import NamedTuple
|
||||||
from multiprocessing import Process, SimpleQueue, cpu_count # <1>
|
from multiprocessing import Process, SimpleQueue, cpu_count # <1>
|
||||||
from multiprocessing import queues # <2>
|
from multiprocessing import queues # <2>
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from primes import is_prime, NUMBERS
|
from primes import is_prime, NUMBERS
|
||||||
|
|
||||||
class Result(NamedTuple): # <3>
|
class PrimeResult(NamedTuple): # <3>
|
||||||
flag: bool
|
n: int
|
||||||
|
prime: bool
|
||||||
elapsed: float
|
elapsed: float
|
||||||
|
|
||||||
JobQueue = queues.SimpleQueue[int] # <4>
|
JobQueue = queues.SimpleQueue[int] # <4>
|
||||||
ResultQueue = queues.SimpleQueue[Tuple[int, Result]] # <5>
|
ResultQueue = queues.SimpleQueue[PrimeResult] # <5>
|
||||||
|
|
||||||
def check(n: int) -> Result: # <6>
|
def check(n: int) -> PrimeResult: # <6>
|
||||||
t0 = perf_counter()
|
t0 = perf_counter()
|
||||||
res = is_prime(n)
|
res = is_prime(n)
|
||||||
return Result(res, perf_counter() - t0)
|
return PrimeResult(n, res, perf_counter() - t0)
|
||||||
|
|
||||||
def worker(jobs: JobQueue, results: ResultQueue) -> None: # <7>
|
def worker(jobs: JobQueue, results: ResultQueue) -> None: # <7>
|
||||||
while n := jobs.get(): # <8>
|
while n := jobs.get(): # <8>
|
||||||
result = check(n) # <9>
|
results.put(check(n)) # <9>
|
||||||
results.put((n, result)) # <10>
|
|
||||||
# end::PRIMES_PROC_TOP[]
|
# end::PRIMES_PROC_TOP[]
|
||||||
|
|
||||||
# tag::PRIMES_PROC_MAIN[]
|
# tag::PRIMES_PROC_MAIN[]
|
||||||
@@ -32,11 +39,11 @@ def main() -> None:
|
|||||||
else:
|
else:
|
||||||
workers = int(sys.argv[1])
|
workers = int(sys.argv[1])
|
||||||
|
|
||||||
t0 = perf_counter()
|
print(f'Checking {len(NUMBERS)} numbers with {workers} processes:')
|
||||||
|
|
||||||
jobs: JobQueue = SimpleQueue() # <2>
|
jobs: JobQueue = SimpleQueue() # <2>
|
||||||
results: ResultQueue = SimpleQueue()
|
results: ResultQueue = SimpleQueue()
|
||||||
|
t0 = perf_counter()
|
||||||
print(f'Checking {len(NUMBERS)} numbers with {workers} processes:')
|
|
||||||
|
|
||||||
for n in NUMBERS: # <3>
|
for n in NUMBERS: # <3>
|
||||||
jobs.put(n)
|
jobs.put(n)
|
||||||
@@ -47,7 +54,7 @@ def main() -> None:
|
|||||||
jobs.put(0) # <6>
|
jobs.put(0) # <6>
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
n, (prime, elapsed) = results.get() # <7>
|
n, prime, elapsed = results.get() # <7>
|
||||||
label = 'P' if prime else ' '
|
label = 'P' if prime else ' '
|
||||||
print(f'{n:16} {label} {elapsed:9.6f}s') # <8>
|
print(f'{n:16} {label} {elapsed:9.6f}s') # <8>
|
||||||
if jobs.empty(): # <9>
|
if jobs.empty(): # <9>
|
||||||
|
|||||||
@@ -1,18 +1,26 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
sequential.py: baseline for comparing sequential, multiprocessing,
|
||||||
|
and threading code for CPU-intensive work.
|
||||||
|
"""
|
||||||
|
|
||||||
from time import perf_counter
|
from time import perf_counter
|
||||||
from typing import NamedTuple
|
from typing import NamedTuple
|
||||||
|
|
||||||
from primes import is_prime, NUMBERS
|
from primes import is_prime, NUMBERS
|
||||||
|
|
||||||
class Result(NamedTuple): # <1>
|
class Result(NamedTuple): # <1>
|
||||||
flag: bool
|
prime: bool
|
||||||
elapsed: float
|
elapsed: float
|
||||||
|
|
||||||
def check(n: int) -> Result: # <2>
|
def check(n: int) -> Result: # <2>
|
||||||
t0 = perf_counter()
|
t0 = perf_counter()
|
||||||
flag = is_prime(n)
|
prime = is_prime(n)
|
||||||
return Result(flag, perf_counter() - t0)
|
return Result(prime, perf_counter() - t0)
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
print(f'Checking {len(NUMBERS)} numbers sequentially:')
|
||||||
t0 = perf_counter()
|
t0 = perf_counter()
|
||||||
for n in NUMBERS: # <3>
|
for n in NUMBERS: # <3>
|
||||||
prime, elapsed = check(n)
|
prime, elapsed = check(n)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# spinner_async_experiment.py
|
# spinner_prime_async_nap.py
|
||||||
|
|
||||||
# credits: Example by Luciano Ramalho inspired by
|
# credits: Example by Luciano Ramalho inspired by
|
||||||
# Michele Simionato's multiprocessing example in the python-list:
|
# Michele Simionato's multiprocessing example in the python-list:
|
||||||
@@ -8,7 +8,7 @@ import asyncio
|
|||||||
import itertools
|
import itertools
|
||||||
import math
|
import math
|
||||||
|
|
||||||
# tag::SPINNER_ASYNC_NAP[]
|
# tag::PRIME_NAP[]
|
||||||
async def is_prime(n):
|
async def is_prime(n):
|
||||||
if n < 2:
|
if n < 2:
|
||||||
return False
|
return False
|
||||||
@@ -17,15 +17,14 @@ async def is_prime(n):
|
|||||||
if n % 2 == 0:
|
if n % 2 == 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
sleep = asyncio.sleep # <1>
|
root = math.isqrt(n)
|
||||||
root = math.floor(math.sqrt(n))
|
|
||||||
for i in range(3, root + 1, 2):
|
for i in range(3, root + 1, 2):
|
||||||
if n % i == 0:
|
if n % i == 0:
|
||||||
return False
|
return False
|
||||||
if i % 100_000 == 1: # <2>
|
if i % 100_000 == 1: # <2>
|
||||||
await sleep(0)
|
await asyncio.sleep(0)
|
||||||
return True
|
return True
|
||||||
# end::SPINNER_ASYNC_NAP[]
|
# end::PRIME_NAP[]
|
||||||
|
|
||||||
|
|
||||||
async def spin(msg: str) -> None:
|
async def spin(msg: str) -> None:
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
threads.py: shows that Python threads are slower than
|
||||||
|
sequential code for CPU-intensive work.
|
||||||
|
"""
|
||||||
|
|
||||||
from time import perf_counter
|
from time import perf_counter
|
||||||
from typing import Tuple, NamedTuple
|
from typing import NamedTuple
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from queue import SimpleQueue
|
from queue import SimpleQueue
|
||||||
import sys
|
import sys
|
||||||
@@ -7,22 +14,22 @@ import os
|
|||||||
|
|
||||||
from primes import is_prime, NUMBERS
|
from primes import is_prime, NUMBERS
|
||||||
|
|
||||||
class Result(NamedTuple):
|
class PrimeResult(NamedTuple): # <3>
|
||||||
flag: bool
|
n: int
|
||||||
|
prime: bool
|
||||||
elapsed: float
|
elapsed: float
|
||||||
|
|
||||||
JobQueue = SimpleQueue[int]
|
JobQueue = SimpleQueue[int]
|
||||||
ResultQueue = SimpleQueue[Tuple[int, Result]]
|
ResultQueue = SimpleQueue[PrimeResult]
|
||||||
|
|
||||||
def check(n: int) -> Result:
|
def check(n: int) -> PrimeResult:
|
||||||
t0 = perf_counter()
|
t0 = perf_counter()
|
||||||
res = is_prime(n)
|
res = is_prime(n)
|
||||||
return Result(res, perf_counter() - t0)
|
return PrimeResult(n, res, perf_counter() - t0)
|
||||||
|
|
||||||
def worker(jobs: JobQueue, results: ResultQueue) -> None:
|
def worker(jobs: JobQueue, results: ResultQueue) -> None:
|
||||||
while n := jobs.get():
|
while n := jobs.get():
|
||||||
result = check(n)
|
results.put(check(n))
|
||||||
results.put((n, result))
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
if len(sys.argv) < 2: # <1>
|
if len(sys.argv) < 2: # <1>
|
||||||
@@ -30,11 +37,11 @@ def main() -> None:
|
|||||||
else:
|
else:
|
||||||
workers = int(sys.argv[1])
|
workers = int(sys.argv[1])
|
||||||
|
|
||||||
t0 = perf_counter()
|
print(f'Checking {len(NUMBERS)} numbers with {workers} threads:')
|
||||||
|
|
||||||
jobs: JobQueue = SimpleQueue() # <2>
|
jobs: JobQueue = SimpleQueue() # <2>
|
||||||
results: ResultQueue = SimpleQueue()
|
results: ResultQueue = SimpleQueue()
|
||||||
|
t0 = perf_counter()
|
||||||
print(f'Checking {len(NUMBERS)} numbers with {workers} threads:')
|
|
||||||
|
|
||||||
for n in NUMBERS: # <3>
|
for n in NUMBERS: # <3>
|
||||||
jobs.put(n)
|
jobs.put(n)
|
||||||
@@ -45,7 +52,7 @@ def main() -> None:
|
|||||||
jobs.put(0) # <6>
|
jobs.put(0) # <6>
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
n, (prime, elapsed) = results.get() # <7>
|
n, prime, elapsed = results.get() # <7>
|
||||||
label = 'P' if prime else ' '
|
label = 'P' if prime else ' '
|
||||||
print(f'{n:16} {label} {elapsed:9.6f}s')
|
print(f'{n:16} {label} {elapsed:9.6f}s')
|
||||||
if jobs.empty(): # <8>
|
if jobs.empty(): # <8>
|
||||||
|
|||||||
Reference in New Issue
Block a user