【问题标题】:Problem in simulating a preemptive M/M/1 queue in Python在 Python 中模拟抢占式 M/M/1 队列时出现问题
【发布时间】:2021-11-14 15:14:46
【问题描述】:

下面显示了我的代码,它模拟了具有两种到达类型的 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”立即离开系统,而服务器不再继续为该作业提供服务?

【问题讨论】:

    标签: python python-3.x simpy


    【解决方案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()
    

    【讨论】:

      猜你喜欢
      • 2021-01-25
      • 2022-08-21
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 2023-03-11
      • 2018-10-21
      • 2013-04-30
      • 2010-11-13
      相关资源
      最近更新 更多