为需要不同资源类型的单个活动建模



进程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,1个存储用于资源A,1个用于资源B。进程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')

相关内容

  • 没有找到相关文章

最新更新