SimPy(二)

Shared Resources共享资源

在进程交互中可能需要用到,一系列进程进行排队以使用某种资源,比如多个客户等待银行服务,多辆汽车等待通过缴费站,仓库货物的运输消耗和通信网络的数据包转发等.
Resources,可以由有限数量的过程一次使用的进程(例如,具有有限数量的燃油泵的加油站).
Containers,用于模拟同质,无差别主体的生产和消费的资源,可以是连续的(如水)或离散的(如苹果).
Stores,允许生成和使用的Python对象资源.
每个资源有最大容量和两个队列,一个是put something的队列另一个是get something的队列,put()和get()是相应的事件触发的方法.

import simpy
def resource_user(env, resource):
    request = resource.request()  # Generate a request event
    yield request                 # Wait for access
    yield env.timeout(1)          # Do something
    resource.release(request)     # Release the resource

>>> env = simpy.Environment()
>>> res = simpy.Resource(env, capacity=1)#创建资源
>>> user = env.process(resource_user(env, res))
>>> env.run()

因为每次都要release资源,若进程在等待中被中断,则要写成try:…finally:…结构,使用资源的request events能写成

def resource_user(env, resource):
    with resource.request() as req:  # Generate a request event
        yield req                    # Wait for access
        yield env.timeout(1)         # Do something
                                      # Resource released automatically
>>> user = env.process(resource_user(env, res))
>>> env.run()

当有多个进程要使用资源时,允许检索当前用户或派对用户的列表,当前用户的数量和资源的容量.

def print_status(res):
    res.count, res.capacity, res.users, res.queue
Containers
class GasStation:
    def __init__(self, env):
        self.fuel_dispensers = simpy.Resource(env, capacity=2)
        self.gas_tank = simpy.Container(env, init=100, capacity=1000)
        self.mon_proc = env.process(self.monitor_tank(env))

    def monitor_tank(self, env):
        while True:
            if self.gas_tank.level < 100:
                print('Calling tanker at %s' % env.now)
                env.process(tanker(env, self))
            yield env.timeout(15)

def tanker(env, gas_station):
    yield env.timeout(10)  # Need 10 Minutes to arrive
    print('Tanker arriving at %s' % env.now)
    amount = gas_station.gas_tank.capacity - gas_station.gas_tank.level
    yield gas_station.gas_tank.put(amount)

def car(name, env, gas_station):
    print('Car %s arriving at %s' % (name, env.now))
    with gas_station.fuel_dispensers.request() as req:
        yield req
        print('Car %s starts refueling at %s' % (name, env.now))
        yield gas_station.gas_tank.get(40)
        yield env.timeout(5)
        print('Car %s done refueling at %s' % (name, env.now))

def car_generator(env, gas_station):
    for i in range(4):
        env.process(car(i, env, gas_station))
        yield env.timeout(5)

>>> env = simpy.Environment()
>>> gas_station = GasStation(env)
>>> car_gen = env.process(car_generator(env, gas_station))
>>> env.run(35)
Car 0 arriving at 0
Car 0 starts refueling at 0
Car 1 arriving at 5
Car 0 done refueling at 5
Car 1 starts refueling at 5
Car 2 arriving at 10
Car 1 done refueling at 10
Car 2 starts refueling at 10
Calling tanker at 15
Car 3 arriving at 15
Car 3 starts refueling at 15
Tanker arriving at 25
Car 2 done refueling at 30
Car 3 done refueling at 30
Stores

在加油站中,加油机设置为Resource,油罐的油量设为Container,Stores和Container不一样,Stores资源可以是多种多样的就像商店里的各种物品,而Container是同质的单一的无差别主体的,比如油或水.与Store不同,FilterStore可以过滤资源对象,PriorityStore可以设定资源顺序.

def producer(env, store):
    for i in range(100):
        yield env.timeout(2)
        yield store.put('spam %s' % i)
        print('Produced spam at', env.now)

def consumer(name, env, store):
    while True:
        yield env.timeout(1)
        print(name, 'requesting spam at', env.now)
        item = yield store.get()
        print(name, 'got', item, 'at', env.now)

>>> env = simpy.Environment()
>>> store = simpy.Store(env, capacity=2)

>>> prod = env.process(producer(env, store))
>>> consumers = [env.process(consumer(i, env, store)) for i in range(2)]

>>> env.run(until=5)
0 requesting spam at 1
1 requesting spam at 1
Produced spam at 2
0 got spam 0 at 2
0 requesting spam at 3
Produced spam at 4
1 got spam 1 at 4
>>> from collections import namedtuple

>>> Machine = namedtuple('Machine', 'size, duration')
>>> m1 = Machine(1, 2)  # Small and slow
>>> m2 = Machine(2, 1)  # Big and fast

>>> env = simpy.Environment()
>>> machine_shop = simpy.FilterStore(env, capacity=2)
>>> machine_shop.items = [m1, m2]  # Pre-populate the machine shop

def user(name, env, ms, size):
    machine = yield ms.get(lambda machine: machine.size == size)
    print(name, 'got', machine, 'at', env.now)
    yield env.timeout(machine.duration)
    yield ms.put(machine)
    print(name, 'released', machine, 'at', env.now)

>>> users = [env.process(user(i, env, machine_shop, (i % 2) + 1))
...          for i in range(3)]
>>> env.run()
0 got Machine(size=1, duration=2) at 0
1 got Machine(size=2, duration=1) at 0
1 released Machine(size=2, duration=1) at 1
0 released Machine(size=1, duration=2) at 2
2 got Machine(size=1, duration=2) at 2
2 released Machine(size=1, duration=2) at 4
>>> env = simpy.Environment()
>>> issues = simpy.PriorityStore(env)

def inspector(env, issues):
    for issue in [simpy.PriorityItem('P2', '#0000'),
                  simpy.PriorityItem('P0', '#0001'),
                  simpy.PriorityItem('P3', '#0002'),
                  simpy.PriorityItem('P1', '#0003')]:
        yield env.timeout(1)
        print(env.now, 'log', issue)
        yield issues.put(issue)

def maintainer(env, issues):
    while True:
        yield env.timeout(3)
        issue = yield issues.get()
        print(env.now, 'repair', issue)

>>> _ = env.process(inspector(env, issues))
>>> _ = env.process(maintainer(env, issues))
>>> env.run()
1 log PriorityItem(priority='P2', item='#0000')
2 log PriorityItem(priority='P0', item='#0001')
3 log PriorityItem(priority='P3', item='#0002')
3 repair PriorityItem(priority='P0', item='#0001')
4 log PriorityItem(priority='P1', item='#0003')
6 repair PriorityItem(priority='P1', item='#0003')
9 repair PriorityItem(priority='P2', item='#0000')
12 repair PriorityItem(priority='P3', item='#0002')

Monitoring可以监控process进程,Resource资源使用,跟踪事件模拟.

通信网络仿真包

有人基于python的SimPy包开发了网络仿真包其实就是一个类函数脚本SimComponents,,其相关的详细介绍可转到博客简介.这个仿真平台将各种网络结构抽象成相应的组件,将组件搭建连接起来,就可以完成仿真了,首先介绍网络组件.

Packet

数据包组件,不产生任何动作事件,只是单纯的数据包对象,可以用SimPy的Store资源进行数据包的存取转发,其属性有generation time;size;flow_id;packet id;source;destination.

Packet Generator

数据包生成器产生Packet数据包对象,属性有inter_arrival time;packet size;out成员变量用于将生成器连接到具有put()成员函数的任何组件.

PacketSink

数据接收端组件,记录数据包到达时间和等待时间等信息,支持put()操作.

SwitchPort

交换机端口,在数据交换路由中建立先进先出的队列,可以设置输出端口的速率和队列大小的限制,跟踪收到的数据包和丢弃的数据包.

Portmonitor

端口监视器,监视跟踪交换路由的队列大小.

RandomBrancher

随机分支,解复用元素,按概率随机选择输出端口.

PacketSink.selector

读取数据包的生成源地址,选择符合要求的数据包,进行统计等待时间等信息.

FlowDemux

解复用元素,用于通过flow_id拆分数据包流,具有与构造函数中的概率列表长度相同的输出端口列表,使用这些连接到其它网络元素.

SnoopSplitter

像分离器一样的窥探端口,将原始数据包发送到端口1,并将数据包的副本发送到端口2,设置out1和out的值.

WFQServer

WFQ是Weighted Fair Queuing,加权公平队列,高优先级流量保证带宽,但低优先级流量可以获取公平的贷款共享权力,可以预防高优先级别带宽获取不公平的资源共享.

VirtualClockServer

模拟虚拟时钟服务器

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值