簡體   English   中英

在嵌套對象中使用 Python 多處理庫

[英]Using Python multiprocessing library inside nested objects

我正在嘗試使用多處理庫來並行化一些昂貴的計算,而不會阻塞其他一些計算,輕得多。 兩者都需要通過一些變量進行交互,盡管可能以不同的速度運行。

為了說明這一點,我創建了以下示例,該示例工作正常:

import multiprocessing
import time
import numpy as np


class SumClass:

    def __init__(self):

        self.result = 0.0
        self.p = None
        self.return_value = None

    def expensive_function(self, new_number, return_value):

        # Execute expensive calculation
        #######
        time.sleep(np.random.random_integers(5, 10, 1))
        return_value.value = self.result + new_number
        #######

    def execute_function(self, new_number):

        print(' New number received: %f' % new_number)
        self.return_value = multiprocessing.Value("f", 0.0, lock=True)
        self.p = multiprocessing.Process(target=self.expensive_function, args=(new_number, self.return_value))
        self.p.start()

    def is_executing(self):

        if self.p is not None:

            if not self.p.is_alive():
                self.result = self.return_value.value
                self.p = None
                return False

            else:
                return True

        else:
            return False


if __name__ == '__main__':

    sum_obj = SumClass()
    current_value = 0

    while True:

        if not sum_obj.is_executing():

            # Randomly determine whether the function must be executed or not
            if np.random.rand() < 0.25:
                print('Current sum value: %f' % sum_obj.result)
                new_number = np.random.rand(1)[0]
                sum_obj.execute_function(new_number)

        # Execute other (light) stuff
        #######
        print('Executing other stuff')
        current_value += sum_obj.result * 0.1
        print('Current value: %f' % current_value)
        time.sleep(1)
        #######

基本上,在主循環中執行了一些輕量級函數,並且根據隨機條件,如果前一個進程已經完成,一些繁重的工作會被發送到另一個進程,由需要在執行之間存儲一些數據的對象執行。 盡管costum_function需要一些時間,但是light函數會繼續執行而不會被阻塞。

雖然上面的代碼完成了工作,但我想知道:這是最好/最合適的方法嗎?

此外,假設類 SumClass 有另一個對象的實例,該對象也需要存儲數據。 例如:

import multiprocessing
import time
import numpy as np


class Operator:

    def __init__(self):

        self.last_value = 1.0

    def operate(self, value):

        print('    Operation, last value: %f' % self.last_value)
        self.last_value *= value
        return self.last_value


class SumClass:

    def __init__(self):

        self.operator_obj = Operator()
        self.result = 0.0

        self.p = None
        self.return_value = None

    def expensive_function(self, new_number, return_value):

        # Execute expensive calculation
        #######
        time.sleep(np.random.random_integers(5, 10, 1))

        # Apply operation
        number = self.operator_obj.operate(new_number)

        # Apply other operation
        return_value.value = self.result + number
        #######

    def execute_function(self, new_number):

        print('    New number received: %f' % new_number)
        self.return_value = multiprocessing.Value("f", 0.0, lock=True)
        self.p = multiprocessing.Process(target=self.expensive_function, args=(new_number, self.return_value))
        self.p.start()

    def is_executing(self):
        if self.p is not None:
            if not self.p.is_alive():
                self.result = self.return_value.value
                self.p = None
                return False
            else:
                return True
        else:
            return False


if __name__ == '__main__':

    sum_obj = SumClass()
    current_value = 0

    while True:

        if not sum_obj.is_executing():

            # Randomly determine whether the function must be executed or not
            if np.random.rand() < 0.25:
                print('Current sum value: %f' % sum_obj.result)
                new_number = np.random.rand(1)[0]
                sum_obj.execute_function(new_number)

        # Execute other (light) stuff
        #######
        print('Executing other stuff')
        current_value += sum_obj.result * 0.1
        print('Current value: %f' % current_value)
        time.sleep(1)
        #######

現在,在cost_function內部,使用了對象Operator的函數成員,它需要存儲傳遞的數字。

正如預期的那樣,成員變量last_value不會改變,即它不保留任何值。

有沒有辦法正確地做到這一點?

我可以想象我可以安排一切,這樣我只需要使用一個類級別,並且它會運行良好。 然而,這是一個玩具示例,實際上有不同層次的復雜對象,這很難。

非常感謝您提前!

from concurrent.futures import ThreadPoolExecutor
from numba import jit
import requests
import timeit


def timer(number, repeat):
    def wrapper(func):
        runs = timeit.repeat(func, number=number, repeat=repeat)
        print(sum(runs) / len(runs))
    return wrapper


URL = "https://httpbin.org/uuid"

@jit(nopython=True, nogil=True,cache=True)
def fetch(session, url):
    with session.get(url) as response:
        print(response.json()['uuid'])


@timer(1, 1)
def runner():
    with ThreadPoolExecutor(max_workers=25) as executor:
        with requests.Session() as session:
            executor.map(fetch, [session] * 100, [URL] * 100)
            executor.shutdown(wait=True)
            executor._adjust_thread_count

也許這可能會有所幫助。

我正在使用 ThreadPoolExecutor 進行多線程處理。 您還可以使用 ProcessPoolExecutor。

對於計算成本高的操作,您可以使用 numba 來制作函數的緩存字節碼,以便更快地執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM