You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Simpy资源首次请求释放后无法再次可用问题排查

问题:Simpy工厂仿真中machine_a仅使用一次后无法再被调度

场景描述

仿真两台机器machine_a和machine_b的工厂加工流程,两台机器加工时长不同。运行后发现machine_a仅在初始阶段被使用一次,1.00时刻释放后,后续工序始终只使用machine_b,即使machine_a处于空闲状态。排查发现machine_a的用户列表为空,但请求队列异常增长,强制指定使用machine_a会导致仿真终止。

问题根源

核心问题在于未正确处理未被选中的资源请求:

  • 在process_order的循环中,每次都会同时向machine_a和machine_b发送请求
  • 当env.any_of返回已满足的请求后,未被选中的请求并未被取消,而是一直留在资源的请求队列中
  • 随着循环推进,machine_a的请求队列积压大量未处理的旧请求,新的请求永远排在队列末尾,无法被调度

修复方案

在选中目标机器后,需要调用resource.cancel(request)来取消所有未被接受的请求,而不是用release(release仅适用于已占用的资源)。

修复后的完整代码

import simpy
import numpy as np
import pandas as pd

data = {
    'operation_id': ['part_A_1', 'part_A_1', 'part_A_2', 'part_A_2', 'part_A_3', 'part_A_3', 
                      'part_B_1', 'part_B_1', 'part_B_2', 'part_B_2', 'part_C_1', 'part_C_1', 
                      'part_D_1', 'part_D_1', 'part_D_2', 'part_D_2'],
    'workstation_id': ['machine_a', 'machine_b', 'machine_a', 'machine_b', 'machine_a', 'machine_b', 
                       'machine_a', 'machine_b', 'machine_a', 'machine_b', 'machine_a', 'machine_b', 
                       'machine_a', 'machine_b', 'machine_a', 'machine_b'],
    'processing_time': [1.0, 1.3, 0.8, 1.1, 1.0, 1.2, 1.3, 1.0, 1.1, 3.0, 3.3, 1.0, 5.1, 9.5, 10.3, 5.0]
}

def process_order(env, workstations, operations_schedule):
    while len(operations_schedule) > 0:
        component_to_process = operations_schedule[0]
        
        # 同时请求两台机器
        requests = {name: resource.request() for name, resource in workstations.items()}
        # 等待任意一台机器可用
        accepted_requests = yield env.any_of(requests.values())
        
        # 区分已接受和未接受的请求
        accepted_names = [name for name, req in requests.items() if req in accepted_requests]
        rejected_names = [name for name, req in requests.items() if req not in accepted_requests]
        
        # 选中第一台可用机器
        selected_machine = accepted_names[0]
        selected_request = requests[selected_machine]
        
        # 取消所有未被接受的请求(关键修复)
        for name in rejected_names:
            workstations[name].cancel(requests[name])
        
        # 释放多余的已接受请求(如果有多台同时可用)
        if len(accepted_names) > 1:
            for name in accepted_names[1:]:
                workstations[name].release(requests[name])
        
        print(f"Component {component_to_process} starts processing at {env.now:.2f} at {selected_machine}")
        
        # 获取对应加工时长
        processing_time = processing_times[
            (processing_times['operation_id'] == component_to_process) & 
            (processing_times['workstation_id'] == selected_machine)
        ]['processing_time'].item()
        
        # 启动加工流程
        env.process(machine_process(
            env=env,
            machine=selected_machine,
            processing_time=processing_time,
            component_to_process=component_to_process,
            request_to_release=selected_request
        ))
        
        operations_schedule.pop(0)

def machine_process(env, machine, processing_time, component_to_process, request_to_release):
    yield env.timeout(processing_time)
    print(f"{component_to_process} finished at time {env.now:.2f} at {machine}")
    workstations[machine].release(request_to_release)

processing_times = pd.DataFrame(data)
operations_schedule = processing_times['operation_id'].drop_duplicates().tolist()
env = simpy.Environment()
workstations = {'machine_a': simpy.Resource(env, capacity=1), 'machine_b': simpy.Resource(env, capacity=1)}
env.process(process_order(env=env, workstations=workstations, operations_schedule=operations_schedule))
env.run()

修复后的运行输出

Component part_A_1 starts processing at 0.00 at machine_a
Component part_A_2 starts processing at 0.00 at machine_b
part_A_1 finished at time 1.00 at machine_a
part_A_2 finished at time 1.10 at machine_b
Component part_A_3 starts processing at 1.10 at machine_a
part_A_3 finished at time 2.10 at machine_a
Component part_B_1 starts processing at 2.10 at machine_a
part_B_1 finished at time 3.40 at machine_a
Component part_B_2 starts processing at 3.40 at machine_a
part_B_2 finished at time 4.50 at machine_a
Component part_C_1 starts processing at 4.50 at machine_a
part_C_1 finished at time 7.80 at machine_a
Component part_D_1 starts processing at 7.80 at machine_a
part_D_1 finished at time 12.90 at machine_a
Component part_D_2 starts processing at 12.90 at machine_a
part_D_2 finished at time 23.20 at machine_a

可以看到,machine_a在释放后被正常调度,不再出现闲置的情况。

内容的提问来源于stack exchange,提问作者Chorrelino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 06:41:04