python - 在 Python 中模拟抢占式 M/M/1 队列时出现问题
问题描述
下面显示了我的代码,它模拟了具有两种到达类型的 M/M/1 抢占式队列,其中第一种类型的优先级高于第二种类型。但是,我不知道为什么在我的代码中抢先规则没有按应有的方式工作。我的意思是在抢占队列中,例如,如果类型 2 的作业正在接收服务并且类型 1 的作业到达,则服务器中断类型 2 作业的服务并开始类型 1 作业的服务。但是,一旦类型 1 作业的服务完成,它应该 继续为中断的类型 2 作业提供服务。
在我的代码中,如果工作类型 2 正在接受服务并且工作类型 1 到达,那么工作类型 2 会立即永久离开系统。我想知道您能否告诉我为什么会发生这种情况以及如何解决?
非常感谢您提前付出的时间和精力。
import random
import simpy
rn_seed = 10
t1_interval_arrivals = 20.0
t2_interval_arrivals = 1
t1_interval_service = 5
t2_interval_service = 20
def type_1_generator(env, interval, server):
i = 0
while True:
c = job(env, "type_1"+" #"+ str(i), "type_1", server, t1_interval_service)
env.process(c)
t = random.expovariate(1.0 / interval)
yield env.timeout(t)
i +=1
def type_2_generator(env, interval, server):
i = 0
while True:
c = job(env, "type_2"+" #"+str(i), "type_2", server, t2_interval_service)
env.process(c)
t = random.expovariate(1.0 / interval)
yield env.timeout(t)
i +=1
def job(env, name, typ , server, sr_interval):
arrive = env.now
print("Job", name, "Arrived at: ",arrive)
service_interval = random.expovariate(1.0 / sr_interval)
print("Job", name, "Service time: ",service_interval)
if typ == "type_1":
while service_interval:
with server.request(priority=1) as req:
yield req
yield env.timeout(service_interval)
service_interval = 0
print("Job", name, "Left system at: ",env.now)
elif typ == "type_2":
while service_interval:
try:
start = env.now
with server.request(priority=2) as req:
yield req
yield env.timeout(service_interval)
service_interval = 0
print("Job", name, "Left system at: ",env.now)
except simpy.Interrupt:
print("Job", name, "Is interrupted at: ",env.now)
service_interval -= env.now - start
print("Job", name, "Remaining service: ",env.now)
print("Job", name, "Left system at ",env.now)
# Setup and start the simulation
random.seed(rn_seed)
env = simpy.Environment()
# Start processes and run
server = simpy.PreemptiveResource(env, capacity=1)
env.process(type_1_generator(env, t1_interval_arrivals, server))
env.process(type_2_generator(env, t2_interval_arrivals, server))
env.run()
以下是结果示例:
Job type_2 #1 Arrived at: 0.5601717881563535
Job type_2 #1 Service time: 34.69876113045603
Job type_1 #1 Arrived at: 16.94474499667717
Job type_1 #1 Service time: 0.22635015810062187
Job type_2 #1 Is interrupted at: 16.94474499667717
Job type_2 #1 Remaining service: 18.31418792193521
Job type_2 #1 Left system at 16.94474499667717
Job type_1 #1 Left system at: 17.17109515477779
在上面的结果中您可以看到,一旦“Job type_1 #1”到达 16.94,服务器中断了“Job type_2 #1”的服务,该作业的剩余服务时间为 18.31。但是,一旦服务器完成了“Job type_1 #1”,它就永远不会继续为“Job type_2 #1”提供服务。事实上,当“Job type_1 #1”到达时,“Job type_2 #1”立即离开了系统。这清楚地表明了我的代码有什么问题。为什么“Job type_2 #1”立即离开系统,而服务器从不继续为该作业提供服务?
解决方案
我对您的代码进行了一些更改。需要注意的是,当您重新提交对资源的请求时,它会被放在队列的末尾。所以我给中断的第二类工作比新的第二类工作更高的优先级。第一类作业仍然具有最高优先级。我还添加了一些打印语句。
import random
import simpy
rn_seed = 10
t1_interval_arrivals = 20.0
t2_interval_arrivals = 1
t1_interval_service = 5
t2_interval_service = 20
# use for unique id across all jobs
i = 0
def type_1_generator(env, interval, server):
global i
while i < 6:
c = job(env, "type_1"+" #"+ str(i), "type_1", server, t1_interval_service)
i +=1
env.process(c)
t = random.expovariate(1.0 / interval)
yield env.timeout(t)
def type_2_generator(env, interval, server):
global i
while i < 4:
c = job(env, "type_2"+" #"+str(i), "type_2", server, t2_interval_service)
i +=1
env.process(c)
t = random.expovariate(1.0 / interval)
yield env.timeout(t)
def job(env, name, typ , server, sr_interval):
"""
use three priorites so interuped jobs can
take precendence over type 2 jobs that have
not started yet
job priorities are:
type 1: 1
type 2: 3
interupted type 2: 2
"""
arrive = env.now
print("Job", name, "Arrived at: ",arrive)
service_interval = random.expovariate(1.0 / sr_interval)
print("Job", name, "Service time: ",service_interval)
if typ == "type_1":
while service_interval:
with server.request(priority=1) as req:
yield req
print("Job", name, "seized resource at: ",env.now)
yield env.timeout(service_interval)
service_interval = 0
print("Job", name, "released resource at: ",env.now)
print("Job", name, "finished at: ",env.now)
elif typ == "type_2":
priority=3
while service_interval:
try:
with server.request(priority=priority) as req:
yield req
start = env.now
if priority == 3:
print("Job", name, "seized resource at: ",env.now)
else:
print("Job", name, "resumed with resource at: ",env.now)
yield env.timeout(service_interval)
service_interval = 0
print("Job", name, "released resource at: ",env.now)
except simpy.Interrupt:
# up priority to take precenance of not started jobs
priority=2
print("Job", name, "Is interrupted at: ",env.now)
service_interval -= env.now - start
print("Job", name, "Remaining service: ",service_interval)
print("Job", name, "finished ",env.now)
# Setup and start the simulation
random.seed(rn_seed)
env = simpy.Environment()
# Start processes and run
server = simpy.PreemptiveResource(env, capacity=1)
env.process(type_1_generator(env, t1_interval_arrivals, server))
env.process(type_2_generator(env, t2_interval_arrivals, server))
env.run()
推荐阅读
- multiplication - 为什么补码乘法需要做符号扩展?
- postgresql - postgres COPY 功能是否支持 utf 16 编码文件?
- reactjs - 两个不同反应应用程序之间的数据流
- oracle - 如何创建显示表格的过程(select * from emp)
- websocket - 尝试使用 websocket api 网关,值得吗?
- ember.js - 如何验证模板中是否存在特定的上下文组件?
- kubernetes - 对 K8s 服务所在的位置以及 Istio 的 Envoy 代理所在的位置感到困惑?
- docker - 如何使用 Hashicorp Nomad/Consul 处理有状态实例类型的工作负载的最佳方式
- php - Zip 文件需要包含空文件夹
- php - Laravel查询检查表列值是否存在