在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

在上面的结果中,你可以看到;作业类型1#1";到达16.94时,服务器中断了"0"的服务;作业类型2#1";并且该作业的剩余服务时间是18.31。然而,一旦服务器完成了";作业类型1#1";它从不继续为"0"提供服务;作业类型_2#1";。事实上;作业类型2#1";立即离开系统;作业类型1#1";到达。这清楚地表明了我的代码有什么问题。为什么"作业类型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()

最新更新