2017-07-25 17 views
5

Tôi có một số lớp phức tạp A tính toán dữ liệu (phép tính ma trận lớn) trong khi tiêu thụ dữ liệu đầu vào từ lớp B.Python 3 đa xử lý.Tiếp cận bên trong lớp học?

A chính nó sử dụng nhiều lõi. Tuy nhiên, khi A cần đoạn dữ liệu tiếp theo, nó chờ một thời gian kể từ khi B chạy trong cùng một chuỗi chính.

A chủ yếu sử dụng GPU để tính toán, tôi muốn có B thu thập dữ liệu đồng thời trên CPU.

cách tiếp cận mới nhất của tôi là:

# every time *A* needs data 
def some_computation_method(self): 
    data = B.get_data() 
    # start computations with data 

... và B trông xấp xỉ như thế này:

class B(object): 

    def __init__(self, ...): 
     ... 
     self._queue = multiprocessing.Queue(10) 
     loader = multiprocessing.Process(target=self._concurrent_loader) 

    def _concurrent_loader(self): 
     while True: 
      if not self._queue.full(): 
       # here: data loading from disk and pre-processing 
       # that requires access to instance variables 
       # like self.path, self.batch_size, ... 
       self._queue.put(data_chunk) 
      else: 
       # don't eat CPU time if A is too busy to consume 
       # the queue at the moment 
       time.sleep(1) 

    def get_data(self): 
     return self._queue.get() 

thể phương pháp này được coi là một "pythonic" giải pháp?

Vì tôi không có nhiều kinh nghiệm với mô-đun đa xử lý của Python, tôi đã xây dựng một cách tiếp cận dễ dàng/đơn giản. Tuy nhiên, nó trông giống như "hacky" với tôi.

Giải pháp tốt hơn để lớp B tải dữ liệu từ đĩa đồng thời và cung cấp dữ liệu qua hàng đợi, trong khi chuỗi chính chạy tính toán nặng và tiêu thụ dữ liệu từ hàng đợi theo thời gian?

Trả lời

1

Trong khi giải pháp của bạn là hoàn toàn OK, đặc biệt là đối với các dự án "nhỏ", nó có nhược điểm của luồng được kết hợp chặt chẽ với lớp B. Do đó, nếu bạn (ví dụ) vì một lý do nào đó muốn sử dụng B theo cách không phải là, bạn đã hết may mắn.

Cá nhân tôi sẽ viết các lớp một cách an toàn chủ đề, và sau đó gọi nó là sử dụng đề từ bên ngoài:

class B(object): 
    def __init__(self): 
     self._queue = multiprocessing.Queue(10) 

    ... 

if __name__ == '__main__': 
    b = B() 

    loader = multiprocessing.Process(target=b._concurrent_loader) 
    loader.start() 

Điều này làm cho B linh hoạt hơn, tách phụ thuộc tốt hơn và dễ dàng hơn để kiểm tra. Nó cũng làm cho mã dễ đọc hơn bằng cách là rõ ràng về việc tạo chuỗi, so với việc xảy ra ngầm định khi tạo lớp.

Các vấn đề liên quan