4. 规则驱动型排产(一):先入先出(FIFO)、最短加工时间(SPT)、最早交货期(EDD)的原理与实现
各位工程师朋友,今天我们聊聊排产算法里最基础、也最实用的三类规则。说实话,很多刚入行的同事总觉得排产必须上AI、上遗传算法才够高级。我个人习惯是:能用简单规则解决的问题,绝不上复杂模型。你想想看,工厂里每天几千个lot在跑,如果每个决策都要算十分钟,那黄花菜都凉了。
4.1 先入先出(FIFO)——最朴素的公平
FIFO,说白了就是谁先来谁先做。这个规则在半导体工厂里应用极广,尤其是光刻区、扩散区这些瓶颈工序。我记得刚入行时带我的老师傅说:「别小看FIFO,它能让你的WIP分布最均匀。」
原理:按照lot到达当前设备的时间戳排序,最早到达的优先加工。
适用场景:
- 设备负载均衡要求高
- 产品种类单一,工艺时间差异不大
- 客户对交期没有特殊要求
核心公式:优先级 = ArrivalTime(lot) ,值越小优先级越高。
代码实现(Python伪代码):
def fifo_schedule(lots, machine):
# lots: list of dict, 每个lot包含lot_id, arrival_time, process_time
# 按到达时间排序
sorted_lots = sorted(lots, key=lambda x: x['arrival_time'])
schedule = []
current_time = 0
for lot in sorted_lots:
start_time = max(current_time, lot['arrival_time'])
end_time = start_time + lot['process_time']
schedule.append({
'lot_id': lot['lot_id'],
'start': start_time,
'end': end_time
})
current_time = end_time
return schedule
避坑指南:我曾经在一个项目中直接用FIFO排产,结果发现某个lot的工艺时间特别长,导致后面所有lot都延迟了。后来我加了一个「超时打断」机制——如果某个lot加工时间超过阈值,就暂时挂起,先处理后面的短lot。嗯,这里要注意,FIFO不是万能的。
4.2 最短加工时间(SPT)——效率优先
SPT规则,顾名思义,加工时间最短的lot优先。这个规则的目标很明确:最小化平均流程时间。说白了就是让更多的lot尽快做完,提高设备利用率。
原理:比较每个lot在当前设备上的加工时间,选最小的先做。
适用场景:
- 设备是瓶颈,需要最大化产出
- 产品工艺时间差异大(比如有5分钟和5小时的lot混在一起)
- 对交期要求不严格
核心公式:优先级 = ProcessTime(lot) ,值越小优先级越高。
代码实现:
def spt_schedule(lots, machine):
# 按加工时间排序
sorted_lots = sorted(lots, key=lambda x: x['process_time'])
schedule = []
current_time = 0
for lot in sorted_lots:
start_time = max(current_time, lot['arrival_time'])
end_time = start_time + lot['process_time']
schedule.append({
'lot_id': lot['lot_id'],
'start': start_time,
'end': end_time
})
current_time = end_time
return schedule
注意:SPT有一个致命缺陷——它会无限期推迟长加工时间的lot。我在一个12寸晶圆厂遇到过这种情况:某个需要6小时刻蚀的lot被连续跳过了3天,最后变成了紧急插单。所以实际应用中,我建议给每个lot设置一个「最大等待时间」,超过这个时间就强制提升优先级。
4.3 最早交货期(EDD)——客户至上
EDD规则,按交货期排序,最早到期的先做。这个规则在半导体后道封装测试环节特别重要,因为客户对交期非常敏感。
原理:比较每个lot的承诺交货日期(Due Date),最早的优先。
适用场景:
- 客户有严格交期要求
- 产品价值高,延迟成本大
- 产能相对充裕
核心公式:优先级 = DueDate(lot) ,值越小优先级越高。
代码实现:
def edd_schedule(lots, machine):
# 按交货期排序
sorted_lots = sorted(lots, key=lambda x: x['due_date'])
schedule = []
current_time = 0
for lot in sorted_lots:
start_time = max(current_time, lot['arrival_time'])
end_time = start_time + lot['process_time']
schedule.append({
'lot_id': lot['lot_id'],
'start': start_time,
'end': end_time
})
current_time = end_time
return schedule
个人经验:EDD规则有个坑——如果某个lot的交货期已经过了,它的优先级会变得极高,导致其他lot被严重挤压。我曾经在项目中加了一个「松弛度」参数:松弛度 = DueDate - CurrentTime - RemainingProcessTime。松弛度越小,优先级越高。这样既考虑了交期,又兼顾了剩余加工时间。
4.4 三种规则的对比与选择
这三种规则各有优劣,我整理了一个对比表,方便大家在实际项目中快速决策:
| 规则 | 优化目标 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| FIFO | 公平性 | 实现简单,WIP均匀 | 不考虑效率 | 瓶颈设备、均匀负载 |
| SPT | 最小化平均流程时间 | 产出高,设备利用率好 | 长任务被饿死 | 工艺时间差异大 |
| EDD | 最小化最大延迟 | 客户满意度高 | 可能牺牲效率 | 交期敏感场景 |
4.5 核心逻辑流程图
下面我用一张SVG图来展示这三种规则的核心决策逻辑。你想想看,其实它们都是在做同一件事——给每个lot算一个优先级分数,然后排序。只是算分的方式不同。
4.6 实际项目中的组合策略
说实话,在真实的半导体工厂里,很少只用单一规则。我参与过的项目里,最常用的策略是混合规则:
- FIFO + SPT:先按FIFO排队,但如果某个lot的加工时间超过阈值,就按SPT重新排序。这样既保证了公平,又提高了效率。
- EDD + SPT:先按EDD筛选出紧急lot,再在紧急lot内部按SPT排序。这样既保交期,又保产出。
- 动态权重:给每个规则分配一个权重,根据当前工厂状态动态调整。比如WIP高时加大SPT权重,交期紧张时加大EDD权重。
核心要点:规则驱动型排产的精髓不在于规则本身,而在于如何组合、如何调参。我见过太多工程师把FIFO、SPT、EDD背得滚瓜烂熟,但一到现场就不知道怎么用了。记住:规则是死的,工厂是活的。
好了,这一章就到这里。这三种规则虽然简单,但它们是所有复杂排产算法的基础。下一章我们会继续深入,看看如何用加权规则和优先级矩阵来解决更复杂的排产问题。
公众号:蓝海资料掘金营,微信deep3321