Skip to content

Commit a812822

Browse files
Slim Ben AmorSlimBenAmor
authored andcommitted
Add probabilistic WCET feature
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.
1 parent a8cb544 commit a812822

6 files changed

Lines changed: 84 additions & 19 deletions

File tree

misc/script.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88
from simso.core import Model
99
from simso.configuration import Configuration
10+
import numpy as np
1011

1112

1213
def main(argv):
@@ -21,7 +22,7 @@ def main(argv):
2122

2223
# Add tasks:
2324
configuration.add_task(name="T1", identifier=1, period=7,
24-
activation_date=0, wcet=3, deadline=7)
25+
activation_date=0, wcet=np.array([[1,2,3],[.1,.2,.7]]), deadline=7) # add a task with a probabilistic WCET
2526
configuration.add_task(name="T2", identifier=2, period=12,
2627
activation_date=0, wcet=3, deadline=12)
2728
configuration.add_task(name="T3", identifier=3, period=20,

simso/configuration/Configuration.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import re
66
from xml.dom import minidom
7+
import numpy as np
78
from simso.core.Scheduler import SchedulerInfo
89
from simso.core import Scheduler
910
from simso.core.Task import TaskInfo
@@ -181,22 +182,33 @@ def check_tasks(self):
181182
"name must begins with a letter and must not contains any "\
182183
"special character."
183184

184-
# Activation date >= 0:
185+
# Activation date >= 0:
185186
assert task.activation_date >= 0, \
186187
"Activation date must be positive."
187188

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

191-
# Deadline >= 0:
192+
# Deadline >= 0:
192193
assert task.deadline >= 0, "Tasks' deadlines must be positives."
193194

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

198-
# WCET >= 0:
199-
assert task.wcet >= 0, "WCET must be positive."
199+
# WCET >= 0:
200+
if isinstance(task.wcet, np.ndarray):
201+
assert np.min(task.wcet[0, :]) >= 0, "WCETs must be positive"
202+
assert np.sum(task.wcet[1, :]) == 1, "probabilities sum must be 1"
203+
else:
204+
assert task.wcet >= 0, "WCET must be positive."
205+
if self.etm == "cache":
206+
# stack
207+
assert task.stack_file, "A task needs a stack profile."
208+
209+
# stack ok
210+
assert task.csdp, "Stack not found or empty."
211+
200212

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

212-
if self.etm == "cache":
213-
# stack
214-
assert task.stack_file, "A task needs a stack profile."
215-
216-
# stack ok
217-
assert task.csdp, "Stack not found or empty."
218-
219224
def check_caches(self):
220225
for index, cache in enumerate(self._caches_list):
221226
# Id unique :
@@ -231,7 +236,7 @@ def check_caches(self):
231236
# Taille positive :
232237
assert cache.size >= 0, "A cache size must be positive."
233238

234-
# Access time >= 0:
239+
# Access time >= 0:
235240
assert cache.access_time >= 0, "An access time must be positive."
236241

237242
def get_hyperperiod(self):

simso/core/Job.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Job(Process):
99
"""The Job class simulate the behavior of a real Job. This *should* only be
1010
instantiated by a Task."""
1111

12-
def __init__(self, task, name, pred, monitor, etm, sim):
12+
def __init__(self, task, name, pred, monitor, etm, sim, wcet=None):
1313
"""
1414
Args:
1515
- `task`: The parent :class:`task <simso.core.Task.Task>`.
@@ -44,6 +44,7 @@ def __init__(self, task, name, pred, monitor, etm, sim):
4444
self._monitor = monitor
4545
self._etm = etm
4646
self._was_running_on = task.cpu
47+
self._wcet = wcet
4748

4849
self._on_activate()
4950

@@ -243,7 +244,9 @@ def wcet(self):
243244
Worst-Case Execution Time in milliseconds.
244245
Equivalent to ``self.task.wcet``.
245246
"""
246-
return self._task.wcet
247+
if (self._wcet is None):
248+
return self._task.wcet
249+
return self._wcet
247250

248251
@property
249252
def activation_date(self):
@@ -291,7 +294,7 @@ def activate_job(self):
291294
# Wait an execute order.
292295
yield passivate, self
293296

294-
# Execute the job.
297+
# Execute the job.
295298
if not self.interrupted():
296299
self._on_execute()
297300
# ret is a duration lower than the remaining execution time.

simso/core/Task.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
from collections import deque
44
from SimPy.Simulation import Process, Monitor, hold, passivate
5+
import numpy as np
56
from simso.core.Job import Job
67
from simso.core.Timer import Timer
8+
from simso.utils.probabilistic_calc import random_int_from_distr
79
from .CSDP import CSDP
810

911
import os
@@ -272,9 +274,15 @@ def create_job(self, pred=None):
272274
directly by a scheduler.
273275
"""
274276
self._job_count += 1
275-
job = Job(self, "{}_{}".format(self.name, self._job_count), pred,
276-
monitor=self._monitor, etm=self._etm, sim=self.sim)
277277

278+
# pick random wcet according to their probabilities
279+
if isinstance(self.wcet, np.ndarray):
280+
wcet_sample = random_int_from_distr(self.wcet, n_sample=1)[0]
281+
else:
282+
wcet_sample = None
283+
284+
job = Job(self, "{}_{}".format(self.name, self._job_count), pred,
285+
monitor=self._monitor, etm=self._etm, sim=self.sim, wcet=wcet_sample)
278286
if len(self._activations_fifo) == 0:
279287
self.job = job
280288
self.sim.activate(job, job.activate_job())

simso/core/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
The core module include all the classes needed for the simulation.
33
"""
44

5+
from simso.core.Scheduler import Scheduler
56
from simso.core.JobEvent import JobEvent
67
from simso.core.ProcEvent import ProcEvent
78
from simso.core.Model import Model
89
from simso.core.Processor import Processor
9-
from simso.core.Scheduler import Scheduler
1010
from simso.core.Timer import Timer
1111
from simso.core.results import Results

simso/utils/probabilistic_calc.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
Created on Tue Nov 27 17:23:01 2018
5+
6+
@author: sbenamor
7+
"""
8+
9+
from random import random
10+
import numpy as np
11+
12+
13+
def random_int_from_distr(proba_dist, n_sample=1):
14+
""" function that generate n random value according to a given
15+
discrete probability distribution proba_dist
16+
17+
Args:
18+
- proba_dist (numpy array 2*m): discrete probability distribution with m possible value.
19+
- n_sample (int): number of generated samples.
20+
21+
Returns:
22+
- list: list of n random generated values.
23+
24+
Example:
25+
>>> randon_int_distr(np.array([[5],[1]]),1) #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
26+
[5]
27+
>>> randon_int_distr(np.array([[2,3,8],[.1, .2, .7]]),1)[0] in [2,3,8] #doctest: \
28+
+ELLIPSIS +NORMALIZE_WHITESPACE
29+
1
30+
>>> np.all(np.isin(randon_int_distr(np.array([[2,3,8],[.1, .2, .7]]),5), [2,3,8])) \
31+
#doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
32+
True
33+
"""
34+
samples = []
35+
36+
cdf = np.cumsum(proba_dist[1, :]) # Cumulative Distribution Function
37+
38+
for _ in range(n_sample):
39+
proba = random() # generate a probability value uniformly between 0 and 1
40+
rand_value_index = np.argmax(cdf > proba) # transform generated probability to a value from the distribution using cdf function
41+
samples.append(int(proba_dist[0, rand_value_index]))
42+
43+
return samples
44+
45+
46+
if __name__ == "__main__":
47+
import doctest
48+
doctest.testmod()

0 commit comments

Comments
 (0)