Проблема моделирования упреждающей очереди M/M/1 в Python

#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()