Made RT interrupt changes
This commit is contained in:
parent
770af49c87
commit
68a247654d
10 changed files with 47 additions and 20 deletions
6
build.sh
6
build.sh
|
|
@ -9,7 +9,7 @@ cp install_mpi4py.sh pypdevs/install_mpi4py.sh
|
|||
cd doc/sphinx
|
||||
rm -r _build/html
|
||||
make html
|
||||
./rewrite_documentation.sh
|
||||
#./rewrite_documentation.sh
|
||||
cd ../..
|
||||
cp -R doc/sphinx/_build/html/ pypdevs/doc
|
||||
cp -R src/ pypdevs/
|
||||
|
|
@ -18,7 +18,7 @@ rm test/output/*
|
|||
cp -R test/ pypdevs/
|
||||
cp LICENSE pypdevs/
|
||||
cp NOTICE pypdevs/
|
||||
mkdir pypdevs/tests/output
|
||||
mkdir -p pypdevs/tests/output
|
||||
rm pypdevs/src/pypdevs/*.pyc
|
||||
rm pypdevs/examples/*/*.pyc
|
||||
rm pypdevs/examples/*/*.pyo
|
||||
|
|
@ -37,3 +37,5 @@ rm -R pypdevs/src/pypdevs/__pycache__
|
|||
|
||||
tar -czf pypdevs.tgz pypdevs
|
||||
rm -R pypdevs
|
||||
|
||||
read -p "Press [Enter] key to continue..."
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
.. literalinclude:: ../notes.txt
|
||||
.. literalinclude:: ../../notes.txt
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ Dependencies
|
|||
|
||||
The following dependencies are mandatory:
|
||||
|
||||
* python 2.7
|
||||
* Python 2.7 **or** Python 3.6+
|
||||
|
||||
For parallel and distributed simulation, the following additional dependencies are required:
|
||||
|
||||
|
|
@ -35,6 +35,16 @@ Installation instructions are given for these two dependencies further in this s
|
|||
|
||||
Realtime simulation using the Tk backend, obviously requires Tk.
|
||||
|
||||
Download
|
||||
--------
|
||||
|
||||
The most up-to-date version of PyPDEVS can be obtained from the git repository::
|
||||
|
||||
git clone https://msdl.uantwerpen.be/git/yentl/PythonPDEVS.git
|
||||
|
||||
Alternatively, the latest release can be downloaded via:
|
||||
https://msdl.uantwerpen.be/git/yentl/PythonPDEVS/archive/master.zip
|
||||
|
||||
PyPDEVS Installation
|
||||
--------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ While examples could be given purely in their formal description, they would not
|
|||
To specify this model, we first define the event exchanged between different examples: the Job.
|
||||
A job is coded as a class ``Job``.
|
||||
It has the attributes ``size`` (i.e., indicative of processing time) and ``creation time`` (i.e., time the event was created, for statistic gathering).
|
||||
The ``Job`` class definition is shown next and can de downloaded: :download:`job.py <../examples/queueing/job.py>`.
|
||||
The ``Job`` class definition is shown next and can de downloaded: :download:`job.py <../../examples/queueing/job.py>`.
|
||||
|
||||
.. literalinclude:: ../examples/queueing/job.py
|
||||
.. literalinclude:: ../../examples/queueing/job.py
|
||||
|
||||
We now focus on each atomic model seperately, starting at the event generator.
|
||||
|
||||
|
|
@ -59,9 +59,9 @@ Finally, the output function returns a new customer event with a randomly define
|
|||
The job has an attribute containing the time at which it was generated.
|
||||
Recall, however, that the output function was invoked before the internal transition, so the current time has not yet been updated by the internal transition.
|
||||
Therefore, the output function also has to do this addition, without storing the result in the state (as it cannot write to the state).
|
||||
The ``Generator`` class definition is shown next and can de downloaded: :download:`generator.py <../examples/queueing/generator.py>`.
|
||||
The ``Generator`` class definition is shown next and can de downloaded: :download:`generator.py <../../examples/queueing/generator.py>`.
|
||||
|
||||
.. literalinclude:: ../examples/queueing/generator.py
|
||||
.. literalinclude:: ../../examples/queueing/generator.py
|
||||
|
||||
Next up is the queue, which is the most interesting component of the simulation, as it is the part we wish to analyze.
|
||||
The ``Queue`` implementation is similar in structure to the ``Generator``.
|
||||
|
|
@ -83,9 +83,9 @@ An important consideration in this model is the ``remaining\_time`` counter, whi
|
|||
We can't simply put the processing time of events in the time advance, as interrupts could happen during this time.
|
||||
When an interrupt happens (e.g., another event arrives), the time advance is invoked again, and would return the total processing time, instead of the remaining time to process the event.
|
||||
To solve this problem, we maintain a counter that explicitly gets decremented when an external interrupt happens.
|
||||
The ``Queue`` class definition is shown next and can de downloaded: :download:`queue.py <../examples/queueing/queue.py>`.
|
||||
The ``Queue`` class definition is shown next and can de downloaded: :download:`queue.py <../../examples/queueing/queue.py>`.
|
||||
|
||||
.. literalinclude:: ../examples/queueing/queue.py
|
||||
.. literalinclude:: ../../examples/queueing/queue.py
|
||||
|
||||
The next atomic model is the ``Processor`` class.
|
||||
It merely receives an incoming event and starts processing it.
|
||||
|
|
@ -95,32 +95,32 @@ We need to send out two events: one containing the job that was processed, and o
|
|||
For this, two different ports are used.
|
||||
Note that the definition of the processor would not be this simple in case there was no queue before it.
|
||||
We can now make the assumption that when we get an event, we are already idle and therefore don't need to queue new incoming events first.
|
||||
The ``Processor`` class definition is shown next and can de downloaded: :download:`processor.py <../examples/queueing/processor.py>`.
|
||||
The ``Processor`` class definition is shown next and can de downloaded: :download:`processor.py <../../examples/queueing/processor.py>`.
|
||||
|
||||
.. literalinclude:: ../examples/queueing/processor.py
|
||||
.. literalinclude:: ../../examples/queueing/processor.py
|
||||
|
||||
The processor finally sends the task to the ``Collector`` class.
|
||||
The collector is an artificial component that is not present in the system being modeled; it is only used for statistics gathering.
|
||||
For each job, it stores the time in the queue.
|
||||
The ``Collector`` class definition is shown next and can de downloaded: :download:`collector.py <../examples/queueing/collector.py>`.
|
||||
The ``Collector`` class definition is shown next and can de downloaded: :download:`collector.py <../../examples/queueing/collector.py>`.
|
||||
|
||||
.. literalinclude:: ../examples/queueing/collector.py
|
||||
.. literalinclude:: ../../examples/queueing/collector.py
|
||||
|
||||
With all atomic examples defined, we only have to couple them together in a coupled model: the ``System``.
|
||||
In this system, we instantiate a generator, queue, and collector, as well as a variable number of processors.
|
||||
The number of processors is variable, but is still static during simulation.
|
||||
The couplings also depend on the number of processors, as each processor is connected to the queue and the collector.
|
||||
The ``System`` class definition is shown next and can de downloaded: :download:`system.py <../examples/queueing/system.py>`.
|
||||
The ``System`` class definition is shown next and can de downloaded: :download:`system.py <../../examples/queueing/system.py>`.
|
||||
|
||||
.. literalinclude:: ../examples/queueing/system.py
|
||||
.. literalinclude:: ../../examples/queueing/system.py
|
||||
|
||||
Now that our DEVS model is completely specified, we can start running simulations on it.
|
||||
Simulation requires an *experiment* file though, which initializes the model with parameters and defines the simulation configuration.
|
||||
The experiment writes out the raw queueing times to a Comma Seperated Value (CSV) file.
|
||||
An experiment file often contains some configuration of the simulation tool, which differs for each tool.
|
||||
The experiment file is shown next and can de downloaded: :download:`experiment.py <../examples/queueing/experiment.py>`.
|
||||
The experiment file is shown next and can de downloaded: :download:`experiment.py <../../examples/queueing/experiment.py>`.
|
||||
|
||||
.. literalinclude:: ../examples/queueing/experiment.py
|
||||
.. literalinclude:: ../../examples/queueing/experiment.py
|
||||
|
||||
Performance Analysis
|
||||
--------------------
|
||||
|
|
|
|||
BIN
pypdevs.tgz
BIN
pypdevs.tgz
Binary file not shown.
|
|
@ -1092,6 +1092,9 @@ class BaseSimulator(Solver):
|
|||
interrupt = self.threading_backend.getInterrupt()
|
||||
if interrupt is None:
|
||||
self.realtime_counter = 100
|
||||
if wait_time == float('inf') and getattr(self, "accept_external_input", False):
|
||||
self.threading_backend.wait(0.01, self.runsim)
|
||||
else:
|
||||
self.threading_backend.wait(wait_time, self.runsim)
|
||||
return True
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class Controller(BaseSimulator):
|
|||
self.running_irreversible = None
|
||||
self.initial_allocator = None
|
||||
self.prev_termination_time = 0.0
|
||||
self.accept_external_input = False
|
||||
|
||||
def __setstate__(self, retdict):
|
||||
"""
|
||||
|
|
@ -317,6 +318,14 @@ class Controller(BaseSimulator):
|
|||
self.termination_condition = termination_condition
|
||||
self.termination_time_check = False
|
||||
|
||||
def setAcceptExternalInputs(self, aei):
|
||||
"""
|
||||
Sets the controller to accept external inputs.
|
||||
When enabled, the "early-return" of the simulator when all components have an infinite
|
||||
time-advance is ignored.
|
||||
"""
|
||||
self.accept_external_input = aei
|
||||
|
||||
def findAndPerformRelocations(self, gvt, activities, horizon):
|
||||
"""
|
||||
First requests the relocator for relocations to perform, and afterwards actually perform them.
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class ThreadingBackend(object):
|
|||
|
||||
def interrupt(self, value):
|
||||
"""
|
||||
Interrupt a running wait call.
|
||||
Interrupt a running wait call, overwriting any previous interrupts.
|
||||
|
||||
:param value: the value that interrupts
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -623,6 +623,7 @@ class SimulatorConfiguration(object):
|
|||
if not isinstance(ports, dict):
|
||||
raise DEVSException("Realtime input port references should be a dictionary")
|
||||
self.simulator.realtime_port_references = ports
|
||||
self.simulator.accept_external_input = True
|
||||
|
||||
def setModelState(self, model, new_state):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ class Simulator(object):
|
|||
self.setSchedulerActivityHeap()
|
||||
self.locations_file = None
|
||||
self.allocator = None
|
||||
self.accept_external_input = False
|
||||
self.realtime_extra = []
|
||||
|
||||
self.model_ids = []
|
||||
|
|
@ -584,6 +585,7 @@ class Simulator(object):
|
|||
self.controller.setDSDEVS(self.dsdevs)
|
||||
self.controller.setActivityTracking(self.activity_tracking)
|
||||
self.controller.setClassicDEVS(self.classicDEVS)
|
||||
self.controller.setAcceptExternalInputs(self.accept_external_input)
|
||||
self.controller.setCellLocationTracer(self.x_size,
|
||||
self.y_size,
|
||||
self.location_cell_view)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue