Simulation with Real Time Synchronization¶
- Authors:
Klaus Muller <Muller@users.sourceforge.net>
Tony Vignaux <Vignaux@users.sourceforge.net>
- SimPy release:
2.3.1
- Web-site:
- Python-Version:
2.6+
- Date:
December 2011
This manual describes SimulationRT, a SimPy module which supports synchronizing the execution of simulation models with real (wallclock) time.
Acknowledgement¶
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.
Synchronizing with wall clock time¶
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""" RealTimeFireworks.py """
2from SimPy.SimulationRT import *
3from random import *
4import time
5## Model components -----------------------------------------------------------
6class Launcher(Process):
7 def launch(self):
8 while True:
9 print "Launch at %2.2f; wallclock: %2.2f"%(now(),time.clock()-startTime)
10 yield hold,self,uniform(1,maxFlightTime)
11 print "Boom!!! Aaaah!! at %2.2f; wallclock: %2.2f"\
12 %(now(),time.clock()-startTime)
13def model():
14 initialize()
15 for i in range(nrLaunchers):
16 lau=Launcher()
17 activate(lau,lau.launch())
18 simulate(real_time=True,rel_speed=1,until=20) ##unit sim time = 1 sec clock
19## Experiment data -----------------------------------------------------------
20nrLaunchers=2
21maxFlightTime=5.0
22startTime=time.clock()
23seed(1234567)
24## Experiment -----------------------------------------------------------------
25model()
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:
1Launch at 0.00; wallclock: 0.00
2Launch at 0.00; wallclock: 0.00
3Boom!!! Aaaah!! at 3.04; wallclock: 3.03
4Launch at 3.04; wallclock: 3.03
5Boom!!! Aaaah!! at 3.90; wallclock: 3.90
6Launch at 3.90; wallclock: 3.90
7Boom!!! Aaaah!! at 5.47; wallclock: 5.47
8Launch at 5.47; wallclock: 5.47
9Boom!!! Aaaah!! at 6.50; wallclock: 6.50
10Launch at 6.50; wallclock: 6.50
11Boom!!! Aaaah!! at 7.35; wallclock: 7.35
12Launch at 7.35; wallclock: 7.35
13Boom!!! Aaaah!! at 9.88; wallclock: 9.87
14Launch at 9.88; wallclock: 9.87
15Boom!!! Aaaah!! at 10.71; wallclock: 10.70
16Launch at 10.71; wallclock: 10.70
17Boom!!! Aaaah!! at 11.84; wallclock: 11.84
18Launch at 11.84; wallclock: 11.84
19Boom!!! Aaaah!! at 12.17; wallclock: 12.16
20Launch at 12.17; wallclock: 12.16
21Boom!!! Aaaah!! at 13.78; wallclock: 13.78
22Launch at 13.78; wallclock: 13.78
23Boom!!! Aaaah!! at 14.63; wallclock: 14.62
24Launch at 14.63; wallclock: 14.62
25Boom!!! Aaaah!! at 17.30; wallclock: 17.29
26Launch at 17.30; wallclock: 17.29
27Boom!!! Aaaah!! at 17.32; wallclock: 17.31
28Launch at 17.32; wallclock: 17.31
Clearly, the wallclock time does not deviate significantly from the simulation time.
Changing the execution speed during a simulation run¶
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"""variableTimeRatio.py
2Shows the SimulationRT capability to change the ratio simulation
3time to wallclock time during the run of a simulation.
4"""
5from SimPy.SimulationRT import *
6
7class Changer(Process):
8 def change(self,when,rat):
9 global ratio
10 yield hold,self,when
11 rtset(rat)
12 ratio=rat
13class Series(Process):
14 def tick(self,nrTicks):
15 oldratio=ratio
16 for i in range(nrTicks):
17 tLastSim=now()
18 tLastWallclock=wallclock()
19 yield hold,self,1
20 diffSim=now()-tLastSim
21 diffWall=wallclock()-tLastWallclock
22 print "now(): %s, sim. time elapsed: %s, wall clock elapsed: "\
23 "%6.3f, sim/wall time ratio: %6.3f"\
24 %(now(),diffSim,diffWall,diffSim/diffWall)
25 if not ratio==oldratio:
26 print "At simulation time %s: ratio simulation/wallclock "\
27 "time now changed to %s"%(now(),ratio)
28 oldratio=ratio
29initialize()
30ticks=15
31s=Series()
32activate(s,s.tick(nrTicks=ticks))
33c=Changer()
34activate(c,c.change(5,5))
35c=Changer()
36activate(c,c.change(10,10))
37ratio=1
38print "At simulation time %s: set ratio simulation/wallclock time to %s"\
39 %(now(),ratio)
40simulate(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:
1At simulation time 0: set ratio simulation/wallclock time to 1
2now(): 1, sim. time elapsed: 1, wall clock elapsed: 0.998, sim/wall time ratio: 1.002
3now(): 2, sim. time elapsed: 1, wall clock elapsed: 0.999, sim/wall time ratio: 1.001
4now(): 3, sim. time elapsed: 1, wall clock elapsed: 0.999, sim/wall time ratio: 1.001
5now(): 4, sim. time elapsed: 1, wall clock elapsed: 0.999, sim/wall time ratio: 1.001
6now(): 5, sim. time elapsed: 1, wall clock elapsed: 0.999, sim/wall time ratio: 1.001
7At simulation time 5: ratio simulation/wallclock time now changed to 5
8now(): 6, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.027
9now(): 7, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.025
10now(): 8, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.026
11now(): 9, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.026
12now(): 10, sim. time elapsed: 1, wall clock elapsed: 0.199, sim/wall time ratio: 5.024
13At simulation time 10: ratio simulation/wallclock time now changed to 10
14now(): 11, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.108
15now(): 12, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.105
16now(): 13, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.102
17now(): 14, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.104
18now(): 15, sim. time elapsed: 1, wall clock elapsed: 0.099, sim/wall time ratio: 10.104
Limitations¶
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:
1"clock()
2On Unix, return the current processor time as a floating point number expressed in seconds.
3The precision, and in fact the very definition of the meaning of ``processor time'' , depends
4on that of the C function of the same name, but in any case, this is the function to use for
5benchmarking Python or timing algorithms.
6
7On Windows, this function returns wall-clock seconds elapsed since the first call to this
8function, as a floating point number, based on the Win32 function QueryPerformanceCounter().
9The resolution is typically better than one microsecond.
10"
The SimulationRT API¶
Structure¶
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.
simulate¶
Executes the simulation model.
Call:
simulate(<optional parameters>)
- Mandatory parameters:
None.
- Optional parameters:
until=0 : the maximum simulation (end) time (positive floating point number; default: 0)
real_time=False : flag to switch real time synchronization on or off (boolean; default: False, meaning no synchronization)
rel_speed=1 : ratio simulation time over wallclock time; example: rel_speed=200 executes 200 units of simulation time in about one second (positive floating point number; default: 1, i.e. 1 sec of simulation time is executed in about 1 sec of wallclock time)
- Return value:
Simulation status at exit.
rtset¶
Changes the ratio simulation time over wall clock time.
Call:
rtset(<new ratio>)
- Mandatory parameters:
None
- Optional parameters:
rel_speed=1 : ratio simulation time over wallclock time; example: rel_speed=200 executes 200 units of simulation time in about one second (positive floating point number; default: 1, i.e. 1 sec of simulation time is executed in about 1 sec of wallclock time)
- Return value:
None