Authors: |
|
---|---|
SimPy release: | 2.2 |
Web-site: | |
Python-Version: | 2.3+ (not 3.0) |
Revision: | $Revision: 297 $ |
Date: | $Date: 2009-03-31 02:24:46 +1300 (Tue, 31 Mar 2009) $ |
Contents
This manual describes SimulationRT, a SimPy module which supports synchronizing the execution of simulation models with real (wallclock) time.
SimulationRT is based on an idea by Geoff Jarrad of CSIRO (Australia). He contributed a lot to its development and testing on Windows and Unix.
The code for the adjustment of the execution speed during the simulation run was contributed by Robert C. Ramsdell.
SimulationRT allows synchronizing simulation time and real (wallclock) time. This capability can be used to implement e.g. interactive game applications or to demonstrate a model’s execution in real time.
It is identical to Simulation, except for the simulate function which takes an additional parameter controlling real-time execution speed.
Here is an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | """ RealTimeFireworks.py """
from SimPy.SimulationRT import *
from random import *
import time
## Model components -----------------------------------------------------------
class Launcher(Process):
def launch(self):
while True:
print "Launch at %2.2f; wallclock: %2.2f"%(now(),time.clock()-startTime)
yield hold,self,uniform(1,maxFlightTime)
print "Boom!!! Aaaah!! at %2.2f; wallclock: %2.2f"\
%(now(),time.clock()-startTime)
def model():
initialize()
for i in range(nrLaunchers):
lau=Launcher()
activate(lau,lau.launch())
simulate(real_time=True,rel_speed=1,until=20) ##unit sim time = 1 sec clock
## Experiment data -----------------------------------------------------------
nrLaunchers=2
maxFlightTime=5.0
startTime=time.clock()
seed(1234567)
## Experiment -----------------------------------------------------------------
model()
|
rel_speed is the ratio simulated time/wallclock time. rels_speed=1 sets the synchronization so that 1 simulation time unit is executed in approximately 1 second of wallclock time. Run under Python 2.6 on a Windows Vista-box (2.3 GHz), this output resulted over about 17.5 seconds of wallclock time:
Launch at 0.00; wallclock: 0.00
Launch at 0.00; wallclock: 0.00
Boom!!! Aaaah!! at 3.04; wallclock: 3.03
Launch at 3.04; wallclock: 3.03
Boom!!! Aaaah!! at 3.90; wallclock: 3.90
Launch at 3.90; wallclock: 3.90
Boom!!! Aaaah!! at 5.47; wallclock: 5.47
Launch at 5.47; wallclock: 5.47
Boom!!! Aaaah!! at 6.50; wallclock: 6.50
Launch at 6.50; wallclock: 6.50
Boom!!! Aaaah!! at 7.35; wallclock: 7.35
Launch at 7.35; wallclock: 7.35
Boom!!! Aaaah!! at 9.88; wallclock: 9.87
Launch at 9.88; wallclock: 9.87
Boom!!! Aaaah!! at 10.71; wallclock: 10.70
Launch at 10.71; wallclock: 10.70
Boom!!! Aaaah!! at 11.84; wallclock: 11.84
Launch at 11.84; wallclock: 11.84
Boom!!! Aaaah!! at 12.17; wallclock: 12.16
Launch at 12.17; wallclock: 12.16
Boom!!! Aaaah!! at 13.78; wallclock: 13.78
Launch at 13.78; wallclock: 13.78
Boom!!! Aaaah!! at 14.63; wallclock: 14.62
Launch at 14.63; wallclock: 14.62
Boom!!! Aaaah!! at 17.30; wallclock: 17.29
Launch at 17.30; wallclock: 17.29
Boom!!! Aaaah!! at 17.32; wallclock: 17.31
Launch at 17.32; wallclock: 17.31
Clearly, the wallclock time does not deviate significantly from the simulation time.
By calling method rtset with a parameter, the ratio simulated time to wallclock time can be changed during a run.
Here is an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | """variableTimeRatio.py
Shows the SimulationRT capability to change the ratio simulation
time to wallclock time during the run of a simulation.
"""
from SimPy.SimulationRT import *
class Changer(Process):
def change(self,when,rat):
global ratio
yield hold,self,when
rtset(rat)
ratio=rat
class Series(Process):
def tick(self,nrTicks):
oldratio=ratio
for i in range(nrTicks):
tLastSim=now()
tLastWallclock=wallclock()
yield hold,self,1
diffSim=now()-tLastSim
diffWall=wallclock()-tLastWallclock
print "now(): %s, sim. time elapsed: %s, wall clock elapsed: "\
"%6.3f, sim/wall time ratio: %6.3f"\
%(now(),diffSim,diffWall,diffSim/diffWall)
if not ratio==oldratio:
print "At simulation time %s: ratio simulation/wallclock "\
"time now changed to %s"%(now(),ratio)
oldratio=ratio
initialize()
ticks=15
s=Series()
activate(s,s.tick(nrTicks=ticks))
c=Changer()
activate(c,c.change(5,5))
c=Changer()
activate(c,c.change(10,10))
ratio=1
print "At simulation time %s: set ratio simulation/wallclock time to %s"\
%(now(),ratio)
simulate(until=100,real_time=True,rel_speed=ratio)
|
The program changes the time ratio twice, at simulation times 5 and 10.
When run on a Windows Vista computer under Python 2.6, this results in this output:
At simulation time 0: set ratio simulation/wallclock time to 1
now(): 1, sim. time elapsed: 1, wall clock elapsed: 0.998, sim/wall time ratio: 1.002
now(): 2, sim. time elapsed: 1, wall clock elapsed: 0.999, sim/wall time ratio: 1.001
now(): 3, sim. time elapsed: 1, wall clock elapsed: 0.999, sim/wall time ratio: 1.001
now(): 4, sim. time elapsed: 1, wall clock elapsed: 0.999, sim/wall time ratio: 1.001
now(): 5, sim. time elapsed: 1, wall clock elapsed: 0.999, sim/wall time ratio: 1.001
At simulation time 5: ratio simulation/wallclock time now changed to 5
now(): 6, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.027
now(): 7, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.025
now(): 8, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.026
now(): 9, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.026
now(): 10, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.024
At simulation time 10: ratio simulation/wallclock time now changed to 10
now(): 11, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.108
now(): 12, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.105
now(): 13, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.102
now(): 14, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.104
now(): 15, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.104
This module works much better under Windows than under Unix or Linux, i.e., it gives much closer synchronization. Unfortunately, the handling of time in Python is not platform-independent at all. Here is a quote from the documentation of the time module:
"clock()
On Unix, return the current processor time as a floating point number expressed in seconds.
The precision, and in fact the very definition of the meaning of ``processor time'' , depends
on that of the C function of the same name, but in any case, this is the function to use for
benchmarking Python or timing algorithms.
On Windows, this function returns wall-clock seconds elapsed since the first call to this
function, as a floating point number, based on the Win32 function QueryPerformanceCounter().
The resolution is typically better than one microsecond.
"
Basically, SimulationStep has the same API as Simulation, but with:
- a change in the definition of simulate, and
- an additional method to change execution speed during a simulation run.
Executes the simulation model.
Call:
simulate(<optional parameters>)
Changes the ratio simulation time over wall clock time.
Call:
rtset(<new ratio>)
$Revision: 297 $ $Date: 2009-03-31 02:24:46 +1300 (Tue, 31 Mar 2009) $