Skip to content

Commit

Permalink
Add probabilistic WCET feature
Browse files Browse the repository at this point in the history
The aim of this commit is to add new feature for real time tasks simulator
'simso'. We allow WCET of a task to be defined as a discrete Probability
Distribution Function (PDF) using a matrix (numpy array) of two row: one
for possible WCET values and the other for their corresponding
probabilities. When the WCET of a task is defined as probability
distribution, the simulator will pick random value from the possible WCET
values proportionally to their probabilities. Then, it create a new job
that has as WCET the generated random value.

The modified files in this commit are:

    - simso/utils/probabilistic_calc.py: new file contain function that
    generate random value according to a probability distribution.
    - simso/configuration/Configuration.py: In case of probabilistic
    WCET, verify that all WCET values are positive and that
    probabilities sum to one.
    - simso/core/Job.py: define new attribute '_wcet' individual value
    for each job instance.
    - simso/core/Task.py: In case of probabilistic WCET, generate random
    value of WCET using 'randon_int_from_distr' function from
    'probabilistic_calc.py' module. Then, create  new job with
    the generated WCET.
    - simso/core/__init__.py: change import order to avoid program crush.

misc/script.py file is also slightly modified to add a task 'T1' with
probabilistic WCET. When run, this script will generate a scheduling where
several instance of task 'T1' has different WCET values.
  • Loading branch information
Slim Ben Amor authored and SlimBenAmor committed Aug 11, 2022
1 parent a8cb544 commit a812822
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 19 deletions.
3 changes: 2 additions & 1 deletion misc/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import sys
from simso.core import Model
from simso.configuration import Configuration
import numpy as np


def main(argv):
Expand All @@ -21,7 +22,7 @@ def main(argv):

# Add tasks:
configuration.add_task(name="T1", identifier=1, period=7,
activation_date=0, wcet=3, deadline=7)
activation_date=0, wcet=np.array([[1,2,3],[.1,.2,.7]]), deadline=7) # add a task with a probabilistic WCET
configuration.add_task(name="T2", identifier=2, period=12,
activation_date=0, wcet=3, deadline=12)
configuration.add_task(name="T3", identifier=3, period=20,
Expand Down
29 changes: 17 additions & 12 deletions simso/configuration/Configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import re
from xml.dom import minidom
import numpy as np
from simso.core.Scheduler import SchedulerInfo
from simso.core import Scheduler
from simso.core.Task import TaskInfo
Expand Down Expand Up @@ -181,22 +182,33 @@ def check_tasks(self):
"name must begins with a letter and must not contains any "\
"special character."

# Activation date >= 0:
# Activation date >= 0:
assert task.activation_date >= 0, \
"Activation date must be positive."

# Period >= 0:
assert task.period >= 0, "Tasks' periods must be positives."

# Deadline >= 0:
# Deadline >= 0:
assert task.deadline >= 0, "Tasks' deadlines must be positives."

# N_instr >= 0:
assert task.n_instr >= 0, \
"A number of instructions must be positive."

# WCET >= 0:
assert task.wcet >= 0, "WCET must be positive."
# WCET >= 0:
if isinstance(task.wcet, np.ndarray):
assert np.min(task.wcet[0, :]) >= 0, "WCETs must be positive"
assert np.sum(task.wcet[1, :]) == 1, "probabilities sum must be 1"
else:
assert task.wcet >= 0, "WCET must be positive."
if self.etm == "cache":
# stack
assert task.stack_file, "A task needs a stack profile."

# stack ok
assert task.csdp, "Stack not found or empty."


# ACET >= 0:
assert task.acet >= 0, "ACET must be positive."
Expand All @@ -209,13 +221,6 @@ def check_tasks(self):
assert 0.0 <= task.mix <= 2.0, \
"A mix must be positive and less or equal than 2.0"

if self.etm == "cache":
# stack
assert task.stack_file, "A task needs a stack profile."

# stack ok
assert task.csdp, "Stack not found or empty."

def check_caches(self):
for index, cache in enumerate(self._caches_list):
# Id unique :
Expand All @@ -231,7 +236,7 @@ def check_caches(self):
# Taille positive :
assert cache.size >= 0, "A cache size must be positive."

# Access time >= 0:
# Access time >= 0:
assert cache.access_time >= 0, "An access time must be positive."

def get_hyperperiod(self):
Expand Down
9 changes: 6 additions & 3 deletions simso/core/Job.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Job(Process):
"""The Job class simulate the behavior of a real Job. This *should* only be
instantiated by a Task."""

def __init__(self, task, name, pred, monitor, etm, sim):
def __init__(self, task, name, pred, monitor, etm, sim, wcet=None):
"""
Args:
- `task`: The parent :class:`task <simso.core.Task.Task>`.
Expand Down Expand Up @@ -44,6 +44,7 @@ def __init__(self, task, name, pred, monitor, etm, sim):
self._monitor = monitor
self._etm = etm
self._was_running_on = task.cpu
self._wcet = wcet

self._on_activate()

Expand Down Expand Up @@ -243,7 +244,9 @@ def wcet(self):
Worst-Case Execution Time in milliseconds.
Equivalent to ``self.task.wcet``.
"""
return self._task.wcet
if (self._wcet is None):
return self._task.wcet
return self._wcet

@property
def activation_date(self):
Expand Down Expand Up @@ -291,7 +294,7 @@ def activate_job(self):
# Wait an execute order.
yield passivate, self

# Execute the job.
# Execute the job.
if not self.interrupted():
self._on_execute()
# ret is a duration lower than the remaining execution time.
Expand Down
12 changes: 10 additions & 2 deletions simso/core/Task.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

from collections import deque
from SimPy.Simulation import Process, Monitor, hold, passivate
import numpy as np
from simso.core.Job import Job
from simso.core.Timer import Timer
from simso.utils.probabilistic_calc import random_int_from_distr
from .CSDP import CSDP

import os
Expand Down Expand Up @@ -272,9 +274,15 @@ def create_job(self, pred=None):
directly by a scheduler.
"""
self._job_count += 1
job = Job(self, "{}_{}".format(self.name, self._job_count), pred,
monitor=self._monitor, etm=self._etm, sim=self.sim)

# pick random wcet according to their probabilities
if isinstance(self.wcet, np.ndarray):
wcet_sample = random_int_from_distr(self.wcet, n_sample=1)[0]
else:
wcet_sample = None

job = Job(self, "{}_{}".format(self.name, self._job_count), pred,
monitor=self._monitor, etm=self._etm, sim=self.sim, wcet=wcet_sample)
if len(self._activations_fifo) == 0:
self.job = job
self.sim.activate(job, job.activate_job())
Expand Down
2 changes: 1 addition & 1 deletion simso/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
The core module include all the classes needed for the simulation.
"""

from simso.core.Scheduler import Scheduler
from simso.core.JobEvent import JobEvent
from simso.core.ProcEvent import ProcEvent
from simso.core.Model import Model
from simso.core.Processor import Processor
from simso.core.Scheduler import Scheduler
from simso.core.Timer import Timer
from simso.core.results import Results
48 changes: 48 additions & 0 deletions simso/utils/probabilistic_calc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Nov 27 17:23:01 2018
@author: sbenamor
"""

from random import random
import numpy as np


def random_int_from_distr(proba_dist, n_sample=1):
""" function that generate n random value according to a given
discrete probability distribution proba_dist
Args:
- proba_dist (numpy array 2*m): discrete probability distribution with m possible value.
- n_sample (int): number of generated samples.
Returns:
- list: list of n random generated values.
Example:
>>> randon_int_distr(np.array([[5],[1]]),1) #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
[5]
>>> randon_int_distr(np.array([[2,3,8],[.1, .2, .7]]),1)[0] in [2,3,8] #doctest: \
+ELLIPSIS +NORMALIZE_WHITESPACE
1
>>> np.all(np.isin(randon_int_distr(np.array([[2,3,8],[.1, .2, .7]]),5), [2,3,8])) \
#doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
True
"""
samples = []

cdf = np.cumsum(proba_dist[1, :]) # Cumulative Distribution Function

for _ in range(n_sample):
proba = random() # generate a probability value uniformly between 0 and 1
rand_value_index = np.argmax(cdf > proba) # transform generated probability to a value from the distribution using cdf function
samples.append(int(proba_dist[0, rand_value_index]))

return samples


if __name__ == "__main__":
import doctest
doctest.testmod()

0 comments on commit a812822

Please sign in to comment.