Simpy仿真脚本故障排查:单Dock资源下组件并发处理异常
SimPy资源调度异常问题分析与修复
问题描述
编写了一个SimPy仿真脚本,用于模拟资源被占用/阻塞时的dock输出及tug等待时间数据。流程规则如下:
- 流程始于转运点,每5秒有一个新组件进入流程(
component_generator函数) - 每个组件需请求tug(容量2)运输至容量为1的dock
- 运输及dock处理期间tug会被占用,完成后释放tug
但脚本存在故障:dock容量配置为1,理论上后到达的组件需等待dock处理完成后才能执行后续操作,但实际Component与Component 0在t=10时同时进入dock处理阶段,不符合资源容量限制。
故障原因分析
核心问题出在dock资源请求未被正确等待:
- 在
transport_and_process函数中,使用with dock.request() as dock_req获取dock请求后,未执行yield dock_req来等待资源分配,直接启动process_at_dock进程,导致dock资源未被实际占用,多个组件可同时进入处理阶段。 process_at_dock函数中对tug.release(tug_req)使用了yield,但release是同步操作,并非SimPy事件,无需yield。
修复后的代码
import simpy import itertools import random sim_time = 20 T_INTER = [5, 5] # 组件到达间隔时间(秒) def transport_and_process(name, env, dock, tug): tug_time = env.now print(f'{env.now:6.1f} s: {name} arrived Transshipment Point') tug_req = tug.request() # 请求tug用于运输 yield tug_req # 等待tug分配 print(f'{env.now:6.1f} s: {name} got tug and start transportation') yield env.timeout(2) # 运输到dock的时间 print(f'{env.now:6.1f} s: {name} arrives the dock') with dock.request() as dock_req: yield dock_req # 等待dock资源空闲,这是关键修复点 print(f'{env.now:6.1f} s: {name} has been assigned to the dock') yield env.process(process_at_dock(name, env, tug_req, tug_time)) def process_at_dock(name, env, tug_req, tug_time): yield env.timeout(10) # dock处理时间 tug.release(tug_req) # 释放tug,无需yield tug_block_time = env.now - tug_time print(f'{env.now:6.1f} s: {name} dock processed') print(f'{env.now:6.1f} s: {name} tug released') print(f'{env.now:6.1f} s: {name} blocked the tug for: {tug_block_time:.1f}') def component_generator(env, dock, tug): """生成新组件进入流程""" for i in itertools.count(): yield env.timeout(random.randint(*T_INTER)) env.process(transport_and_process(f'Component {i}', env, dock, tug)) # 初始化仿真环境 env = simpy.Environment() dock = simpy.Resource(env, capacity=1) tug = simpy.Resource(env, capacity=2) env.process(transport_and_process('Component', env, dock, tug)) env.process(component_generator(env, dock, tug)) env.run(until=sim_time)
修复说明
- 添加
yield dock_req:确保组件必须等待dock资源空闲后,才能进入处理阶段,符合dock容量为1的限制。 - 移除release的yield:
tug.release()是立即执行的同步操作,不需要作为事件等待。 - 优化变量命名:将
tug_time计算提前,避免初始值0导致的时间计算错误。
修复后运行输出示例:
0.0 s: Component arrived Transshipment Point 0.0 s: Component got tug and start transportation 2.0 s: Component arrives the dock 2.0 s: Component has been assigned to the dock 5.0 s: Component 0 arrived Transshipment Point 5.0 s: Component 0 got tug and start transportation 7.0 s: Component 0 arrives the dock 12.0 s: Component dock processed 12.0 s: Component tug released 12.0 s: Component blocked the tug for: 12.0 12.0 s: Component 0 has been assigned to the dock
内容的提问来源于stack exchange,提问作者Padavan
相关产品推荐
相关产品推荐

