# Searches for the first five perfect numbers. # This version uses a multi-process pool for concurrency. import itertools import math # for sqrt import os import time from multiprocessing import Pool # returns the sum of the proper divisors of n def sum_divisors(n): root = int(math.sqrt(n)) result = sum((k + n // k for k in \ range(2, root + 1) if n % k == 0)) + 1 if n == root * root: result -= root return result # returns n if n is a perfect number, else None def is_perfect_number(n): if n == sum_divisors(n): return n # Runs the given function f, measuring how long it took to run. # Returns the elapsed runtime at the end of the call. def measure_runtime(f): start_time = time.time() f() elapsed_time = time.time() - start_time return elapsed_time # Finds and prints the first 5 perfect numbers. def find_perfect_numbers(): print("Searching for perfect numbers on", \ os.cpu_count(), "CPUs:") pool = Pool() results = pool.imap(is_perfect_number, itertools.count(1)) perfects = (n for n in results if n is not None) first_five = itertools.islice(perfects, 5) for k in first_five: print(k) def main(): runtime = measure_runtime(find_perfect_numbers) print("time =", runtime, "sec") main()