[英]Model single activity requiring different resource types
进程 3 需要资源 A 和 B,并且只能在进程 1(由资源 A)和进程 2(由资源 B)完成后启动。 下面的代码似乎按预期执行,但 if / else 语句看起来很不优雅。 是否有“更好”的方式来完成相同的行为?
def orchestration(self):
# Request resources A and B
req_resourceA = self.resourceA.request()
req_resourceB = self.resourceB.request()
# Wait until first resource is available (will change throughout simulation)
available_rec = yield.self.env.any_of([req_resourceA, req_resourceB])
if list(available_rec.keys())[0] == resourceA:
proc1 = self.env.process(self.process1())
yield resourceB
proc2 = self.env.process(self.process2())
else:
proc2 = self.env.process(self.process2())
yield resourceA
proc1 = self.env.process(self.process1())
# Start process 3 only after processes 1 and 2 have been completed
yield proc1 & proc2
yield self.env.timeout(process3_time)
# Manually release both resource requests
self.resourceA.release(req_resourceA)
self.resourceB.release(req_resourceB)
在此解决方案中,我并行而不是按顺序运行进程 1 和 2,并使用 all_of 等待两个进程完成。 这应该会减少资源的一些空闲时间。 进程 1 和 2 也获取它们需要的资源,但不释放它。 相反,他们返回请求,以便将其传递给进程 3。我将资源请求传递给进程 3,认为进程 3 会知道何时释放每个资源。 例如进程 3 可以释放资源 A,做更多的事情,然后释放资源 B
"""
One way steps can be sequcenced
In this example the pre steps are run in parallel
rather the sequentially
Programmer: Michael R. Gibbs
"""
from urllib import request
import simpy
import random
def process1(env, resPool):
"""
Simple process that grabs a resource and does some processing
The resource request is not released, but returned to the calling process
"""
resRequest = resPool.request()
yield resRequest
print(f'{env.now:0.2f} process 1 has resource and started')
yield env.timeout(random.randint(1,5))
print(f'{env.now:0.2f} process 1 has finish')
return resRequest
def process2(env, resPool):
"""
another simple process that grabs a resource and does some processing
The resource request is not released, but returned to the calling process
"""
resRequest = resPool.request()
yield resRequest
print(f'{env.now:0.2f} process 2 has resource and started')
yield env.timeout(random.randint(1,5))
print(f'{env.now:0.2f} process 2 has finish')
return resRequest
def process3(env, resourceAPool, requestA, resourceBPool, requestB):
"""
Final process that reuses resouces from process1 and process2
which this process is dependant on
"""
print(f'{env.now:0.2f} process 3 started')
yield env.timeout(random.randint(1,5))
resourceAPool.release(requestA)
resourceBPool.release(requestB)
print(f'{env.now:0.2f} process 3 finish')
def endToEndProcessing(env, resourceAPool, resourceBPool):
"""
the end to end processes
where process1 and process2 must complete before process 3 can start
"""
while True:
# start each pre process, but do not yeild so they runn in parallel
proc1 = env.process(process1(env,resourceAPool))
proc2 = env.process(process2(env,resourceBPool))
# wait for both processes to finish
preProcesses = yield env.all_of([proc1, proc2])
# get resource requests and pass to process 3
reqA = preProcesses[proc1]
reqB = preProcesses[proc2]
yield env.process(process3(env, resourceAPool, reqA, resourceBPool, reqB))
env = env = simpy.Environment()
resourceAPool = simpy.Resource(env, capacity=1)
resourceBPool = simpy.Resource(env, capacity=1)
env.process(endToEndProcessing(env, resourceAPool, resourceBPool))
env.run(100)
这是一个更复杂的答案
这里每个进程都是异步运行的,使用资源和存储来控制进程的运行。 这里的优点是您可以拥有多个进程,并且通过控制每个进程的数量,您可以进行一些负载平衡。
基本流程是进程 1 和 2 获取资源,通过 2 个存储将资源传递给进程 3,资源 A 存储 1,资源 B 存储 1。进程 3 完成后释放资源
"""
One way steps can be sequenced
In this example the all the processes are run asyc
using a couple of stores to control when process 3 can run
The advanatage to this is allows for load balancing.
For example if process1 takes twice as long as process2
and process2 takes twice as long as process3, then
best resource use might be with 4 process1's 2 process2's and 1 process3
Programmer: Michael R. Gibbs
"""
from urllib import request
import simpy
import random
process3Cnt = 0
def process1(env, id, resPool, reqStore):
"""
Simple process that grabs a resource and does some processing
The resource request is not released, but returned to a store
which process 3 uses to know when it can start
"""
while True:
resRequest = resPool.request()
yield resRequest
print(f'{env.now:0.2f} process 1 id:{id} has resource and started')
yield env.timeout(random.randint(1,16))
reqStore.put(resRequest)
print(f'{env.now:0.2f} process 1 id:{id} has finish')
def process2(env, id, resPool, reqStore):
"""
Another Simple process that grabs a resource and does some processing
The resource request is not released, but returned to a store
which process 3 uses to know when it can start
"""
while True:
resRequest = resPool.request()
yield resRequest
print(f'{env.now:0.2f} process 2 id:{id} has resource and started')
yield env.timeout(random.randint(1,8))
reqStore.put(resRequest)
print(f'{env.now:0.2f} process 2 id:{id} has finish')
def process3(env, id, resourceAPool, requestAStore, resourceBPool, requestBStore):
"""
Final process that reuses resouces from process1 and process2
which this process is dependant on
The resouce requests are passed to proccess 3 using stores
"""
global process3Cnt
while True:
storeAReq = requestAStore.get()
storeBReq = requestBStore.get()
# wait for both store request to finish
storeRequests = yield env.all_of([storeAReq, storeBReq])
# get the resource requests
requestA = storeRequests[storeAReq]
requestB = storeRequests[storeBReq]
print(f'{env.now:0.2f} process 3 id:{id} started')
yield env.timeout(random.randint(1,4))
# release the resources
resourceAPool.release(requestA)
resourceBPool.release(requestB)
print(f'{env.now:0.2f} process 3 id:{id} finish')
process3Cnt += 1
env = env = simpy.Environment()
resourceAPool = simpy.Resource(env, capacity=4)
resourceBPool = simpy.Resource(env, capacity=2)
requestAStore = simpy.Store(env)
requestBStore = simpy.Store(env)
# try changing the number of each process to maximize the throughput
#launch process1
for id in range(1,5):
env.process(process1(env, id, resourceAPool, requestAStore))
#launch process2
for id in range(1,3):
env.process(process2(env, id, resourceBPool, requestBStore))
#launch process3
for id in range(1,2):
env.process(process3(env, id, resourceAPool, requestAStore, resourceBPool, requestBStore))
env.run(100)
print(f'Process 3 ran {process3Cnt} times')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.