【问题标题】:Resource not releasing in Simpy - what am I doing wrong?资源未在 Simpy 中释放 - 我做错了什么?
【发布时间】:2016-09-08 16:25:02
【问题描述】:

我已按照建议简化了代表问题的代码并尝试调试。

这是仍然包含错误的最简单的代码版本:

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 上占用其他资源。

我对此感到非常困惑。任何帮助将不胜感激!

【问题讨论】:

  • 您是否尝试过打印一条消息来检查您是否点击过else 分支(您遗漏的那个)?如果你击中它,你就不会释放资源。
  • 是的,刚刚检查了两条路线的 else 语句,它们从未被命中 - 逻辑没问题。奇怪的是资源没有被释放。
  • 那么请尝试找到一个最小的示例来解决您遇到的错误。逐行删除代码并进行测试。如果错误没有出现,请重新插入上次删除的内容并尝试删除其他内容,直到没有其他内容可以删除。
  • 感谢 Stefan,我已经尽可能地减少了问题,同时仍然包含错误。由于某种原因,在第一个资源被释放后,就无法获取任何资源。
  • @StefanScherfke,我在下面的解决方案中添加了我认为是最小的工作示例。我认为这解释了这个问题,我想知道您对最正确解决方案的看法是什么。

标签: python simpy


【解决方案1】:

我相信问题的出现是因为发布引用了一个特定的请求,但到那时该请求已经被一个新的请求覆盖了。 resource_req 是请求,但是在它可以被释放之前,它被一个新的resource_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:
            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 个批次,但只完成了第一个。

>>> 
Waiting for machine at 0
Load machine at 0
Waiting for machine at 0
Machine starts process at 0
Machine finished process at 10
Machine released at 10
>>> 

看来释放不起作用,因为它指的是第二个请求。对此进行诊断可以找到解决方法,但如果知道正确的方法会很高兴!


一种可能的解决方案是只释放当前用户而不是特定请求:

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)

这确实按预期工作。

【讨论】:

  • 也许@Stefan Scherfke 可以提出更好的解决方案!
  • self.process_proc 的目的是什么?如果该行代码正是您希望 Machine 完成其“工作”的位置(如 process 方法中所定义),那么您可以将 self.process_proc = env.process(self.process(env)) 替换为 yield env.process(self.process(env))
  • @EricLaFevers,这只是为了演示资源释放的具体问题,当您释放的变量被覆盖时。我敢肯定,这是一个非常简单的模拟,可以以更好的方式完成。这是常见用户错误的最小示例。通常,在进行模拟时,您希望密切关注您正在模拟的实际事物的逻辑,因此您很可能只想启动辅助过程并继续,而不是等待辅助过程完成。
  • 最安全的资源请求方式是使用with 语句。当您需要在另一个进程中释放它(如您的示例中)时,您应该将请求显式传递给进程,而不是将其设置为实例属性。这样,请求就不会被另一个进程覆盖。
【解决方案2】:

已解决 - 资源中有错字。

最初定义为:

resource = simpy.Resource(env, 1)

正确定义:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-09
    • 2015-03-03
    • 2011-03-31
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多