2016-09-08 7 views
3

問題を表すコードを示唆して簡略化し、デバッグしようとしました。このランニングからの出力Simpyでリソースが解放されていない - 何が間違っていますか?

import simpy 

SIM_TIME = 5 

def source(env):  
    i = 0 
    while True: 
     i += 1 
     env.process(train(env, 'Train %d' % i, 'a')) 
     yield env.timeout(1) 
     i += 1 
     env.process(train(env, 'Train %d' % i, 'b')) 
     yield env.timeout(1) 

def train(env, name, route): 
    resource_req = resource.request() 
    p3_req = p3.request() 

    if route == 'a': 
     print 'Route a %s generated' % name 
     yield resource_req 
     print 'Route a %s seized resource at time %d' % (name, env.now) 
     yield env.timeout(1) 
     resource.release(resource_req) 
     print 'Route a %s released resource at time %d' % (name, env.now) 

    elif route == 'b': 
     print 'Route b %s generated' % name 
     yield p3_req 
     print 'Route b %s seized resource at time %d' % (name, env.now) 
     yield env.timeout(1) 
     p3.release(p3_req) 
     print 'Route b %s released resource at time %d' % (name, env.now) 

    else: 
     print 'Could not find a route branch' 

env = simpy.Environment() 

resource = simpy.Resource(env, 1) 
p3 = simpy.Resource(env, 1) 

env.process(source(env)) 
env.run(until=SIM_TIME) 

:あなたがリソースを見ることができるように

Route a Train 1 generated 
Route a Train 1 seized resource at time 0 
Route b Train 2 generated 
Route a Train 1 released resource at time 1 
Route a Train 3 generated 
Route b Train 4 generated 
Route a Train 5 generated 

は明らか」でリリースされる。ここ

はまだバグが含まれているコードの中で最もシンプルなバージョンです「経路a」を選択したが、他のリソースは経路aまたは経路bのいずれにも押されない。

私はこれで非常に混乱しています。どんな助けでも大歓迎です!

+0

あなたは(あなたが取り残さいること)を確認するメッセージを印刷しようとしたことがありますか?ヒットした場合は、リソースを解放しません。 –

+0

両方のルートについてelseステートメントをチェックしただけで、それらは決してヒットしません。ロジックはokです。リソースが解放されていないのは不思議です。 – bobo

+0

次に、あなたがバグを打ち負かす最小の例を見つけてみてください。行ごとにコードを削除し、テストします。バグが表示されない場合は、最後の削除を再度挿入し、削除できるものがなくなるまで別の削除を試みます。 –

答えて

0

解決済み - リソースにタイプミスがありました。

resource = simpy.Resource(env, 1) 

正しい定義:もともとのように定義

あなたは `else`枝を打つ場合

resource = simpy.Resource(env, capacity = 1) 
2

リリースでは特定のリクエストが参照されていますが、そのリクエストはすでに新しいリクエストによって上書きされているため、この問題が発生すると思います。 resource_reqは要求ですが、解放する前に新しいresource_reqで上書きされます。私はあなたがこの新しいリクエストをリリースしようとすると、それがリソースによって処理されているリリースではないので(それは新しいものです)、それを適切にリリースしないと信じています。

解決策がわかりません。このポストを見つけようとしましたが、私は同じ問題を自分で持っているからです。 1つの明らかな可能性(私はまだ試していません)は、リクエストのリストを作成し、それを追跡することですが、これは愚かな解決策のようです。単にリソースを解放する方法が必要です(これが望ましい動作です)。私はそれを把握すると私はポストバックしようとします!ここで

は、最小限の作業例です:

import simpy 

class Machine: 
    def __init__(self,env): 
     self.machine = simpy.Resource(env,capacity=1) 
     self.load_proc = env.process(self.load(env)) 

    def load(self,env): 
     "Load machine 1 when it's empty" 
     while True: 
      self.req = self.machine.request() 
      print("Waiting for machine at %d" %env.now) 
      yield self.req 
      print("Load machine at %d" %env.now) 
      self.process_proc = env.process(self.process(env)) 

    def process(self,env): 
     "Machine does process and is then emptied" 
     print("Machine starts process at %d" %env.now) 
     yield env.timeout(10) 
     print("Machine finished process at %d" %env.now) 
     self.machine.release(self.req) 
     print("Machine released at %d" %env.now) 

env = simpy.Environment() 
M1 = Machine(env) 
env.run(until=100) 

はここが継続的にロードしようとするマシンがあるが、それは空であることを待ちます。ロードされると、10秒のプロセスを実行してから、リソースを解放して再度ロードできるようにします。 100回のタイムステップで、明らかに10バッチを作ることができるはずですが、最初のバッチだけが実行されます。

2番目のリクエストを参照しているため、リリースが機能しないようです。これを診断することで、回避策を見つけることができますが、それを行う正しい方法を知ることはうれしいでしょう!


一つの可能​​な解決策は、単に現在のユーザーではなく、特定の要求を解放することです:

import simpy 

class Machine: 
    def __init__(self,env): 
     self.machine = simpy.Resource(env,capacity=1) 
     self.load_proc = env.process(self.load(env)) 

    def load(self,env): 
     "Load machine 1 when it's empty" 
     while True: 
      print("Waiting for machine at %d" %env.now) 
      yield self.machine.request() 
      print("Load machine at %d" %env.now) 
      self.process_proc = env.process(self.process(env)) 

    def process(self,env): 
     "Machine does process and is then emptied" 
     print("Machine starts process at %d" %env.now) 
     yield env.timeout(10) 
     print("Machine finished process at %d" %env.now) 
     if len(self.machine.users)>=1: self.machine.release(self.machine.users[0]) 
     print("Machine released at %d" %env.now) 

env = simpy.Environment() 
M1 = Machine(env) 
env.run(until=100) 

これは期待通りに動作し、あなたが要求のための変数を必要としないという利点があり。あなたがすでに要求されていないものをリリースするリスクがない限り、

self.machine.release(self.machine.users[0]) 

のリリースで十分でしょう。


Stefan Scherfke'sコメントに基づいて更新し、新しいプロセスに明示的にREQを渡すことです:

import simpy 

class Machine: 
    def __init__(self,env): 
     self.machine = simpy.Resource(env,capacity=1) 
     self.load_proc = env.process(self.load(env)) 

    def load(self,env): 
     "Load machine 1 when it's empty" 
     while True: 
      print("Waiting for machine at %d" %env.now) 
      req = self.machine.request() 
      yield req 
      print("Load machine at %d" %env.now) 
      self.process_proc = env.process(self.process(env,req)) 

    def process(self,env,req): 
     "Machine does process and is then emptied" 
     print("Machine starts process at %d" %env.now) 
     yield env.timeout(10) 
     print("Machine finished process at %d" %env.now) 
     self.machine.release(req) 
     print("Machine released at %d" %env.now) 

env = simpy.Environment() 
M1 = Machine(env) 
env.run(until=100) 

予想通りこれは実際に動作しません。

+0

@Stefan Scherfkeはもっと良い解決策を提案するかもしれません! –

+0

'self.process_proc'の目的は何ですか?そのコード行が、 'machine'が(' process'メソッドで定義されているように) ''仕事 'をする場所にあれば、 '' self.process_proc = env.process(self.process(env) ) '' yield env.process(self.process(env)) '' –

+0

@EricLaFeversで、これはリリースしている変数が上書きされている場合のリソースリリースの特定の問題を示すためのものです。これは非常に簡単なシミュレーションであり、はるかに優れた方法で行うことができると確信しています。一般的なユーザーエラーの最小例です。通常、シミュレーションを行う際には、シミュレーションしている実際のもののロジックに従いたいので、2次プロセスを待つのではなく、2次プロセスを開始して実行したいと思う可能性があります終わる。 –

関連する問題