Вычислить факториалы с потоками в Python - PullRequest
0 голосов
/ 06 августа 2020

Мне нужно проверить, является ли n = 17 простым числом: (n-1)! мод n = n-1. Для этого сначала мне нужно вычислить факториал от 16 до 4 потоков, это означает, что интервал 1..16 должен быть разделен на 4 подинтервала: 1..4, 5..8, 9..12, 14 ..16. Мне удалось проверить, является ли 17 простым числом через 16 потоков, по одному на каждую операцию, но я не знаю, как я могу разделить его так, чтобы операции выполнялись только в 4 потоках.

Я был бы очень признателен за идеи, спасибо!

Вот мой код:

import threading

n = 17
t = n-1
ts = []
num = (n-1)/t
       
def calcFak():
    for i in range(t):
        c = i*(n-1)/t+1
        thread = threading.Thread(target=threads, args = (c,))
        ts.append(thread)
        thread.start()
        thread.join()
        

def threads(var):
    print(f"start thread {var}")
    global num
    num = num * var
    print(f"end thread {var}")

def managerThread(thread):
    calcFak()
    print(num)
    if num % n == t:
         print(n, ' is Prime')
    else:
         print(n, ' is not Prime')
    
    
t2 = threading.Thread(target = managerThread, args=(ts,))
t2.start()

1 Ответ

0 голосов
/ 06 августа 2020

Прямо сейчас вы вычисляете все последовательно из-за оператора thread join() в вашей функции calcFak(). Таким образом, выполнение вашей функции прямо сейчас фактически такое же, как и в приведенном ниже коде:

n = 17
t = n - 1
num = t/t

for i in range(t):
    c = i*t/t + 1
    print(f'Start {c}')
    num = num * c
    print(f'End thread {c}')

print(num)
if num % n == t:
    print(f'{n} is a prime number')
else:
    print(f'{n} is not a prime number')

Как видите, нет преимущества от потоковой передачи. Вместо этого используйте очереди и рабочие функции, чтобы разделить выполнение вашей программы:

import threading
from queue import Queue
import time
n = 17
t = n - 1
num = t/t

# For threading
q = Queue()
num_lock = threading.Lock() # Lock so that no threads can overwrite our num value
threads = []                # List to store created threads

# Our worker gets items from the queue and processes them
def worker():
    global num
    while True:
        if not q.empty():
            c = q.get()
            num_lock.acquire()
            num = num * c
            num_lock.release()
            q.task_done()

for i in range(t):
    q.put(i*t/t + 1)

for thread in range(4):
    threads.append(threading.Thread(target=worker))
    threads[-1].daemon = True
    threads[-1].start()
    print('Made 1 thread')

q.join()

if num % n == t:
    print(f'{n} is a prime number')
else:
    print(f'{n} is not a prime number')

# Prints:
# Made 1 thread
# Made 1 thread
# Made 1 thread
# Made 1 thread
# 17 is a prime number

В приведенном выше коде мы создаем очередь, в которой хранятся данные для использования рабочими функциями. Рабочие функции блокируют переменную num и затем изменяют ее. Когда очередь пуста (что происходит после того, как мы присоединяемся к очереди с помощью q.join()), мы затем получаем доступ к окончательному значению переменной num, чтобы определить, является ли число простым или нет.

...