2016-07-01 7 views
0

Я пытаюсь создать имитацию производителя/потребителя, когда потребитель обрабатывает партии партиями. Проблема заключается в том, что функция Store.get() удаляет элементы из магазина, как только он называется, но мне нужно ждать, пока я под названием выход:Simpy Store Batch Processing

import simpy 

def producer(env, Q): 
    item = 0 
    while True: 
     yield Q.put(item) 
     print('Submit item:%d'%item) 
     item += 1 

def consumer(env, Q): 
    while True: 
     yield env.timeout(20) 
     events = [Q.get() for i in range(4)] 
     items = yield env.all_of(events) 
     print([items for items in items.values()]) 


env = simpy.Environment() 
maxQD = 2 
Q = simpy.Store(env, capacity=maxQD) 

env.process(producer(env, Q)) 
env.process(consumer(env, Q)) 
env.run(until=500) 

Который производит следующий вывод:

Submit item:0 
Submit item:1 
Submit item:2 
Submit item:3 
Submit item:4 
[0, 1, 2, 3] 
Submit item:5 
Submit item:6 
Submit item:7 
Submit item:8 
[4, 5, 6, 7] 
Submit item:9 
Submit item:10 
Submit item:11 
Submit item:12 
[8, 9, 10, 11] 
... 

с maxQD установлен в 2, я ожидал бы просто:

Submit item:0 
Submit item:1 

с блокировкой потребителя, пока она успешно не получает 4 пункта, и производитель не в состоянии добавить больше чем 2.

Вы можете сортировать исправить эту проблему, проверив LEN (Q.items):

import simpy 

def producer(env, Q): 
    item = 0 
    while True: 
     yield Q.put(item) 
     print('Submit item:%d'%item) 
     item += 1 

def consumer(env, Q): 
    while True: 
     yield env.timeout(20) 
     if len(Q.items) >= 4: 
      events = [Q.get() for i in range(4)] 
      items = yield env.all_of(events) 
      print([items for items in items.values()]) 


env = simpy.Environment() 
maxQD = 4 
Q = simpy.Store(env, capacity=maxQD) 

env.process(producer(env, Q)) 
env.process(consumer(env, Q)) 
env.run(until=500) 

Но вы все равно получите разочарование поведением, что прибудете() удаляет элементы перед выходом, что делает его похожим на 5 элементы были добавлены к Q (обратите внимание maxQD изменился до 4):

Submit item:0 
Submit item:1 
Submit item:2 
Submit item:3 
Submit item:4 
[0, 1, 2, 3] 
+0

То, что вы наблюдаете, является предполагаемым поведением. env.all_of() не ждет, пока все события get * не смогут добиться успеха, но пока все не удастся. Каждое отдельное событие, которое вы передаете env.all_of(), является независимым и будет запущено как можно скорее. Таким образом, семантика этого примера не «дожидается, пока в магазине не будет 4 элемента», но «подождите, пока вы в конечном итоге не получите 4 элемента из магазина». –

ответ

1

решенных с помощью подклассов магазина:

class BatchGet(simpy.resources.base.Get): 
    def __init__(self, resource, count): 
     self.count = count 
     super().__init__(resource) 

class BatchStore(simpy.resources.store.Store): 
    get = simpy.core.BoundClass(BatchGet) 

    def _do_put(self, event): 
     if len(self.items) + len(event.item) <= self._capacity: 
      self.items.extend(event.item) 
      event.succeed() 

    def _do_get(self, event): 
     count = event.count 
     if len(self.items) >= count: 
      ret = self.items[:count] 
      self.items = self.items[count:] 
      event.succeed(ret) 

Puts должен взять список (так как это партия элементов) и возвращает список.