Получить значения из многопроцессорной библиотеки - PullRequest
0 голосов
/ 03 апреля 2020

Я пытаюсь использовать многопроцессорную библиотеку для сравнения производительности моего процессора на 1 ядре против 2 ядер. Поэтому я рассчитываю отличный продукт, используя 1 л oop, 2 цикла на 1 ядре и 2 цикла на 2 ядра (1 ядро ​​/ л oop). Проблема в том, что значения D1.result и D2.result равны 0 , хотя ожидается, что они будут произведением "half / l * 1020". *». Код следующий:

import random
from multiprocessing import Process as Task, freeze_support
N = 10 ** 3
l = [random.randint(2 ** 999, 2 ** 1000 - 1) for x in range(N)]
# ---------------------------------------------------------------
class Loop:
    def __init__(self):
        self.result=0
    def boucle(self,start,end):
        self.result = l[start]
        for v in l[start+1:end]:
            self.result = self.result*v
# ---------------------------------------------------------------
if __name__=="__main__":
    print("1 Loop without multiprocessing")
    A=Loop()
    sta = time.time()
    ra=A.boucle(0,N)
    end = time.time()
    print("--> Time :", end - sta)
    #----------------------------------------------------------------------
    print("2 Loops without multiprocessing")
    B1=Loop()
    B2=Loop()
    sta = time.time()
    rb1 = B1.boucle(0, N//2)
    rb2 = B2.boucle(N//2, N)
    rb = B1.result*B2.result
    end = time.time()
    print("--> Time :", end - sta)
    if rb - A.result == 0 :  
        check="OK"
    else :
        check="fail"
    print("--> Check :", check)
    # ----------------------------------------------------------------------
    print("2 Loops with multiprocessing")
    freeze_support()
    D1=Loop()
    D2=Loop()
    v1 = Task(target=D1.boucle, args=(0,N//2))
    v2 = Task(target=D2.boucle, args=(N//2,N))
    sta = time.time()
    v1.start()
    v2.start()
    v1.join()
    v2.join()
    rd = D1.result*D2.result
    end = time.time()
    print("D1",D1.result)
    print("D2",D2.result)
    print("--> Time :", end - sta)
    if rd - A.result == 0 :    
        check="OK"
    else :
        check="fail"
    print("--> Check :", check)

Результат этого кода:

1 Loop without multiprocessing
--> Time : 0.5025153160095215
2 Loops without multiprocessing
--> Time : 0.283463716506958
--> Check : OK
2 Loops with multiprocessing
D1 0
D2 0
--> Time : 0.2579989433288574
--> Check : fail

Process finished with exit code 0

Почему D1 0 и D2 0 и не результат l oop? Спасибо тебе!

1 Ответ

0 голосов
/ 03 апреля 2020

Проблема с этим кодом отображается при отображении D1 и D2: в многопроцессорной обработке задачи выполняются в раздвоенном процессе. Этот процесс получил копию данных. В каждом разветвленном процессе значение вычисляется правильно, но оно никогда не отправляется обратно в основной процесс.

Чтобы обойти это, вы можете:

  • Использовать общую память для хранения результат, но в этом случае вы ограничены C типами. Ваши числа не умещаются в 64 бита (максимальный целочисленный размер в C), поэтому это не очень хорошее решение.

  • Использовать пул процессов, поэтому данные будут передаваться с использованием очереди, и вы сможете управлять реальными python типами.

Эта последняя опция требует, чтобы функция "boucle" возвращала результат.

Вот код:

import random
from multiprocessing import Process as Task, freeze_support, Pool
import time

N = 10 ** 3
l = [random.randint(2 ** 999, 2 ** 1000 - 1) for x in range(N)]


# ---------------------------------------------------------------
class Loop:
    def __init__(self):
        self.result = 0

    def boucle(self, start, end):
        self.result = l[start]

        for v in l[start + 1:end]:
            self.result = self.result * v

        return self.result


# ---------------------------------------------------------------
if __name__ == "__main__":
    print("1 Loop without multiprocessing")
    A = Loop()
    sta = time.time()
    ra = A.boucle(0, N)
    end = time.time()
    print("--> Time :", end - sta)
    # ----------------------------------------------------------------------

    print("2 Loops without multiprocessing")
    B1 = Loop()
    B2 = Loop()
    sta = time.time()
    rb1 = B1.boucle(0, N // 2)
    rb2 = B2.boucle(N // 2, N)
    rb = B1.result * B2.result
    end = time.time()
    print("--> Time :", end - sta)
    if rb - A.result == 0:
        check = "OK"
    else:
        check = "fail"
    print("--> Check :", check)
    # ----------------------------------------------------------------------
    print("2 Loops with multiprocessing")
    freeze_support()
    D1 = Loop()
    D2 = Loop()

    pool = Pool(processes=2)

    with pool:
        sta = time.time()
        sta = time.time()
        rb1 = pool.apply_async(B1.boucle, (0, N // 2))
        rb2 = pool.apply_async(B2.boucle, (N // 2, N))

        v1 = rb1.get()
        v2 = rb2.get()

        rd = v1 * v2
        end = time.time()

        print("D1", D1.result)
        print("D2", D2.result)
    print("--> Time :", end - sta)
    if rd - A.result == 0:
        check = "OK"
    else:
        check = "fail"
    print("--> Check :", check)

И результат:

1 Loop without multiprocessing
--> Time : 0.3473360538482666
2 Loops without multiprocessing
--> Time : 0.18696999549865723
--> Check : OK
2 Loops with multiprocessing
D1 0
D2 0
--> Time : 0.1116642951965332
--> Check : OK

Вы также можете использовать карту с пулом, чтобы вернуть значение, но я не пробовал в этом случае, потому что вы вызываете только 2 функции и работники пула получают задачи с помощью «пакетов функций - см. maxtaskperchild», поэтому вполне возможно, что только один работник получит 2 функции для себя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...