2017-07-25 136 views
5

B sınıfındaki girdi verilerini tüketirken verileri (büyük matris hesaplamaları) hesaplayan bazı karmaşık sınıf A var.Python 3 çoklu işlem. Proses içi sınıf?

bir kendisi çoklu çekirdek kullanır. A sonraki veri yığın ihtiyaç duyduğunda Ancak, aynı ana iş parçacığı B koşular beri oldukça uzun bir süre bekler. Bir esas hesaplamalar için GPU kullanır yana

, bir CPU ile eş zamanlı veri toplama B istiyorum.

Benim son yaklaşımdı:

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() 

bu yaklaşım "pythonic" çözüm düşünülebilir miydi:

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

... ve B böyle yaklaşık görünüyor? Python'ın çoklu işlem modülü ile pek deneyime sahip olduğundan

, kolay bir/basit bir yaklaşım inşa ettik. Ancak, bana "hacky" gibi görünüyor. Ana iş parçacığı ağır hesaplamaları çalışır ve zaman zaman kuyruktan verileri tüketirken

Ne, eş zamanlı ve bazı kuyruğa yoluyla tedarik diskten bir sınıf B yükleme verileri için daha iyi bir çözüm olacaktır? Çözümünüz özellikle "küçük" projeler için, mükemmel bir sakınca iken

cevap

1

, bu parçacığı sıkıca sınıfta B ile birleştiğinde alma dezavantajı vardır. Bu nedenle (örneğin) bir sebepten dolayı B kaynaklı olmayan bir şekilde kullanmak istediğinizde şansınız kalmadı.

Şahsen dışından konuları kullanarak çağrı ardından parçacığı güvenli bir şekilde sınıf yazmak ve olacaktır:

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() 

Bu B daha esnek, daha iyi bağımlılıkları ayıran ve test etmek kolaylaşır. Ayrıca, kod oluşturma işlemi hakkında dolaylı olarak gerçekleştiğinden, kod oluşturma hakkında açık olmasıyla kodun daha okunabilir olmasını sağlar.