2 回答
TA贡献1826条经验 获得超6个赞
您可以使用该multiprocessing库来完成此操作。基本思想是有两组流程。第一个过程可以queue用素数填充 a,然后您可以委托其他过程来处理这些素数并打印您的完美数字。
我确实做了一些更改并实现了一个基本is_prime功能。(请注意,对于此实现,您只需要检查直到数字的平方根)。有更好的方法,但这不是这个问题的目的。
无论如何,我们的append_primes函数与您的第一个循环相同,除了不是将素数附加到列表中,而是将素数放入队列中。我们需要某种信号来表明我们已经完成了附加素数,这就是我们q.put("DONE")最后的原因。"DONE"只要处理得当,它是任意的,可以是您想要的任何类型的信号。
然后,这perfect_number有点像你的第二个循环。它接受一个素数并打印出一个完美数(如果存在)。您可能希望将其退回,但这取决于您的要求。
最后,运行和执行多处理的所有逻辑都必须位于一个if __name__ == "__main__"块内,以避免在文件被腌制并发送到新进程时一遍又一遍地重新运行。我们初始化我们的队列并创建/启动将素数附加到该队列的过程。
当它运行时,我们创建了我们自己的多处理池版本。标准 mp 池不与队列一起玩,所以我们必须有点花哨。我们初始化我们想要运行的最大进程数,并将其设置为当前 cpu 计数减 1(因为 1 将运行该append_primes函数。
我们循环q直到"DONE"返回(记住,这是我们的信号来自append_primes)。我们将不断循环处理进程池,直到找到可用的进程。一旦发生这种情况,我们将创建并启动该过程,然后继续进行下一个数字。
processes最后,我们进行一些清理,并通过调用哪些块来确保所有内容都完成,Process.join()直到进程完成执行。我们也确保prime_finder已经完成。
import multiprocessing as mp
import os
import queue
import time
def is_prime(n):
""" Returns True if n is prime """
for i in range(2, int(n**0.5)):
if n%i == 0:
return False
return True
def append_primes(max, q):
""" Searches for primes between 2 and max and adds them to the Queue (q) """
pid = os.getpid()
for num in range(2, int(max)+1):
if is_prime(num):
print(f"{pid} :: Put {num} in queue.")
q.put(num)
q.put("DONE") # A signal to stop processing
return
def perfect_number(prime, limit = 25000000000000000000):
""" Prints the perfect number, if it exists, given the prime """
pp = 2**prime
perfect = (pp - 1) * (pp // 2)
if perfect > limit:
return
if is_prime(pp - 1):
print(f"{os.getpid()} :: Perfect: {perfect}", flush = True)
return
if __name__ == "__main__":
q = mp.Queue()
max = 1000 # When to stop looking for primes
prime_finder = mp.Process(target = append_primes, args = (max, q,))
prime_finder.start()
n_processes = os.cpu_count() - 1 # -1 because 1 is for prime_finder
processes = [None]*n_processes
for prime in iter(q.get, "DONE"):
proc_started = False
while not proc_started: # Check each process till we find an 'available' one.
for m, proc in enumerate(processes):
if proc is None or not proc.is_alive():
processes[m] = mp.Process(target = perfect_number, args = (prime, ))
processes[m].start()
proc_started = True # Get us out of the while loop
break # and out of the for loop.
for proc in processes:
if proc is None: # In case max < n_processes
continue
proc.join()
prime_finder.join()
如果您只想查看完美数字,请注释掉其中的print语句。append_primes前面出现的数字是进程的ID(只是为了让你可以看到有多个进程同时工作)
TA贡献1784条经验 获得超9个赞
当您可以将第二个循环的逻辑放在第一个循环中时,为什么要同时执行 2 个 for 循环:只是使用 bool 来确定您是否已达到限制,而不是完美循环中的 break。
你也不需要检查if num > 1。只需从范围开始2
primes=[]
limit = 25_000_000_000_000_000_000
reached_limit = False
def is_prime(n):
return 2 in [n,2**n%n]
for num in range(2, 1_000_000_000_000):
for i in range(2,num):
if (num % i) == 0:
break
else:
primes.append(num)
if not reached_limit:
pp = 2 ** num
perfect = (pp - 1) * (pp // 2)
if perfect > limit:
reached_limit = True
elif is_prime(pp-1):
print(perfect)
添加回答
举报