#python #python-3.x #simpy
Вопрос:
Ниже показан мой код, который имитирует очередь с упреждением 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, сервер прервал обслуживание для «Тип задания 2 #1», а оставшееся время обслуживания для этого задания составляет 18.31. Однако, как только сервер завершит работу с «Типом задания 1 #1», он никогда не продолжит службу для «Типа задания 2 #1». Фактически, «Тип задания 2 #1» немедленно покинул систему, когда появилось «Тип задания 1 #1». Это ясно показывает, в чем моя проблема с моим кодом. Почему «Тип задания 2 #1» немедленно покидает систему, а сервер никогда не продолжает обслуживание для этого задания?
Ответ №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()