├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── data ├── P_n_task_DAG_FTP_C_varyingM.yml ├── P_n_task_DAG_FTP_I_varyingU.yml ├── SOTA_n_task_DAG_FTP_C_varyingU.yml ├── n_task_CDAG_FTP_C_varyingN.yml ├── n_task_DAG_EDF_C_varyingM.yml ├── n_task_DAG_EDF_C_varyingN.yml ├── n_task_DAG_EDF_C_varyingU.yml ├── n_task_DAG_EDF_I_varyingN.yml ├── n_task_DAG_FTP_A_varyingM.yml ├── n_task_DAG_FTP_A_varyingN.yml ├── n_task_DAG_FTP_A_varyingU.yml ├── n_task_DAG_FTP_C_varyingM.yml ├── n_task_DAG_FTP_C_varyingN.yml ├── n_task_DAG_FTP_C_varyingU.yml ├── single_task_CDAG_FTP_I_varyingM.yml ├── single_task_DAG_EDF_A_varyingM.yml ├── single_task_DAG_EDF_A_varyingU.yml ├── single_task_DAG_EDF_C_varyingM.yml ├── single_task_DAG_EDF_C_varyingU.yml ├── single_task_DAG_FTP_A_varyingM.yml ├── single_task_DAG_FTP_A_varyingU.yml ├── single_task_DAG_FTP_C_varyingM.yml ├── single_task_DAG_FTP_C_varyingU.yml └── thesis │ ├── multi │ ├── P_n_task_DAG_FTP_I_varyingM.yml │ ├── P_n_task_DAG_FTP_I_varyingU.yml │ ├── SOTA_n_task_DAG_FTP_C_varyingM.yml │ ├── SOTA_n_task_DAG_FTP_C_varyingU.yml │ ├── n_task_CDAG_FTP_C_varyingM.yml │ ├── n_task_CDAG_FTP_C_varyingU.yml │ ├── n_task_DAG_EDF_I_varyingM.yml │ ├── n_task_DAG_EDF_I_varyingU.yml │ ├── n_task_DAG_FTP_A_varyingM.yml │ ├── n_task_DAG_FTP_A_varyingU.yml │ ├── n_task_DAG_FTP_C_varyingM.yml │ ├── n_task_DAG_FTP_C_varyingU.yml │ ├── n_task_DAG_FTP_I_varyingM.yml │ └── n_task_DAG_FTP_I_varyingU.yml │ └── single │ ├── P_single_task_DAG_FTP_I_varyingU.yml │ ├── SOTA_single_task_DAG_FTP_C_varyingU.yml │ ├── single_task_CDAG_FTP_C_varyingU.yml │ ├── single_task_DAG_EDF_I_varyingU.yml │ ├── single_task_DAG_FTP_A_varyingU.yml │ ├── single_task_DAG_FTP_C_varyingU.yml │ └── single_task_DAG_FTP_I_varyingU.yml ├── demo ├── dot_files.txt ├── eval_all.sh ├── evaluate.cpp ├── main.cpp ├── taskset.yaml ├── taskset_2.yaml └── test0.dot ├── img ├── dot_format.png └── sched_times.png ├── include └── dagSched │ ├── DAGTask.h │ ├── GeneratorParams.h │ ├── SP-Tree.h │ ├── SubTask.h │ ├── Taskset.h │ ├── evaluate.h │ ├── plot_utils.h │ ├── scheduling_utils.h │ ├── tests.h │ └── utils.h └── src ├── DAGTask ├── DAGTask.cpp ├── DAGTask_Melani.cpp └── DAGTask_io.cpp ├── SP-Tree.cpp ├── SubTask.cpp ├── Taskset.cpp ├── tests ├── Baruah2012.cpp ├── Baruah2014.cpp ├── Bonifaci2013.cpp ├── Casini2018.cpp ├── Chang2020.cpp ├── Fonseca2016.cpp ├── Fonseca2017.cpp ├── Fonseca2019.cpp ├── Graham1969.cpp ├── Han2019.cpp ├── He2019.cpp ├── Li2013.cpp ├── Melani2015.cpp ├── Nasri2019.cpp ├── Pathan2017.cpp ├── Qamhieh2013.cpp ├── Serrano2016.cpp ├── Zahaf2019.cpp └── tests_common.cpp └── utils.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *vscode/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "np-schedulability-analysis"] 2 | path = np-schedulability-analysis 3 | url = https://github.com/brandenburg/np-schedulability-analysis 4 | [submodule "matplotlib-cpp"] 5 | path = matplotlib-cpp 6 | url = https://github.com/mive93/matplotlib-cpp 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(dag-sched CXX) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC -Wno-deprecated-declarations -Wno-unused-variable") 5 | 6 | #------------------------------------------------------------------------------- 7 | # Options 8 | #------------------------------------------------------------------------------- 9 | 10 | option(WITH_ZAHAF "Compiling also for Zahaf2019 test (if you have the rights to access the repo)" OFF) 11 | 12 | #------------------------------------------------------------------------------- 13 | # External Libraries 14 | #------------------------------------------------------------------------------- 15 | find_package(Eigen3 REQUIRED) 16 | include_directories(${EIGEN3_INCLUDE_DIR}) 17 | 18 | find_package(yaml-cpp REQUIRED) 19 | 20 | find_package(Python3 COMPONENTS Interpreter Development) 21 | message("Python_FOUND:${Python3_FOUND}") 22 | # message("Python_VERSION:${Python3_VERSION}") 23 | # message("Python_Development_FOUND:${Python3_Development_FOUND}") 24 | message("Python_LIBRARIES:${Python3_LIBRARIES}") 25 | message("Python_INCLUDE_DIRS:${Python3_INCLUDE_DIRS}") 26 | 27 | #------------------------------------------------------------------------------- 28 | # Submodules 29 | #------------------------------------------------------------------------------- 30 | 31 | add_subdirectory(np-schedulability-analysis) 32 | 33 | if(WITH_ZAHAF) 34 | add_compile_definitions(ZAHAF2019) 35 | add_subdirectory(rt_compiler) 36 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rt_compiler ${CMAKE_CURRENT_SOURCE_DIR}/rt_compiler/build) 37 | endif() 38 | 39 | #------------------------------------------------------------------------------- 40 | # Build libraries 41 | #------------------------------------------------------------------------------- 42 | 43 | 44 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include matplotlib-cpp 45 | ${CMAKE_CURRENT_SOURCE_DIR}/np-schedulability-analysis/include 46 | ${Python3_INCLUDE_DIRS}) 47 | 48 | file(GLOB dag-sched-SRC "src/*/*.cpp" "src/*.cpp") 49 | 50 | if(WITH_ZAHAF) 51 | set(dag-sched-LIBS yaml-cpp ${Python3_LIBRARIES} tbb rt_compiler) 52 | else() 53 | set(dag-sched-LIBS yaml-cpp ${Python3_LIBRARIES} tbb) 54 | endif() 55 | 56 | add_library(dag-sched SHARED ${dag-sched-SRC}) 57 | target_link_libraries(dag-sched ${dag-sched-LIBS} ) 58 | 59 | #------------------------------------------------------------------------------- 60 | # Build executables 61 | #------------------------------------------------------------------------------- 62 | add_executable(demo demo/main.cpp) 63 | target_link_libraries(demo dag-sched) 64 | 65 | add_executable(eval demo/evaluate.cpp) 66 | target_link_libraries(eval dag-sched) 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A library to test schedulability of the real-time DAG task model 2 | 3 | This repo offers a library to handle the real-time Directed Acyclic Graph (DAG) task model and its extensions, such as the Conditional DAG and the Typed DAG. 4 | Moreover, several methods from real-time literature have been implemented. 5 | It's one of the contributions of Micaela Verucchi's Ph.D. thesis "A comprehensive analysis of DAG tasks: solutions for modern real-time embedded systems". 6 | 7 | If you use this code in your research, please cite the following paper. 8 | 9 | ``` 10 | @article{verucchi2023survey, 11 | title={A survey on real-time DAG scheduling, revisiting the Global-Partitioned Infinity War}, 12 | author={Verucchi, Micaela and Olmedo, Ignacio Sa{\~n}udo and Bertogna, Marko}, 13 | journal={Real-Time Systems}, 14 | pages={1--52}, 15 | year={2023}, 16 | publisher={Springer} 17 | } 18 | ``` 19 | 20 | ## Dependencies 21 | 22 | For this repo the following libraries are needed: graphviz (for dot), libyaml-cpp-dev (to read yaml confi files) and python3-matplotlib (to plot the charts). 23 | On Linux, install the dependencies in this way: 24 | 25 | ``` 26 | sudo apt-get install graphviz libyaml-cpp-dev python3-matplotlib libtbb-dev libeigen3-dev python3-dev 27 | 28 | 29 | ``` 30 | 31 | ## How to compile this repo 32 | 33 | Once the dependencies have been installed, build the project with cmake. 34 | 35 | ``` 36 | git clone https://github.com/mive93/DAG-scheduling 37 | cd DAG-scheduling 38 | git submodule update --init --recursive 39 | mkdir build && cd build 40 | cmake .. 41 | make 42 | ``` 43 | 44 | ## Input and output 45 | 46 | This library reads and outputs DAG in DOT format as shown in the image. 47 | 48 | ![dot](img/dot_format.png "DAG with DOT") 49 | 50 | ### Input 51 | 52 | The library accept two input formats for taskse: yaml or DOT. 53 | 54 | #### YAML format 55 | 56 | A taskset is specified as an array of task, which has the following params 57 | * ```t``` the period 58 | * ```d``` the deadline 59 | * ```vertices``` array of nodes of the DAG, defined by: 60 | * ```id``` id of the node 61 | * ```c``` WCET of the node 62 | * ```p``` core to which the node is assigned to [optional] 63 | * ```s``` gamma, the kind of engine the node is assigned to [optional] 64 | 65 | An example is given with demo/taskset.yaml. 66 | #### DOT format 67 | 68 | Each DAG is defined via a DOT file, and each path of dot file belonging to the taskset should be written (line by line) in a txt file. 69 | An example is given in demo/dot_files.txt 70 | 71 | Each DOT file is the defined with this convention. 72 | At the begninning there is an initial node with the info of the DAG Task, where the deadline ```D``` and the period ```T``` should be specified. For example: 73 | ```i [shape=box, D=603.859, T=1605.45]; ``` 74 | 75 | Then each node is secified by an ID, a label which represent the WCET and additional optional parameters, as ```p``` and ```s```. For example: 76 | ``` 0 [label="57", p=7];``` 77 | 78 | Finally the edges are discribed only via nodes IDs. For example: 79 | ``` 0 -> 2;``` 80 | 81 | A complete example is given in demo/test0.dot. 82 | 83 | ### Output 84 | 85 | To convert a dot file into a png image use the following command: 86 | 87 | ``` 88 | dot -Tpng test.dot > test.png 89 | ``` 90 | 91 | ## Demo 92 | The demo is a program that tests all the supported methods on user-defined DAG task set or a randomly generated one. 93 | It can be executed as 94 | 95 | ``` 96 | ./demo 97 | ``` 98 | 99 | where 100 | * ``` ``` can be set to 0 if the taskset should be read from file, or to 1 if the taskset should be randomly generated, using the method proposed by Melani et al. [1][2]. 101 | * `````` path to the file that describes the task set to analyze if ``` ``` is set to 0. 102 | 103 | ## Eval 104 | The eval program will evaluate several schedulability methods based on a given config file. 105 | To run the evaluation execute: 106 | 107 | ``` 108 | ./eval 109 | ``` 110 | Where 111 | * `````` is a yml file, like the ones in the data folder, that specifies all the parameters for the task set generation and the selection of the methods to evaluate. 112 | * `````` 1 to show plots, 0 to hide them. In any case, the resulting plots will not be shown but saved in a folder named res. 113 | 114 | At the end of each evaluation two kinds of plots will be produced, one regarding the schedulability rate and one the execution times of the methods. 115 | 116 | ![plots](img/sched_times.png "Resulting plots") 117 | 118 | 119 | ## Supported schedulability tests 120 | 121 | | Work | Workload | Deadline | Model | Scheduling | Preemption | Algorithm | 122 | | ----------------------| ----------- | -------- | ---------- | ---------- | ---------- | --------- | 123 | | Baruah2012 [3] | single task | C | DAG | G | - | EDF | 124 | | Bonifaci2013 [4] | task set | A | DAG | G | FP | EDF, DM | 125 | | Li2013 [5] | task set | I | DAG | G | FP | EDF | 126 | | Qamhieh2013 [6] | task set | C | DAG | G | FP | EDF | 127 | | Baruah2014 [7] | task set | C | DAG | G | FP | EDF | 128 | | Melani2015 [1] | task set | C | DAG, C-DAG | G | FP | EDF, FTP | 129 | | Serrano2016 [8] | task set | C | DAG | G | LP | FTP | 130 | | Fonseca2016 [14] | task set | C | DAG | P | FP | FTP | 131 | | Pathan2017 [9] | task set | C | DAG | G | FP | DM | 132 | | Fonseca2017 [10] | task set | C | DAG | G | FP | DM | 133 | | Casini2018 [15] | task set | C | DAG | P | LP | FTP | 134 | | Han2019 [11] | single task | C | H-DAG | G | \- | \- | 135 | | He2019 [12] | task set | C | DAG | G | FP | EDF, FTP | 136 | | Fonseca2019 [13] | task set | C, A | DAG | G | FP | EDF, FTP | 137 | | Nasri2019 [16] |task set | C | DAG | G | LP | EDF | 138 | | Zahaf2020 [17] |task set | C | HC-DAG | P | FP, FNP | EDF | 139 | 140 | * [1] Alessandra Melani et al. “Response-time analysis of conditional dag tasks in multiprocessor systems”. (ECRTS 2015) 141 | * [2] https://retis.sssup.it/~d.casini/resources/DAG_Generator/cptasks.zip 142 | * [3] Baruah et al. "A generalized parallel task model for recurrent real-time processes" (RTSS 2012) 143 | * [4] Bonifaci et al., "Feasibility Analysis in the Sporadic DAG Task Model" (ECRTS 2013) 144 | * [5] Li et al. "Outstanding Paper Award: Analysis of Global EDF for Parallel Tasks" (ECRTS 2013) 145 | * [6] Qamhieh et al. "Global EDF scheduling of directed acyclic graphs on multiprocessor systems", (RTNS 2013) 146 | * [7] Baruah et al. "Improved Multiprocessor Global Schedulability Analysis of Sporadic DAG Task Systems" (ECRTS 2014) 147 | * [8] Maria A Serrano et al. “Response-time analysis of DAG tasks under fixed priority scheduling with limited preemptions” (DATE 2016) 148 | * [9] Risat Pathan et al. “Scheduling parallel real-time recurrent tasks on multicore platforms”. (IEEE Transactions on Parallel and Distributed Systems 2017) 149 | * [10] Fonseca et al. “Improved response time analysis of sporadic dag tasks for global fp scheduling”. (RTNS 2017) 150 | * [11] Meiling Han et al. “Response time bounds for typed dag parallel tasks on heterogeneous multi-cores”. (IEEE Transactions on Parallel and Distributed Systems 2019) 151 | * [12] Qingqiang He et al. “Intra-task priority assignment in real-time scheduling of dag tasks on multi-cores”. (IEEE Transactions on Parallel and Distributed Systems 2019) 152 | * [13] Fonseca et al. “Schedulability Analysis of DAG Tasks with Arbitrary Deadlines under Global Fixed-Priority Scheduling”. (Real-Time Systems 2019) 153 | * [14] Fonseca et al. “Response time analysis of sporadic dag tasks under partitioned scheduling”. (SIES 2016) 154 | * [15] Daniel Casini et al. “Partitioned fixed-priority scheduling of parallel tasks without preemptions”. (RTSS 2018). 155 | * [16] Mitra Nasri, et al. “Response-time analysis of limited-preemptive parallel DAG tasks under global scheduling”. (ECRTS 2019) 156 | * [17] Houssam-Eddine Zahaf et al. “The HPC-DAG Task Model for Heterogeneous Real-Time Systems”. (IEEE Transactions on Computers 2020) 157 | 158 | -------------------------------------------------------------------------------- /data/P_n_task_DAG_FTP_C_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 0 20 | aType : 0 21 | sType : 1 22 | wType : 1 23 | DAGType : 0 24 | -------------------------------------------------------------------------------- /data/P_n_task_DAG_FTP_I_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | tasksetPerVarFactor : 100 17 | nTasks: 10000 18 | gType : 1 19 | dtype : 1 20 | aType : 0 21 | sType : 1 22 | wType : 1 23 | DAGType : 0 24 | -------------------------------------------------------------------------------- /data/SOTA_n_task_DAG_FTP_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 7 14 | stepU : 0.25 15 | m : 8 16 | tasksetPerVarFactor : 100 17 | nTasks: 10000 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | sType : 3 22 | wType : 1 23 | DAGType : 0 24 | -------------------------------------------------------------------------------- /data/n_task_CDAG_FTP_C_varyingN.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | Utot : 2.5 11 | saveRate: 25 12 | Nmin: 11 13 | Nmax: 50 14 | stepN : 1 15 | m : 4 16 | tasksetPerVarFactor : 1 17 | gType : 0 18 | dtype : 0 19 | aType : 0 20 | wType : 1 21 | DAGType : 1 22 | -------------------------------------------------------------------------------- /data/n_task_DAG_EDF_C_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 0 20 | aType : 1 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/n_task_DAG_EDF_C_varyingN.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | Utot : 2.5 11 | saveRate: 25 12 | Nmin: 11 13 | Nmax: 50 14 | stepN : 1 15 | m : 4 16 | tasksetPerVarFactor : 1 17 | gType : 0 18 | dtype : 0 19 | aType : 1 20 | wType : 1 21 | DAGType : 0 22 | -------------------------------------------------------------------------------- /data/n_task_DAG_EDF_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 0 20 | aType : 1 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/n_task_DAG_EDF_I_varyingN.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | Utot : 2.5 11 | saveRate: 25 12 | Nmin: 11 13 | Nmax: 50 14 | stepN : 1 15 | m : 4 16 | tasksetPerVarFactor : 1 17 | gType : 0 18 | dtype : 1 19 | aType : 1 20 | wType : 1 21 | DAGType : 0 22 | -------------------------------------------------------------------------------- /data/n_task_DAG_FTP_A_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 2 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/n_task_DAG_FTP_A_varyingN.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | Utot : 2.5 11 | saveRate: 25 12 | Nmin: 11 13 | Nmax: 50 14 | stepN : 1 15 | m : 4 16 | tasksetPerVarFactor : 1 17 | gType : 0 18 | dtype : 2 19 | aType : 0 20 | wType : 1 21 | DAGType : 0 22 | -------------------------------------------------------------------------------- /data/n_task_DAG_FTP_A_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 2 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/n_task_DAG_FTP_C_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 0 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/n_task_DAG_FTP_C_varyingN.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | Utot : 2.5 11 | saveRate: 25 12 | Nmin: 11 13 | Nmax: 50 14 | stepN : 1 15 | m : 4 16 | tasksetPerVarFactor : 1 17 | gType : 0 18 | dtype : 0 19 | aType : 0 20 | wType : 1 21 | DAGType : 0 22 | -------------------------------------------------------------------------------- /data/n_task_DAG_FTP_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | tasksetPerVarFactor : 500 17 | nTasks: 10000 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/single_task_CDAG_FTP_I_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 1 20 | aType : 0 21 | wType : 0 22 | DAGType : 1 23 | -------------------------------------------------------------------------------- /data/single_task_DAG_EDF_A_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 2 20 | aType : 1 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/single_task_DAG_EDF_A_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 2 20 | aType : 1 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/single_task_DAG_EDF_C_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 0 20 | aType : 1 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/single_task_DAG_EDF_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 0 20 | aType : 1 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/single_task_DAG_FTP_A_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 2 20 | aType : 0 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/single_task_DAG_FTP_A_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 2 20 | aType : 0 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/single_task_DAG_FTP_C_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 0 20 | aType : 0 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/single_task_DAG_FTP_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.1 9 | probSCond : 0 10 | beta: 0.1 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/multi/P_n_task_DAG_FTP_I_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 1 20 | aType : 0 21 | sType : 1 22 | wType : 1 23 | DAGType : 0 24 | -------------------------------------------------------------------------------- /data/thesis/multi/P_n_task_DAG_FTP_I_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | tasksetPerVarFactor : 500 17 | nTasks: 10000 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | sType : 1 22 | wType : 1 23 | DAGType : 0 24 | -------------------------------------------------------------------------------- /data/thesis/multi/SOTA_n_task_DAG_FTP_C_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | tasksetPerVarFactor : 500 17 | nTasks: 10000 18 | gType : 2 19 | dtype : 0 20 | aType : 0 21 | sType : 3 22 | wType : 1 23 | DAGType : 0 24 | -------------------------------------------------------------------------------- /data/thesis/multi/SOTA_n_task_DAG_FTP_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | tasksetPerVarFactor : 500 17 | nTasks: 10000 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | sType : 3 22 | wType : 1 23 | DAGType : 0 24 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_CDAG_FTP_C_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 0 20 | aType : 0 21 | wType : 1 22 | DAGType : 1 23 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_CDAG_FTP_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | wType : 1 22 | DAGType : 1 23 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_DAG_EDF_I_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 1 20 | aType : 1 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_DAG_EDF_I_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 1 20 | aType : 1 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_DAG_FTP_A_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 2 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_DAG_FTP_A_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 2 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_DAG_FTP_C_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 0 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_DAG_FTP_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | tasksetPerVarFactor : 500 17 | nTasks: 10000 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_DAG_FTP_I_varyingM.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Utot: 2 13 | mMin: 2 14 | mMax: 30 15 | stepM : 1 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 2 19 | dtype : 1 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/multi/n_task_DAG_FTP_I_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | tasksetPerVarFactor : 500 17 | nTasks: 10000 18 | gType : 1 19 | dtype : 1 20 | aType : 0 21 | wType : 1 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/single/P_single_task_DAG_FTP_I_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | tasksetPerVarFactor : 500 17 | nTasks: 1 18 | gType : 1 19 | dtype : 1 20 | aType : 0 21 | sType : 1 22 | wType : 1 23 | DAGType : 0 24 | -------------------------------------------------------------------------------- /data/thesis/single/SOTA_single_task_DAG_FTP_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | tasksetPerVarFactor : 500 17 | nTasks: 1 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | sType : 3 22 | wType : 1 23 | DAGType : 0 24 | -------------------------------------------------------------------------------- /data/thesis/single/single_task_CDAG_FTP_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | wType : 0 22 | DAGType : 1 23 | -------------------------------------------------------------------------------- /data/thesis/single/single_task_DAG_EDF_I_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 1 20 | aType : 1 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/single/single_task_DAG_FTP_A_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 2 20 | aType : 0 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/single/single_task_DAG_FTP_C_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 0 20 | aType : 0 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /data/thesis/single/single_task_DAG_FTP_I_varyingU.yml: -------------------------------------------------------------------------------- 1 | maxParBranches: 6 2 | recDepth: 2 3 | pCond : 0 4 | pPar: 0.8 5 | pTerm : 0.2 6 | Cmin: 1 7 | Cmax: 100 8 | addProb : 0.2 9 | probSCond : 0 10 | beta: 0.28 11 | saveRate: 25 12 | Umin: 0 13 | Umax: 8 14 | stepU : 0.25 15 | m : 8 16 | nTasks: 10000 17 | tasksetPerVarFactor : 500 18 | gType : 1 19 | dtype : 1 20 | aType : 0 21 | wType : 0 22 | DAGType : 0 23 | -------------------------------------------------------------------------------- /demo/dot_files.txt: -------------------------------------------------------------------------------- 1 | /home/micaela/repos/DAG-scheduling/demo/test0.dot -------------------------------------------------------------------------------- /demo/eval_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd build 4 | target="../data/thesis/single" 5 | for f in "$target"/* 6 | do 7 | # echo ./eval "$target"/$(basename $f) 0 8 | ./eval "$target"/$(basename $f) 0 9 | # break; 10 | 11 | done -------------------------------------------------------------------------------- /demo/evaluate.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/evaluate.h" 2 | int main(int argc, char *argv[]) { 3 | 4 | if(REPRODUCIBLE) srand (1); 5 | else srand (time(NULL)); 6 | 7 | std::string gp_file = "../data/n_task_DAG_EDF_C_varyingU.yml"; 8 | if(argc > 1) 9 | gp_file = argv[1]; 10 | bool show_plots = true; 11 | if(argc > 2) 12 | show_plots = atoi(argv[2]); 13 | 14 | std::string o_file; 15 | removePathAndExtension(gp_file, o_file); 16 | 17 | system("mkdir -p res"); 18 | dagSched::evaluate(gp_file, "res/" + o_file, show_plots); 19 | return 0; 20 | } -------------------------------------------------------------------------------- /demo/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dagSched/DAGTask.h" 3 | #include "dagSched/Taskset.h" 4 | #include "dagSched/tests.h" 5 | #include "dagSched/plot_utils.h" 6 | 7 | #include 8 | 9 | int main(int argc, char **argv){ 10 | 11 | if(REPRODUCIBLE) srand (1); 12 | else srand (time(NULL)); 13 | 14 | bool random_creation = true; 15 | if(argc > 1) 16 | random_creation = atoi(argv[1]); 17 | 18 | std::string taskset_filename = "../demo/taskset.yaml"; 19 | if(argc > 2) 20 | taskset_filename = argv[2]; 21 | 22 | 23 | int n_proc = 4; 24 | std::vector typed_proc = {4,4}; 25 | dagSched::Taskset taskset; 26 | if(random_creation){ 27 | int n_tasks = 4; 28 | float U_tot = 1; 29 | dagSched::GeneratorParams gp; 30 | gp.configureParams(dagSched::GenerationType_t::VARYING_N); 31 | 32 | taskset.generate_taskset_Melani(n_tasks, U_tot, n_proc, gp); 33 | } 34 | else{ 35 | size_t ext = taskset_filename.find("yaml"); 36 | if( ext != std::string::npos) 37 | taskset.readTasksetFromYaml(taskset_filename); 38 | else 39 | taskset.readTasksetFromDOT(taskset_filename); 40 | } 41 | 42 | std::cout<<"Assignment: "<< dagSched::WorstFitProcessorsAssignment(taskset, n_proc)< test"+std::to_string(i)+".png"; 51 | system(dot_command.c_str()); 52 | } 53 | std::cout<<"Taskset utilization: "< taskset.tasks[i].getPeriod()){ 77 | constrained_taskset = false; 78 | implicit_taskset = false; 79 | } 80 | 81 | } 82 | 83 | //taskset tests 84 | std::cout<<"Taskset tests: \n"; 85 | 86 | 87 | //arbitrary 88 | std::cout<< "\tBonifaci 2013 arbitrary (GP-FP-EDF): " < 2; 16 | 0 -> 8; 17 | 2 -> 4; 18 | 2 -> 5; 19 | 2 -> 6; 20 | 2 -> 7; 21 | 3 -> 1; 22 | 4 -> 3; 23 | 5 -> 3; 24 | 6 -> 3; 25 | 7 -> 3; 26 | 8 -> 10; 27 | 8 -> 11; 28 | 9 -> 1; 29 | 10 -> 9; 30 | 11 -> 9; 31 | } 32 | -------------------------------------------------------------------------------- /img/dot_format.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mive93/DAG-scheduling/7ccd59d52929c90ff13ad675b45b5c72ff6215df/img/dot_format.png -------------------------------------------------------------------------------- /img/sched_times.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mive93/DAG-scheduling/7ccd59d52929c90ff13ad675b45b5c72ff6215df/img/sched_times.png -------------------------------------------------------------------------------- /include/dagSched/DAGTask.h: -------------------------------------------------------------------------------- 1 | #ifndef DAGTASK_H 2 | #define DAGTASK_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include "dagSched/SubTask.h" 15 | #include "dagSched/utils.h" 16 | #include "dagSched/GeneratorParams.h" 17 | 18 | namespace dagSched{ 19 | 20 | enum creationStates {CONDITIONAL_T=0, PARALLEL_T=1, TERMINAL_T=2}; 21 | 22 | class DAGTask{ 23 | 24 | std::vector V; 25 | 26 | float t = 0; // period 27 | float d = 0; // deadline 28 | float L = 0; // longest chain 29 | float vol = 0; // volume 30 | float wcw = 0; // worst case workload (= to volume if no conditional branch exist) 31 | float delta = 0; // density 32 | float u = 0; // utilization 33 | 34 | std::vector ordIDs; // ids in topological order 35 | std::map typedVol; // volume for typed DAG [type of core, volume] 36 | std::map pVol; // volume for partitioned DAG [core id, volume] 37 | 38 | public: 39 | 40 | float R = 0; // response time 41 | 42 | DAGTask(){}; 43 | DAGTask(const float T, const float D): t(T), d(D) {}; 44 | ~DAGTask(){}; 45 | 46 | //input - output 47 | void readTaskFromYamlNode(YAML::Node tasks, const int i); 48 | void readTaskFromDOT(const std::string &filename); 49 | void saveAsDot(const std::string &filename); 50 | friend std::ostream& operator<<(std::ostream& os, const DAGTask& t); 51 | 52 | //operation on DAG 53 | void cloneVertices(const std::vector& to_clone_V); 54 | void destroyVerices(); 55 | void isSuccessor(const SubTask* v, const SubTask *w, bool &is_succ) const; 56 | bool allPrecAdded(std::vector pred, std::vector ids); 57 | void topologicalSort(); 58 | bool checkIndexAndIdsAreEqual(); 59 | void computeAccWorkload(); 60 | void computeLength(); 61 | void computeVolume(); 62 | void computeTypedVolume(); 63 | void computepVolume(); 64 | void computeWorstCaseWorkload(); 65 | void computeUtilization(); 66 | void computeDensity(); 67 | std::vector> computeAllPathsSingleSource(std::vector& path, std::vector>& all_paths) const; 68 | std::vector> computeAllPaths() const; 69 | 70 | // EST, EFT, LST, LFT 71 | void localDeadline(SubTask *task, const int i); 72 | void localOffset(SubTask *task, const int i); 73 | void computeLocalOffsets(); 74 | void computeLocalDeadlines(); 75 | void computeEFTs(); 76 | void computeLSTs(); 77 | 78 | std::vector getSubTaskAncestors(const int i) const; 79 | std::vector getSubTaskDescendants(const int i) const; 80 | void transitiveReduction(); 81 | 82 | //getters 83 | float getLength() const {return L;}; 84 | float getVolume() const {return vol;}; 85 | std::map getTypedVolume() const {return typedVol;}; 86 | std::map getpVolume() const {return pVol;}; 87 | float getWorstCaseWorkload() const {return wcw;}; 88 | float getWCW() const {return wcw;}; 89 | float getPeriod() const {return t;}; 90 | float getDeadline() const {return d;}; 91 | float getUtilization() const {return u;}; 92 | float getDensity() const {return delta;}; 93 | std::vector getTopologicalOrder() const {return ordIDs;}; 94 | std::vector getVertices() const {return V;}; 95 | 96 | //setters 97 | void setVertices(std::vector given_V){ V.clear(); V = given_V; } 98 | void setDeadline(const float deadline) { d = deadline; } 99 | void setPeriod(const float period) { t = period; } 100 | 101 | //Melani generation methods 102 | void assignWCET(const int minC, const int maxC); 103 | void expandTaskSeriesParallel(SubTask* source,SubTask* sink,const int depth,const int numBranches, const bool ifCond, GeneratorParams& gp); 104 | void makeItDag(float prob); 105 | void assignSchedParametersUUniFast(const float U); 106 | void assignSchedParameters(const float beta); 107 | void assignFixedSchedParameters(const float period, const float deadline); 108 | 109 | }; 110 | 111 | 112 | bool compareDAGsDeadlineInc(const DAGTask& a, const DAGTask& b); 113 | bool compareDAGsDeadlineDec(const DAGTask& a, const DAGTask& b); 114 | bool compareDAGsPeriodInc(const DAGTask& a, const DAGTask& b); 115 | bool compareDAGsPeriodDec(const DAGTask& a, const DAGTask& b); 116 | bool compareDAGsUtilInc(const DAGTask& a, const DAGTask& b); 117 | bool compareDAGsUtilDec(const DAGTask& a, const DAGTask& b); 118 | 119 | } 120 | 121 | #endif /* DAGTASK_H */ -------------------------------------------------------------------------------- /include/dagSched/GeneratorParams.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef GENERATORPARAMS_H 3 | #define GENERATORPARAMS_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "dagSched/utils.h" 12 | 13 | namespace dagSched{ 14 | 15 | enum GenerationType_t {VARYING_N, VARYING_U, VARYING_M}; 16 | enum DeadlinesType_t {CONSTRAINED, IMPLICIT, ARBITRARY}; 17 | enum SchedulingType_t {GLOBAL, PARTITIONED, FEDERATED, SOTA}; 18 | enum AlgorithmType_t {FTP, EDF}; 19 | enum workloadType_t {SINGLE_DAG, TASKSET}; 20 | enum DAGType_t {DAG, CDAG, TDAG}; 21 | 22 | class GeneratorParams{ 23 | 24 | public: 25 | 26 | // Hyperparameters for the generation of DAG and conditional DAGs proposed by Melani et al. (MelaniGen) 27 | int maxCondBranches = 2; // max conditional branches allowed 28 | int maxParBranches = 6; // max parallel branches allowed 29 | int recDepth = 2; // maximum recursion depth for the generation of the task graphs 30 | 31 | float pCond = 0; // probability of generating a conditional branch 32 | float pPar = 0.2; // probability of generating a parallel branch 33 | float pTerm = 0.8; // probability of generating a terminal vertex 34 | float Cmin = 1; // minimum WCET for subtasks 35 | float Cmax = 100; // maximum WCET for subtasks 36 | float addProb = 0.1; // probability to add an edge between 2 nodes, if possible 37 | float probSCond = 0.5; // probability that the source is conditional 38 | float Utot = 1; 39 | float beta = 0.1; 40 | 41 | int saveRate = 25; 42 | 43 | float Umin = 0; 44 | float Umax = 8; 45 | float stepU = 0.25; 46 | int m = 8; 47 | 48 | int nMin = 11; 49 | int nMax = 20; 50 | int nTasks = 0; 51 | int stepN = 1; 52 | 53 | int mMin = 2; 54 | int mMax = 30; 55 | int stepM = 1; 56 | 57 | int tasksetPerVarFactor = 1; 58 | int nTasksets = 1; 59 | 60 | int diffProcTypes = 1; 61 | int minProcPerType = 1; 62 | int maxProcPerType = 1; 63 | 64 | std::vector typedProc; 65 | 66 | GenerationType_t gType = GenerationType_t::VARYING_N; 67 | DeadlinesType_t dtype = DeadlinesType_t::CONSTRAINED; 68 | SchedulingType_t sType = SchedulingType_t::GLOBAL; 69 | AlgorithmType_t aType = AlgorithmType_t::FTP; 70 | workloadType_t wType = workloadType_t::TASKSET; 71 | DAGType_t DAGType = DAGType_t::DAG; 72 | 73 | //distribution to add branches 74 | std::discrete_distribution dist; 75 | std::vector weights; 76 | std::mt19937 gen; 77 | 78 | void configureParams(GenerationType_t gt){ 79 | gType = gt; 80 | 81 | weights.push_back(pCond); 82 | weights.push_back(pPar); 83 | weights.push_back(pTerm); 84 | dist.param(std::discrete_distribution ::param_type(std::begin(weights), std::end(weights))); 85 | 86 | switch (gt){ 87 | case VARYING_N: 88 | nTasksets = tasksetPerVarFactor * (nMax - nMin + 1); 89 | break; 90 | case VARYING_U: 91 | nTasksets = tasksetPerVarFactor * ((Umax - Umin) / stepU); 92 | break; 93 | case VARYING_M: 94 | mMin = std::floor(Utot); 95 | nTasksets = tasksetPerVarFactor * (mMax - mMin + 1); 96 | break; 97 | } 98 | 99 | if(DAGType != DAGType_t::CDAG){ 100 | pCond = 0; 101 | probSCond = 0; 102 | } 103 | 104 | if(DAGType != DAGType_t::TDAG){ 105 | typedProc.resize(diffProcTypes); 106 | for(int p=0; p(); 121 | if(config["maxParBranches"]) maxParBranches = config["maxParBranches"].as(); 122 | if(config["recDepth"]) recDepth = config["recDepth"].as(); 123 | if(config["pCond"]) pCond = config["pCond"].as(); 124 | if(config["pPar"]) pPar = config["pPar"].as(); 125 | if(config["pTerm"]) pTerm = config["pTerm"].as(); 126 | if(config["Cmin"]) Cmin = config["Cmin"].as(); 127 | if(config["Cmax"]) Cmax = config["Cmax"].as(); 128 | if(config["addProb"]) addProb = config["addProb"].as(); 129 | if(config["probSCond"]) probSCond = config["probSCond"].as(); 130 | if(config["Utot"]) Utot = config["Utot"].as(); 131 | if(config["beta"]) beta = config["beta"].as(); 132 | if(config["saveRate"]) saveRate = config["saveRate"].as(); 133 | if(config["Umin"]) Umin = config["Umin"].as(); 134 | if(config["Umax"]) Umax = config["Umax"].as(); 135 | if(config["stepU"]) stepU = config["stepU"].as(); 136 | if(config["m"]) m = config["m"].as(); 137 | if(config["nMin"]) nMin = config["nMin"].as(); 138 | if(config["nMax"]) nMax = config["nMax"].as(); 139 | if(config["nTasks"]) nTasks = config["nTasks"].as(); 140 | if(config["stepN"]) stepN = config["stepN"].as(); 141 | if(config["mMin"]) mMin = config["mMin"].as(); 142 | if(config["mMax"]) mMax = config["mMax"].as(); 143 | if(config["stepM"]) stepM = config["stepM"].as(); 144 | if(config["tasksetPerVarFactor"]) tasksetPerVarFactor = config["tasksetPerVarFactor"].as(); 145 | if(config["nTasksets"]) nTasksets = config["nTasksets"].as(); 146 | if(config["diffProcTypes"]) diffProcTypes = config["diffProcTypes"].as(); 147 | if(config["minProcPerType"]) minProcPerType = config["minProcPerType"].as(); 148 | if(config["maxProcPerType"]) maxProcPerType = config["maxProcPerType"].as(); 149 | if(config["gType"]) gType = (GenerationType_t) config["gType"].as(); 150 | if(config["dtype"]) dtype = (DeadlinesType_t) config["dtype"].as(); 151 | if(config["sType"]) sType = (SchedulingType_t) config["sType"].as(); 152 | if(config["aType"]) aType = (AlgorithmType_t) config["aType"].as(); 153 | if(config["wType"]) wType = (workloadType_t) config["wType"].as(); 154 | if(config["DAGType"]) DAGType = (DAGType_t) config["DAGType"].as(); 155 | } 156 | 157 | void print(){ 158 | std::cout<<"maxCondBranches: "< 5 | #include "dagSched/utils.h" 6 | #include "dagSched/DAGTask.h" 7 | 8 | namespace dagSched{ 9 | 10 | enum NodeType_t{ S, P, L}; 11 | 12 | struct SPNode{ 13 | NodeType_t type; 14 | int id = -1; // id in the tree 15 | int V_id = -1; // corresponding id in the DAG 16 | SPNode *left = nullptr; // left son 17 | SPNode *right = nullptr; // right son 18 | }; 19 | 20 | struct STempNode{ 21 | int left = -1; 22 | int right = -1; 23 | int right_ordids = -1; // topological order in the DAG of right 24 | int left_ordids = -1; // topological order in the DAG of left 25 | bool used = false; 26 | bool visited = false; 27 | }; 28 | 29 | bool compareSTempNode(const STempNode& a, const STempNode& b); 30 | 31 | class SPTree{ 32 | 33 | SPNode *root = nullptr; 34 | int index = 0; 35 | 36 | // output ----------------------------------------------------------------- 37 | void printDotTree(SPNode *node, std::ostream& os, bool print_node =true, bool print_edges=false); 38 | void saveAsDot(SPNode *node,const std::string filename); 39 | 40 | // node creation and deletion --------------------------------------------- 41 | SPNode* createNode(const NodeType_t type, const int V_id=-1); 42 | SPNode* createP(SPNode* node, const int id_right, const int id_left); 43 | SPNode * freeNode(SPNode *&node); 44 | 45 | //searches in the tree ---------------------------------------------------- 46 | 47 | /* Find the node corresponding to VId in a tree */ 48 | void findNode(SPNode* start_node, const int VId, SPNode *& found_node); 49 | /* Find the dad of a node */ 50 | void findDad(SPNode* start_node, const SPNode* son, SPNode *& dad) const; 51 | /* Check if a node is son of another*/ 52 | void isSon(const SPNode* dad, const SPNode* son, bool& is_son); 53 | /* Get all VIds belonging to a tree */ 54 | void getTreeVIDs(SPNode * node, std::vector>& V_ids); 55 | 56 | //SP decomposition tree conversion ---------------------------------------- 57 | 58 | /* Computes join nodes for each vertex. 59 | @param dag: dag G (V, E)to work on 60 | @return a vector with length = |V|, and for each vertex a list of corresponding join vertices 61 | */ 62 | std::vector> computeJoinsForVertices(const DAGTask& dag); 63 | 64 | /* Create initial sequential couple, for each vertex in the dag, 65 | * following topological order 66 | * */ 67 | std::vector computeInitialS(const DAGTask& dag); 68 | 69 | /* This function consider all the S couple. If it finds more that one 70 | * having the same left VId, then it merges them in a parallel construct. 71 | * However, if there are many, they are associated wrt their join nodes. 72 | * */ 73 | std::vector computePSubtrees(const std::vector>& J_nodes, std::vector& S); 74 | 75 | std::vector mergeSubtrees(std::vector subtrees); 76 | 77 | /* Finds the common root, among the subtrees, of all the S with same right */ 78 | SPNode * computeCommonRoot(std::vector subtrees, std::vector S, std::vector S_idx, int& subtree_idx); 79 | 80 | /* Insert all the remaining S (once the Ps are already computed and merged)*/ 81 | void insertS(std::vector&subtrees, std::vector& initial_S); 82 | 83 | public: 84 | 85 | SPTree(){} 86 | ~SPTree(){ 87 | // freeNode(root); //FIXME 88 | } 89 | 90 | /* Convert a NFJ DAG into a decomposition Sequential-Parallel binary tree*/ 91 | void convertNFJDAGtoSPTree(const DAGTask& dag, const int dag_id); 92 | 93 | //Fonseca method (2017 & 2019) -------------------------------------------- 94 | std::vector> computeWDUCO(const DAGTask& dag, const int dag_id); 95 | /* Equation 8 Fonseca 2017*/ 96 | std::vector computeP( SPNode * node, const std::vector& V); 97 | }; 98 | 99 | } 100 | 101 | 102 | #endif /* SPTREE_H */ -------------------------------------------------------------------------------- /include/dagSched/SubTask.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBTASK_H 2 | #define SUBTASK_H 3 | 4 | #include 5 | #include "dagSched/utils.h" 6 | 7 | namespace dagSched{ 8 | 9 | enum subTaskMode {NORMAL_T, C_INTERN_T, C_SOURCE_T, C_SINK_T}; 10 | 11 | class SubTask{ 12 | 13 | public: 14 | 15 | int id = 0; // sub-task id 16 | int depth = 0; // depth in the graph 17 | int width = 0; // width in the graph 18 | int gamma = 0; // type of core 19 | int core = 0; // id of assigned core 20 | int prio = 0; // priority of the subtask 21 | 22 | float c = 0; // WCET 23 | float accWork = 0; // accumulated workload 24 | float r = 0; // response time of the subtask 25 | float localO = -1; // local offset - Earliest Starting Time 26 | float localD = -1; // local deadline - Latest Finishing Time 27 | float EFT = -1; // Earliest Finishing Time 28 | float LST = -1; // Latest Starting Time 29 | 30 | subTaskMode mode = NORMAL_T; // type of node 31 | 32 | std::vector succ; // successors 33 | std::vector pred; // predecessors 34 | 35 | std::vector getCondPred(); 36 | 37 | void localOffset(); 38 | void EasliestFinishingTime(); 39 | void localDeadline(const float task_deadline); 40 | void LatestStartingTime(); 41 | }; 42 | 43 | } 44 | 45 | #endif /* SUBTASK_H */ -------------------------------------------------------------------------------- /include/dagSched/Taskset.h: -------------------------------------------------------------------------------- 1 | #ifndef TASKSET_H 2 | #define TASKSET_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "dagSched/DAGTask.h" 8 | 9 | namespace dagSched{ 10 | 11 | class Taskset{ 12 | 13 | float U = 0; // utilization 14 | float maxDelta = 0; // maximum density 15 | long int HP = 1; // hyper-period 16 | 17 | public: 18 | 19 | std::vector tasks; 20 | 21 | Taskset(){}; 22 | ~Taskset(){}; 23 | 24 | //getters 25 | float getUtilization() const {return U;} 26 | int getHyperPeriod() const {return HP;} 27 | float getMaxDensity() const {return maxDelta;} 28 | 29 | //compute on taskset 30 | void computeUtilization(); 31 | void computeHyperPeriod(); 32 | void computeMaxDensity(); 33 | 34 | //IO 35 | void readTasksetFromYaml(const std::string& params_path); 36 | void readTasksetFromDOT(const std::string& dot_file_path); 37 | void print() const; 38 | 39 | //generate taskset 40 | float UUniFast_Upart(float& sum_U, const int i, const int n_tasks, const DAGTask& t ); 41 | void generate_taskset_Melani(int n_tasks, const float U_tot, const int n_proc, GeneratorParams& gp); 42 | }; 43 | 44 | } 45 | 46 | #endif /* TASKSET_H */ -------------------------------------------------------------------------------- /include/dagSched/evaluate.h: -------------------------------------------------------------------------------- 1 | #ifndef EVALUATE_H 2 | #define EVALUATE_H 3 | 4 | #include "dagSched/utils.h" 5 | #include "dagSched/GeneratorParams.h" 6 | #include "dagSched/Taskset.h" 7 | #include "dagSched/tests.h" 8 | #include "dagSched/plot_utils.h" 9 | 10 | namespace dagSched{ 11 | 12 | void evaluate(const std::string& genparams_path, const std::string& output_fig_path, const bool show_plots){ 13 | GeneratorParams gp; 14 | gp.readFromYaml(genparams_path); 15 | gp.configureParams(gp.gType); 16 | 17 | float U_curr = gp.Utot; 18 | if(gp.gType == GenerationType_t::VARYING_U) 19 | U_curr = gp.Umin; 20 | 21 | int m = gp.m; 22 | if(gp.gType == GenerationType_t::VARYING_M) 23 | m = gp.mMin - 1; 24 | 25 | int n_tasks = gp.nTasks; 26 | if(gp.gType == GenerationType_t::VARYING_N) 27 | n_tasks = gp.nMin - 1; 28 | 29 | std::map> sched_res; 30 | std::map> time_res; 31 | std::vector x; 32 | 33 | int test_idx = -1; 34 | SimpleTimer timer; 35 | 36 | int min_V_all = 100; 37 | int max_V_all = 0; 38 | 39 | for(int i=0; i max_v_size) 62 | max_v_size = task_set.tasks[ii].getVertices().size(); 63 | 64 | if (max_v_size > max_V_all) max_V_all = max_v_size; 65 | if (max_v_size < min_V_all) min_V_all = max_v_size; 66 | 67 | std::cout<<"taskset: "< test"+std::to_string(i)+".png"; 72 | // system(dot_command.c_str()); 73 | // } 74 | 75 | if(gp.sType == SchedulingType_t::GLOBAL){ 76 | switch (gp.dtype){ 77 | case DeadlinesType_t::CONSTRAINED: case DeadlinesType_t::IMPLICIT: 78 | if(gp.aType == AlgorithmType_t::EDF && gp.DAGType == DAGType_t::DAG ){ 79 | if(i % gp.tasksetPerVarFactor == 0){ 80 | sched_res["Qamhieh2013"].push_back(0); 81 | // sched_res["Baruah2014"].push_back(0); 82 | sched_res["Melani2015"].push_back(0); 83 | } 84 | 85 | timer.tic(); 86 | sched_res["Qamhieh2013"][test_idx] += GP_FP_EDF_Qamhieh2013_C(task_set, m); 87 | time_res["Qamhieh2013"].push_back(timer.toc()); 88 | 89 | // timer.tic(); 90 | // sched_res["Baruah2014"][test_idx] += GP_FP_EDF_Baruah2014_C(task_set, m); 91 | // time_res["Baruah2014"].push_back(timer.toc()); 92 | 93 | timer.tic(); 94 | sched_res["Melani2015"][test_idx] += GP_FP_EDF_Melani2015_C(task_set, m); 95 | time_res["Melani2015"].push_back(timer.toc()); 96 | 97 | if(gp.wType == workloadType_t::SINGLE_DAG){ 98 | if(i % gp.tasksetPerVarFactor == 0) 99 | sched_res["Baruah2012"].push_back(0); 100 | 101 | timer.tic(); 102 | sched_res["Baruah2012"][test_idx] += GP_FP_EDF_Baruah2012_C(task_set.tasks[0], m); 103 | time_res["Baruah2012"].push_back(timer.toc()); 104 | } 105 | 106 | if(gp.dtype != DeadlinesType_t::CONSTRAINED){ 107 | if(i % gp.tasksetPerVarFactor == 0) 108 | sched_res["Li2013"].push_back(0); 109 | 110 | timer.tic(); 111 | sched_res["Li2013"][test_idx] += GP_FP_EDF_Li2013_I(task_set, m); 112 | time_res["Li2013"].push_back(timer.toc()); 113 | } 114 | } 115 | else if(gp.aType == AlgorithmType_t::FTP && gp.DAGType ==DAGType_t::DAG){ 116 | if(i % gp.tasksetPerVarFactor == 0){ 117 | sched_res["Bonifaci2013"].push_back(0); 118 | sched_res["Melani2015"].push_back(0); 119 | sched_res["Serrano2016"].push_back(0); 120 | sched_res["Pathan2017"].push_back(0); 121 | sched_res["Fonseca2017"].push_back(0); 122 | sched_res["Fonseca2019"].push_back(0); 123 | sched_res["Nasri2019"].push_back(0); 124 | sched_res["He2019"].push_back(0); 125 | } 126 | 127 | timer.tic(); 128 | sched_res["Bonifaci2013"][test_idx] += GP_FP_DM_Bonifaci2013_C(task_set, m); 129 | time_res["Bon2013"].push_back(timer.toc()); 130 | 131 | timer.tic(); 132 | sched_res["Melani2015"][test_idx] += GP_FP_FTP_Melani2015_C(task_set, m); 133 | time_res["Mel2015"].push_back(timer.toc()); 134 | 135 | timer.tic(); 136 | sched_res["Serrano2016"][test_idx] += GP_LP_FTP_Serrano16_C(task_set, m); 137 | time_res["Ser2016"].push_back(timer.toc()); 138 | 139 | timer.tic(); 140 | sched_res["Pathan2017"][test_idx] += GP_FP_DM_Pathan2017_C(task_set, m); 141 | time_res["Pat2017"].push_back(timer.toc()); 142 | 143 | timer.tic(); 144 | sched_res["Fonseca2017"][test_idx] += GP_FP_FTP_Fonseca2017_C(task_set, m); 145 | time_res["Fon2017"].push_back(timer.toc()); 146 | 147 | timer.tic(); 148 | sched_res["Fonseca2019"][test_idx] += GP_FP_FTP_Fonseca2019(task_set, m); 149 | time_res["Fon2019"].push_back(timer.toc()); 150 | 151 | timer.tic(); 152 | sched_res["Nasri2019"][test_idx] += G_LP_FTP_Nasri2019_C(task_set, m); 153 | time_res["Nas2019"].push_back(timer.toc()); 154 | 155 | timer.tic(); 156 | sched_res["He2019"][test_idx] += GP_FP_FTP_He2019_C(task_set, m); 157 | time_res["He2019"].push_back(timer.toc()); 158 | } 159 | 160 | else if(gp.aType == AlgorithmType_t::EDF && gp.DAGType ==DAGType_t::CDAG ){ 161 | if(i % gp.tasksetPerVarFactor == 0) 162 | sched_res["Melani2015"].push_back(0); 163 | 164 | timer.tic(); 165 | sched_res["Melani2015"][test_idx] += GP_FP_EDF_Melani2015_C(task_set, m); 166 | time_res["Melani2015"].push_back(timer.toc()); 167 | } 168 | else if(gp.aType == AlgorithmType_t::FTP && gp.DAGType ==DAGType_t::CDAG){ 169 | if(i % gp.tasksetPerVarFactor == 0){ 170 | sched_res["Melani2015"].push_back(0); 171 | sched_res["Pathan2017"].push_back(0); 172 | } 173 | 174 | timer.tic(); 175 | sched_res["Melani2015"][test_idx] += GP_FP_FTP_Melani2015_C(task_set, m); 176 | time_res["Melani2015"].push_back(timer.toc()); 177 | 178 | timer.tic(); 179 | sched_res["Pathan2017"][test_idx] += GP_FP_DM_Pathan2017_C(task_set, m); 180 | time_res["Pathan2017"].push_back(timer.toc()); 181 | } 182 | 183 | else if(gp.aType == AlgorithmType_t::FTP && gp.DAGType ==DAGType_t::TDAG && gp.wType == workloadType_t::SINGLE_DAG){ 184 | if(i % gp.tasksetPerVarFactor == 0) 185 | sched_res["Han2019"].push_back(0); 186 | 187 | timer.tic(); 188 | sched_res["Han2019"][test_idx] += GP_FP_Han2019_C_1(task_set.tasks[0], gp.typedProc); 189 | time_res["Han2019"].push_back(timer.toc()); 190 | } 191 | 192 | 193 | break; 194 | case DeadlinesType_t::ARBITRARY: 195 | if(gp.aType == AlgorithmType_t::EDF && gp.DAGType ==DAGType_t::DAG ){ 196 | if(i % gp.tasksetPerVarFactor == 0) 197 | sched_res["Bonifaci2013"].push_back(0); 198 | 199 | timer.tic(); 200 | sched_res["Bonifaci2013"][test_idx] += GP_FP_EDF_Bonifaci2013_A(task_set, m); 201 | time_res["Bonifaci2013"].push_back(timer.toc()); 202 | 203 | if(gp.wType == workloadType_t::SINGLE_DAG){ 204 | if(i % gp.tasksetPerVarFactor == 0) 205 | sched_res["Baruah2012"].push_back(0); 206 | 207 | timer.tic(); 208 | sched_res["Baruah2012"][test_idx] += GP_FP_EDF_Baruah2012_A(task_set.tasks[0], m); 209 | time_res["Baruah2012"].push_back(timer.toc()); 210 | } 211 | } 212 | else if(gp.aType == AlgorithmType_t::FTP && gp.DAGType ==DAGType_t::DAG ){ 213 | if(i % gp.tasksetPerVarFactor == 0){ 214 | sched_res["Bonifaci2013"].push_back(0); 215 | sched_res["Fonseca2019"].push_back(0); 216 | } 217 | 218 | timer.tic(); 219 | sched_res["Bonifaci2013"][test_idx] += GP_FP_DM_Bonifaci2013_A(task_set, m); 220 | time_res["Bonifaci2013"].push_back(timer.toc()); 221 | 222 | timer.tic(); 223 | sched_res["Fonseca2019"][test_idx] += GP_FP_FTP_Fonseca2019(task_set, m, false); 224 | time_res["Fonseca2019"].push_back(timer.toc()); 225 | 226 | if(gp.wType == workloadType_t::SINGLE_DAG){ 227 | if(i % gp.tasksetPerVarFactor == 0) 228 | sched_res["Graham1969"].push_back(0); 229 | 230 | timer.tic(); 231 | sched_res["Graham1969"][test_idx] += Graham1969(task_set.tasks[0], m); 232 | time_res["Graham1969"].push_back(timer.toc()); 233 | } 234 | } 235 | break; 236 | } 237 | } 238 | else if(gp.sType == SchedulingType_t::PARTITIONED){ 239 | 240 | if(gp.aType == AlgorithmType_t::FTP && gp.DAGType == DAGType_t::DAG && gp.dtype != DeadlinesType_t::ARBITRARY){ 241 | if(i % gp.tasksetPerVarFactor == 0){ 242 | sched_res["Fonseca2016"].push_back(0); 243 | sched_res["Casini2018"].push_back(0); 244 | // sched_res["Casini2018_W"].push_back(0); 245 | // sched_res["Casini2018_B"].push_back(0); 246 | // sched_res["Casini2018_F"].push_back(0); 247 | // sched_res["Casini2018_P"].push_back(0); 248 | #ifdef ZAHAF2019 249 | sched_res["Zahaf2019"].push_back(0); 250 | #endif 251 | } 252 | 253 | WorstFitProcessorsAssignment(task_set, m); 254 | 255 | timer.tic(); 256 | sched_res["Fonseca2016"][test_idx] += P_FP_FTP_Fonseca2016_C(task_set, m); 257 | time_res["Fonseca2016"].push_back(timer.toc()); 258 | 259 | timer.tic(); 260 | sched_res["Casini2018"][test_idx] += P_LP_FTP_Casini2018_C(task_set, m); 261 | time_res["Casini2018"].push_back(timer.toc()); 262 | 263 | // timer.tic(); 264 | // int worst = P_LP_FTP_Casini2018_C_withAssignment(task_set, m, PartitioningCoresOrder_t::WORST_FIT); 265 | // sched_res["Casini2018_W"][test_idx] += worst; 266 | // time_res["Casini2018_W"].push_back(timer.toc()); 267 | 268 | // timer.tic(); 269 | // int best = P_LP_FTP_Casini2018_C_withAssignment(task_set, m, PartitioningCoresOrder_t::BEST_FIT); 270 | // sched_res["Casini2018_B"][test_idx] += best; 271 | // time_res["Casini2018_B"].push_back(timer.toc()); 272 | 273 | // timer.tic(); 274 | // int first = P_LP_FTP_Casini2018_C_withAssignment(task_set, m, PartitioningCoresOrder_t::FIRST_FIT); 275 | // sched_res["Casini2018_F"][test_idx] += first; 276 | // time_res["Casini2018_F"].push_back(timer.toc()); 277 | 278 | // std::cout<<"PARTITIONED: "<<(first || best || worst)< x = {0.5,0.6,1,.3,.8,1,.9}; 5 | std::vector y1 = {1.0, 0.7, 0.4, 0.0, -0.4, -0.7, -1}; 6 | std::vector y2 = {1.0, 0.99, 0.45, 0.10, -0.14, -0.72, -1.3}; 7 | std::vector> data {x, y1, y2}; 8 | std::vector names = {"1", "2", "3"}; 9 | matplotlibcpp::boxplot(data, names); 10 | 11 | matplotlibcpp::legend(); 12 | matplotlibcpp::save("test.png"); 13 | matplotlibcpp::show(); 14 | } 15 | 16 | void testMatplotlib(){ 17 | const std::string name = "ciao"; 18 | std::vector x, y; 19 | x.push_back(1); 20 | x.push_back(2); 21 | x.push_back(3); 22 | x.push_back(4); 23 | 24 | y.push_back(1); 25 | y.push_back(2); 26 | y.push_back(3); 27 | y.push_back(4); 28 | 29 | matplotlibcpp::named_plot(name, x, y); 30 | matplotlibcpp::annotate("1", 1, 1); 31 | matplotlibcpp::annotate("2", 2, 2); 32 | matplotlibcpp::annotate("3", 3, 3); 33 | matplotlibcpp::annotate("4", 4, 4); 34 | matplotlibcpp::legend(); 35 | matplotlibcpp::show(); 36 | } 37 | 38 | void plotResults(std::map> sched_res, const std::vector& x, const std::string& x_axis, const std::string& y_axis, const std::string& output_fig_path, bool show_plots=true){ 39 | std::vector line_colors = {"#0072BD", "#D95319", "#7E2F8E", "#77AC30", "#4DBEEE", "#A2142F", "#EDB120", "k", "#0072BD", "#D95319"}; 40 | std::vector line_styles = {"-", "--", ":", "-.", "--", ":", "-.","-", "--", ":", "-.","-", "--", ":", "-."}; 41 | std::vector line_marker = {".", "v", "*", "o", "+", ".", "X", "<","", "v", "*", ".", "+", "X", "4", "<"}; 42 | 43 | matplotlibcpp::figure(); 44 | 45 | int i=0; 46 | for(std::map>::iterator iter = sched_res.begin(); iter != sched_res.end(); ++iter){ 47 | // std::cout<first, x, iter->second, line_colors[i], line_marker[i], line_styles[i]); 49 | i++; 50 | } 51 | 52 | matplotlibcpp::xlabel(x_axis); 53 | matplotlibcpp::ylabel(y_axis); 54 | matplotlibcpp::legend(); 55 | matplotlibcpp::save(output_fig_path + ".pdf"); 56 | if(show_plots) 57 | matplotlibcpp::show(); 58 | } 59 | 60 | void plotTimes(std::map> time_res, const std::string& output_fig_path, bool show_plots=true){ 61 | std::vector> data; 62 | std::vector names; 63 | 64 | matplotlibcpp::figure(); 65 | 66 | for(std::map>::iterator iter = time_res.begin(); iter != time_res.end(); ++iter){ 67 | names.push_back(iter->first); 68 | data.push_back(iter->second); 69 | 70 | } 71 | matplotlibcpp::boxplot(data, names); 72 | 73 | matplotlibcpp::ylabel("Latency (us)"); 74 | matplotlibcpp::save(output_fig_path + "_times.pdf"); 75 | if(show_plots) 76 | matplotlibcpp::show(); 77 | } 78 | -------------------------------------------------------------------------------- /include/dagSched/scheduling_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHED_UTILS_H 2 | #define SCHED_UTILS_H 3 | 4 | #include 5 | 6 | int demandBoundFunction(const float interval, const float D, const float T, const float C){ 7 | return (std::floor( (interval - D) / T ) + 1 ) * C; 8 | } 9 | 10 | 11 | #endif /*SCHED_UTILS_H*/ -------------------------------------------------------------------------------- /include/dagSched/tests.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTS_H 2 | #define TESTS_H 3 | 4 | #include 5 | #include "dagSched/DAGTask.h" 6 | #include "dagSched/Taskset.h" 7 | 8 | namespace dagSched{ 9 | 10 | //common 11 | enum PartitioningTaskOrder_t {INC_DEAD, DEC_DEAD, INC_PRIO, DEC_PRIO, INC_UTIL, DEC_UTIL}; 12 | enum PartitioningCoresOrder_t {FIRST_FIT, BEST_FIT, WORST_FIT}; 13 | 14 | bool deadlineMonotonicSorting (const DAGTask& tau_x, const DAGTask& tau_y); 15 | std::vector getCandidatesProcInOrder(const std::vector& proc_util, const float cur_util, const PartitioningCoresOrder_t& c_order); 16 | 17 | bool WorstFitProcessorsAssignment(Taskset& taskset, const int m); 18 | bool BestFitProcessorsAssignment(Taskset& taskset, const int m); 19 | 20 | 21 | //methods from here 22 | bool Graham1969(const DAGTask& task, const int m); 23 | 24 | //global policy, fully preemptive 25 | bool GP_FP_EDF_Baruah2012_C(const DAGTask& task, const int m); 26 | bool GP_FP_EDF_Baruah2012_A(const DAGTask& task, const int m); 27 | 28 | bool GP_FP_EDF_Bonifaci2013_A(const Taskset& taskset, const int m); 29 | bool GP_FP_DM_Bonifaci2013_A(const Taskset& taskset, const int m); 30 | bool GP_FP_DM_Bonifaci2013_C(const Taskset& taskset, const int m); 31 | 32 | bool GP_FP_EDF_Li2013_I(const Taskset& taskset, const int m); 33 | 34 | bool GP_FP_EDF_Qamhieh2013_C(Taskset taskset, const int m); 35 | 36 | bool GP_FP_EDF_Baruah2014_C(Taskset taskset, const int m); 37 | 38 | float workloadUpperBound(const DAGTask& task, const float t, const int m); 39 | bool GP_FP_EDF_Melani2015_C(Taskset taskset, const int m); 40 | bool GP_FP_FTP_Melani2015_C(Taskset taskset, const int m); 41 | 42 | bool GP_FP_DM_Pathan2017_C(Taskset taskset, const int m); 43 | 44 | std::vector> computeWorkloadDistributionCO(const DAGTask& t, const int task_idx); 45 | std::vector> computeWorkloadDistributionCI(const DAGTask& task); 46 | float computeCarryOutUpperBound(const DAGTask& task, const int interval, const std::vector>& WD_UCO_y); 47 | float computeCarryInUpperBound(const DAGTask& task, const int interval, const std::vector>& WD_UCI_y); 48 | bool GP_FP_FTP_Fonseca2017_C(Taskset taskset, const int m); 49 | 50 | bool GP_FP_FTP_Fonseca2019(Taskset taskset, const int m, bool constrained_deadlines = true); 51 | 52 | bool GP_FP_Han2019_C_1(const DAGTask& task, const std::vector m); 53 | 54 | bool GP_FP_He2019_C(DAGTask task, const int m); 55 | bool GP_FP_FTP_He2019_C(Taskset taskset, const int m); 56 | 57 | 58 | //global policy, limited preemptive 59 | 60 | bool GP_LP_FTP_Serrano16_C(Taskset taskset, const int m); 61 | 62 | //partitioned policy 63 | 64 | class SSTask{ 65 | public: 66 | std::vector S; 67 | std::vector C; 68 | std::vector CvID; 69 | float Sub = 0; 70 | int coreId = 0; 71 | 72 | void print(){ 73 | std::cout<<"Task ss (core "<(C, "C"); 76 | std::cout<<"\t"; 77 | printVector(S, "S"); 78 | std::cout<<"\tSub: "<& V, const std::vector& path_ss, const int core_id, const std::vector>& RTs); 83 | bool P_FP_FTP_Fonseca2016_C(Taskset taskset, const int m, const bool joint=true); 84 | bool P_LP_FTP_Casini2018_C(Taskset taskset, const int m); 85 | bool P_LP_FTP_Casini2018_C_withAssignment(Taskset taskset, const int m, const PartitioningCoresOrder_t c_order); 86 | 87 | bool G_LP_FTP_Nasri2019_C(Taskset taskset, const int m); 88 | 89 | #ifdef ZAHAF2019 90 | bool P_LP_EDF_Zahaf2019_C(const Taskset& taskset, const int m); 91 | #endif 92 | 93 | } 94 | 95 | #endif /*TESTS_H*/ -------------------------------------------------------------------------------- /include/dagSched/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define REPRODUCIBLE 1 14 | 15 | #define FatalError(s) { \ 16 | std::stringstream _where, _message; \ 17 | _where << __FILE__ << ':' << __LINE__; \ 18 | _message << std::string(s) + "\n" << __FILE__ << ':' << __LINE__;\ 19 | std::cerr << _message.str() << "\nAborting...\n"; \ 20 | exit(EXIT_FAILURE); \ 21 | } 22 | 23 | // Colored output 24 | #define COL_END "\033[0m" 25 | #define COL_CYANB "\033[1;36m" 26 | 27 | #define TIME_VERBOSE 1 28 | #define METHOD_VERBOSE 0 29 | 30 | #define TSTART timespec start, end; \ 31 | clock_gettime(CLOCK_MONOTONIC, &start); 32 | 33 | #define TSTOP_C(col, show) clock_gettime(CLOCK_MONOTONIC, &end); \ 34 | double t_ns = ((double)(end.tv_sec - start.tv_sec) * 1.0e9 + \ 35 | (double)(end.tv_nsec - start.tv_nsec))/1.0e6; \ 36 | if(show) std::cout< 80 | void set_difference_inplace(std::set& a, const std::set& b) 81 | { 82 | std::set c; 83 | std::set_difference(a.begin(), a.end(),b.begin(), b.end(), std::inserter(c, c.begin()) ); 84 | a = c; 85 | } 86 | 87 | template 88 | void printVector(const std::vector& v, const std::string& name = ""){ 89 | std::cout< 96 | void printSet(const std::set& v, const std::string& name = ""){ 97 | std::cout< 104 | void printPairVector(const std::vector>& v, const std::string& name = ""){ 105 | std::cout< 113 | bool areEqual(const T a, const T b){ 114 | return std::fabs(a - b) < std::numeric_limits::epsilon(); 115 | } 116 | 117 | int intRandMaxMin(const int v_min, const int v_max); 118 | float floatRandMaxMin(const float v_min, const float v_max); 119 | 120 | void removePathAndExtension(const std::string &full_string, std::string &name); 121 | 122 | 123 | enum DOTLine_t {DOT_BEGIN, DOT_END, DOT_NODE, DOT_EDGE, DAG_INFO, VOID_LINE}; 124 | 125 | struct dot_info{ 126 | DOTLine_t lineType; 127 | int p = -1; 128 | int s = -1; 129 | int id = -1; 130 | int id_from = -1; 131 | int id_to = -1; 132 | float wcet = 0; 133 | float period = 0; 134 | float deadline = 0; 135 | }; 136 | 137 | std::vector> separateOnComma(const std::string& line); 138 | dot_info parseDOTLine(const std::string& line); 139 | 140 | #endif /*UTILS_H*/ -------------------------------------------------------------------------------- /src/DAGTask/DAGTask.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/DAGTask.h" 2 | 3 | namespace dagSched{ 4 | 5 | void DAGTask::cloneVertices(const std::vector& to_clone_V){ 6 | V.clear(); 7 | for(int i=0; ipred.clear(); 15 | V[i]->succ.clear(); 16 | 17 | for(int j=0; jsucc.size();++j) 18 | V[i]->succ.push_back(V[to_clone_V[i]->succ[j]->id]); 19 | 20 | for(int j=0; jpred.size();++j) 21 | V[i]->pred.push_back(V[to_clone_V[i]->pred[j]->id]); 22 | 23 | } 24 | } 25 | 26 | void DAGTask::destroyVerices(){ 27 | for(int i=0; isucc.size(); ++i){ 33 | 34 | if(w->succ[i] == v){ 35 | is_succ = true; 36 | return; 37 | } 38 | else{ 39 | 40 | isSuccessor(v, w->succ[i], is_succ); 41 | } 42 | } 43 | return; 44 | } 45 | 46 | std::vector DAGTask::getSubTaskAncestors(const int i) const{ 47 | 48 | std::vector ancst; 49 | bool is_succ = false; 50 | for(int j=0; j DAGTask::getSubTaskDescendants(const int i) const{ 61 | 62 | std::vector desc; 63 | bool is_succ = false; 64 | for(int j=0; j succ_desc; 77 | //find all the successors descendants 78 | for(int j=0; jsucc.size();++j){ 79 | std::vector succ_desc_j = getSubTaskDescendants(V[i]->succ[j]->id); 80 | succ_desc.insert(succ_desc.end(), succ_desc_j.begin(), succ_desc_j.end()); 81 | } 82 | 83 | // is a successor is also a successors descendants, mark to remove 84 | std::vector to_remove; 85 | for(int j=0; jsucc.size();++j){ 86 | if ( std::find(succ_desc.begin(), succ_desc.end(), V[i]->succ[j]) != succ_desc.end() ){ 87 | to_remove.push_back(V[i]->succ[j]); 88 | } 89 | } 90 | 91 | //remove 92 | for(auto& r:to_remove){ 93 | V[i]->succ.erase(std::remove(V[i]->succ.begin(), V[i]->succ.end(), r), V[i]->succ.end()); 94 | r->pred.erase(std::remove(r->pred.begin(), r->pred.end(), V[i]), r->pred.end()); 95 | } 96 | } 97 | } 98 | 99 | bool DAGTask::allPrecAdded(std::vector pred, std::vector ids){ 100 | bool prec_present; 101 | for(int i=0; iid == ids[j]){ 105 | prec_present = true; 106 | break; 107 | } 108 | } 109 | if(!prec_present) 110 | return false; 111 | } 112 | return true; 113 | } 114 | 115 | void DAGTask::topologicalSort (){ 116 | std::vector V_copy; 117 | ordIDs.clear(); 118 | 119 | for(const auto &v: V) 120 | V_copy.push_back(*v); 121 | 122 | bool nodes_to_add = true; 123 | while(nodes_to_add){ 124 | nodes_to_add = false; 125 | for(auto &v: V_copy){ 126 | if((v.pred.empty() || allPrecAdded(v.pred, ordIDs))){ 127 | if(v.id != -1 ){ 128 | ordIDs.push_back(v.id); 129 | v.id = -1; 130 | } 131 | } 132 | else 133 | nodes_to_add = true; 134 | } 135 | } 136 | 137 | if(!checkIndexAndIdsAreEqual()) 138 | FatalError("Ids and Indexes do not correspond, can't use computed topological order!"); 139 | if(ordIDs.size() != V.size()) 140 | FatalError("Ids and V sizes differ!"); 141 | } 142 | 143 | bool DAGTask::checkIndexAndIdsAreEqual(){ 144 | for(size_t i=0; iid != i) 146 | return false; 147 | return true; 148 | } 149 | 150 | void DAGTask::computeVolume(){ 151 | vol = 0; 152 | for(size_t i=0; ic; 154 | } 155 | 156 | void DAGTask::computeWorstCaseWorkload(){ 157 | // Algorithm 1, Melani et al. "Response-Time Analysis of Conditional DAG Tasks in Multiprocessor Systems" 158 | // computes volume both for DAGs and Conditinal DAGs 159 | if(!ordIDs.size()) 160 | topologicalSort(); 161 | 162 | std::vector> paths (V.size()); 163 | paths[ordIDs[ordIDs.size()-1]].insert(ordIDs[ordIDs.size()-1]); 164 | int idx; 165 | for(int i = ordIDs.size()-2; i >= 0; --i ){ 166 | idx = ordIDs[i]; 167 | paths[idx].insert(idx); 168 | 169 | if(V[idx]->succ.size()){ 170 | if(V[idx]->mode != C_SOURCE_T){ 171 | for(int j=0; jsucc.size(); ++j) 172 | paths[idx].insert(paths[V[idx]->succ[j]->id].begin(), paths[V[idx]->succ[j]->id].end()); 173 | } 174 | else{ 175 | std::vector sum (V[idx]->succ.size(), 0); 176 | int max_id = 0; 177 | float max_sum = 0; 178 | for(int j=0; jsucc.size(); ++j){ 179 | for(auto k: paths[V[idx]->succ[j]->id]) 180 | sum[j] += V[k]->c; 181 | if(sum[j] > max_sum){ 182 | max_sum = sum[j]; 183 | max_id = j; 184 | } 185 | } 186 | paths[idx].insert(paths[V[idx]->succ[max_id]->id].begin(), paths[V[idx]->succ[max_id]->id].end()); 187 | } 188 | } 189 | } 190 | 191 | wcw = 0; 192 | for(auto i:paths[ordIDs[0]]){ 193 | wcw += V[i]->c; 194 | } 195 | } 196 | 197 | void DAGTask::computeTypedVolume(){ 198 | for(size_t i=0; igamma) == typedVol.end() ) 200 | typedVol[V[i]->gamma] = V[i]->c; 201 | else 202 | typedVol[V[i]->gamma] += V[i]->c; 203 | } 204 | } 205 | 206 | void DAGTask::computepVolume(){ 207 | pVol.clear(); 208 | for(size_t i=0; icore) == pVol.end() ) 210 | pVol[V[i]->core] = V[i]->c; 211 | else 212 | pVol[V[i]->core] += V[i]->c; 213 | } 214 | } 215 | 216 | void DAGTask::computeAccWorkload(){ 217 | int max_acc_prec; 218 | for(size_t i=0; ipred.size();++j){ 221 | if(V[ordIDs[i]]->pred[j]->accWork > max_acc_prec) 222 | max_acc_prec = V[ordIDs[i]]->pred[j]->accWork; 223 | } 224 | 225 | V[ordIDs[i]]->accWork = V[ordIDs[i]]->c + max_acc_prec; 226 | } 227 | } 228 | 229 | void DAGTask::computeLength(){ 230 | if(!ordIDs.size()) 231 | topologicalSort(); 232 | L = 0; 233 | computeAccWorkload(); 234 | for(const auto&v :V) 235 | if(v->accWork > L) 236 | L = v->accWork; 237 | } 238 | 239 | void DAGTask::computeUtilization(){ 240 | if(vol == 0) 241 | computeWorstCaseWorkload(); 242 | u = wcw / t; 243 | } 244 | 245 | void DAGTask::computeDensity(){ 246 | if(L == 0) 247 | computeLength(); 248 | delta = L / d; 249 | } 250 | 251 | void DAGTask::computeLocalOffsets(){ 252 | if(!ordIDs.size()) 253 | topologicalSort(); 254 | 255 | for(int i=0; ilocalOffset(); 257 | } 258 | } 259 | 260 | void DAGTask::computeLocalDeadlines(){ 261 | if(!ordIDs.size()) 262 | topologicalSort(); 263 | 264 | for(int i=ordIDs.size()-1; i>=0;--i){ 265 | V[ordIDs[i]]->localDeadline(d); 266 | } 267 | } 268 | 269 | void DAGTask::computeEFTs(){ 270 | DAGTask::computeLocalOffsets(); 271 | 272 | for(auto&v:V) 273 | v->EasliestFinishingTime(); 274 | } 275 | void DAGTask::computeLSTs(){ 276 | DAGTask::computeLocalDeadlines(); 277 | 278 | for(auto&v:V) 279 | v->LatestStartingTime(); 280 | } 281 | 282 | std::vector> DAGTask::computeAllPathsSingleSource(std::vector& path, std::vector>& all_paths) const{ 283 | 284 | int last_node = path.back(); 285 | if(V[last_node]->succ.size() > 0) { 286 | for(int i=0; isucc.size(); ++i){ 287 | std::vector new_path = path; 288 | new_path.push_back(V[last_node]->succ[i]->id); 289 | all_paths = computeAllPathsSingleSource(new_path, all_paths); 290 | } 291 | } 292 | else 293 | all_paths.push_back(path); 294 | 295 | return all_paths; 296 | } 297 | 298 | std::vector> DAGTask::computeAllPaths() const{ 299 | std::vector> all_paths; 300 | for(int i=0; ipred.size() == 0){ 302 | std::vector cur_path; 303 | cur_path.push_back(i); 304 | all_paths = computeAllPathsSingleSource(cur_path, all_paths); 305 | } 306 | } 307 | 308 | return all_paths; 309 | } 310 | 311 | bool compareDAGsDeadlineInc(const DAGTask& a, const DAGTask& b){ 312 | return a.getDeadline() < b.getDeadline(); 313 | } 314 | 315 | bool compareDAGsDeadlineDec(const DAGTask& a, const DAGTask& b){ 316 | return a.getDeadline() > b.getDeadline(); 317 | } 318 | 319 | bool compareDAGsPeriodInc(const DAGTask& a, const DAGTask& b){ 320 | return a.getPeriod() < b.getPeriod(); 321 | } 322 | 323 | bool compareDAGsPeriodDec(const DAGTask& a, const DAGTask& b){ 324 | return a.getPeriod() > b.getPeriod(); 325 | } 326 | 327 | bool compareDAGsUtilInc(const DAGTask& a, const DAGTask& b){ 328 | return a.getUtilization() < b.getUtilization(); 329 | } 330 | 331 | bool compareDAGsUtilDec(const DAGTask& a, const DAGTask& b){ 332 | return a.getUtilization() > b.getUtilization(); 333 | } 334 | 335 | } -------------------------------------------------------------------------------- /src/DAGTask/DAGTask_Melani.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/DAGTask.h" 2 | 3 | namespace dagSched{ 4 | 5 | void DAGTask::assignWCET(const int minC, const int maxC){ 6 | for(auto &v: V) 7 | v->c = intRandMaxMin(minC, maxC); 8 | } 9 | 10 | void DAGTask::expandTaskSeriesParallel(SubTask* source,SubTask* sink,const int depth,const int numBranches, const bool ifCond, GeneratorParams& gp){ 11 | 12 | int depthFactor = std::max(gp.maxCondBranches, gp.maxParBranches); 13 | int horSpace = std::pow(depthFactor,depth); 14 | 15 | if(source == nullptr && sink==nullptr){ 16 | SubTask *so = new SubTask; //source 17 | SubTask *si = new SubTask; //sink 18 | so->depth = depth; 19 | si->depth = -depth; 20 | so->width = 0; 21 | so->width = 0; 22 | si->id = 1; 23 | 24 | V.push_back(so); 25 | V.push_back(si); 26 | 27 | double r = ((double) rand() / (RAND_MAX)); 28 | if (r < gp.probSCond){ //make it conditional 29 | int cond_branches = intRandMaxMin(2, gp.maxCondBranches); 30 | expandTaskSeriesParallel(V[0], V[1], depth - 1, cond_branches, true, gp); 31 | } 32 | else{ 33 | int par_branches = intRandMaxMin(2, gp.maxParBranches); 34 | expandTaskSeriesParallel(V[0], V[1], depth - 1, par_branches, false, gp); 35 | } 36 | } 37 | else{ 38 | float step = horSpace / (numBranches - 1); 39 | float w1 = (source->width - horSpace / 2); 40 | float w2 = (sink->width - horSpace / 2); 41 | 42 | for(int i=0; i(gp.dist(gp.gen)); 47 | 48 | switch (state){ 49 | case TERMINAL_T:{ 50 | SubTask *v = new SubTask; 51 | v->id = V.size(); 52 | v->pred.push_back(source); 53 | v->succ.push_back(sink); 54 | v->mode = ifCond? C_INTERN_T : NORMAL_T; 55 | v->depth = depth; 56 | v->width = w1 + step * (i - 1); 57 | 58 | V.push_back(v); 59 | 60 | source->mode = ifCond ? C_SOURCE_T : NORMAL_T; 61 | sink->mode = ifCond ? C_SINK_T : NORMAL_T; 62 | source->succ.push_back(V[V.size()-1]); 63 | 64 | sink->pred.push_back(V[V.size()-1]); 65 | break; 66 | } 67 | case PARALLEL_T: case CONDITIONAL_T:{ 68 | SubTask *v1 = new SubTask; 69 | v1->id = V.size(); 70 | v1->pred.push_back(source); 71 | v1->mode = ifCond? C_INTERN_T : NORMAL_T; 72 | v1->depth = depth; 73 | v1->width = w1 + step * (i - 1); 74 | V.push_back(v1); 75 | 76 | source->succ.push_back(V[V.size()-1]); 77 | source->mode = ifCond ? C_SOURCE_T : NORMAL_T; 78 | 79 | SubTask *v2 = new SubTask; 80 | v2->id = V.size(); 81 | v2->succ.push_back(sink); 82 | v2->mode = ifCond? C_INTERN_T : NORMAL_T; 83 | v2->depth = -depth; 84 | v2->width = w2 + step * (i - 1); 85 | V.push_back(v2); 86 | 87 | sink->pred.push_back(V[V.size()-1]); 88 | sink->mode = ifCond ? C_SINK_T : NORMAL_T; 89 | 90 | int max_branches = (state == PARALLEL_T )? gp.maxParBranches : gp.maxCondBranches; 91 | float cond = (state == PARALLEL_T) ? false: true; 92 | 93 | int branches = intRandMaxMin(2, max_branches); 94 | 95 | expandTaskSeriesParallel(V[V.size()-2], V[V.size()-1], depth - 1, branches, cond, gp); 96 | 97 | break; 98 | } 99 | 100 | default: 101 | break; 102 | } 103 | } 104 | } 105 | } 106 | 107 | void DAGTask::makeItDag(float prob){ 108 | bool is_already_succ= false; 109 | std::vector v_cond_pred; 110 | std::vector w_cond_pred; 111 | for(auto &v:V){ 112 | v_cond_pred = v->getCondPred(); 113 | 114 | for(auto &w:V){ 115 | w_cond_pred = w->getCondPred(); 116 | is_already_succ = false; 117 | 118 | isSuccessor(w, v, is_already_succ); 119 | 120 | if( v->depth > w->depth && 121 | v->mode != C_SOURCE_T && 122 | !is_already_succ && 123 | w_cond_pred.size() == v_cond_pred.size() && 124 | std::equal(v_cond_pred.begin(), v_cond_pred.end(), w_cond_pred.begin()) && 125 | ((double) rand() / (RAND_MAX)) < prob 126 | ) 127 | { 128 | //add an edge v -> w 129 | v->succ.push_back(w); 130 | w->pred.push_back(v); 131 | } 132 | } 133 | } 134 | } 135 | 136 | 137 | 138 | void DAGTask::assignSchedParametersUUniFast(const float U){ 139 | t = std::ceil(wcw / U); 140 | d = t; 141 | } 142 | 143 | void DAGTask::assignSchedParameters(const float beta){ 144 | float Tmin = L; 145 | float Tmax = wcw / beta; 146 | t = floatRandMaxMin(Tmin, Tmax); 147 | d = floatRandMaxMin(Tmin, t); 148 | } 149 | 150 | void DAGTask::assignFixedSchedParameters(const float period, const float deadline){ 151 | t = period; 152 | d = deadline; 153 | } 154 | 155 | } -------------------------------------------------------------------------------- /src/DAGTask/DAGTask_io.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/DAGTask.h" 2 | 3 | namespace dagSched{ 4 | 5 | std::ostream& operator<<(std::ostream& os, const DAGTask& t) 6 | { 7 | 8 | os<<"----------------------------------------------------\n"; 9 | os<< "deadline :" << t.d <id << " - c: "<c <<" \tsucc: "; 19 | for(auto s:v->succ) 20 | os<< s->id << " "; 21 | os<<" \tprec: "; 22 | for(auto p:v->pred) 23 | os<< p->id << " "; 24 | 25 | os<<" \tcore: " << v->core; 26 | os<<" \tlocal O: " << v->localO; 27 | os<<" \tlocal D: " << v->localD; 28 | os<<" \n"; 29 | } 30 | if(t.ordIDs.size()){ 31 | std::cout<<"Topological order: "; 32 | for(auto id:t.ordIDs) 33 | std::cout<(); 44 | d = tasks[i]["d"].as(); 45 | 46 | YAML::Node vert = tasks[i]["vertices"]; 47 | 48 | std::map id_pos; 49 | 50 | for(int j=0; jid = j; 53 | v->c = vert[j]["c"].as(); 54 | 55 | id_pos[vert[j]["id"].as()] = j; 56 | 57 | if(vert[j]["s"]) 58 | v->gamma = vert[j]["s"].as(); 59 | 60 | if(vert[j]["p"]) 61 | v->core = vert[j]["p"].as(); 62 | 63 | V.push_back(v); 64 | } 65 | 66 | YAML::Node edges = tasks[i]["edges"]; 67 | int form_id, to_id; 68 | for(int j=0; j()]; 72 | to_id = id_pos[edges[j]["to"].as()]; 73 | 74 | V[form_id]->succ.push_back(V[to_id]); 75 | V[to_id]->pred.push_back(V[form_id]); 76 | } 77 | 78 | } 79 | 80 | void DAGTask::readTaskFromDOT(const std::string &filename){ 81 | std::ifstream dot_dag(filename); 82 | std::string line; 83 | int node_count = 0; 84 | int form_id, to_id; 85 | 86 | std::map id_pos; 87 | while (std::getline(dot_dag, line)){ 88 | dot_info di = parseDOTLine(line); 89 | 90 | if (di.lineType == DOTLine_t::DAG_INFO){ 91 | t = di.period; 92 | d = di.deadline; 93 | } 94 | else if (di.lineType == DOTLine_t::DOT_NODE){ 95 | 96 | SubTask *v = new SubTask; 97 | v->id = node_count; 98 | v->c = di.wcet; 99 | id_pos[di.id] = node_count; 100 | 101 | if(di.s != -1) 102 | v->gamma = di.s; 103 | 104 | if(di.p != -1) 105 | v->core = di.p; 106 | 107 | V.push_back(v); 108 | node_count++; 109 | } 110 | else if (di.lineType == DOTLine_t::DOT_EDGE){ 111 | 112 | form_id = id_pos[di.id_from]; 113 | to_id = id_pos[di.id_to]; 114 | 115 | V[form_id]->succ.push_back(V[to_id]); 116 | V[to_id]->pred.push_back(V[form_id]); 117 | } 118 | 119 | } 120 | dot_dag.close(); 121 | } 122 | 123 | void DAGTask::saveAsDot(const std::string &filename){ 124 | std::ofstream of(filename); 125 | 126 | of<<"digraph Task {\n"; 127 | 128 | of<<"i [shape=box, label=\"D="<id<<" [label=\""<c<<"("<id<<", p:"<core<<")"<<"\""; 131 | if(v->mode == C_SOURCE_T) of<<",shape=diamond"; 132 | else if(v->mode == C_SINK_T) of<<",shape=box"; 133 | of<<"];\n"; 134 | } 135 | 136 | for (const auto &v: V){ 137 | for(auto s: v->succ) 138 | of<id<<" -> "<id<<";\n"; 139 | } 140 | of<<"}"; 141 | 142 | of.close(); 143 | } 144 | 145 | } -------------------------------------------------------------------------------- /src/SubTask.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/SubTask.h" 2 | 3 | namespace dagSched{ 4 | 5 | std::vector SubTask::getCondPred(){ 6 | std::vector cond_pred; 7 | for(const auto& p:pred){ 8 | if(p->mode == C_SOURCE_T) 9 | cond_pred.push_back(p->id); 10 | } 11 | return cond_pred; 12 | } 13 | 14 | void SubTask::localOffset(){ 15 | if(pred.size() == 0) 16 | localO = 0; 17 | else{ 18 | localO = 0; 19 | float temp_local_o = 0; 20 | for(int i=0; ilocalO + pred[i]->c; 22 | if(temp_local_o > localO) localO = temp_local_o; 23 | } 24 | } 25 | } 26 | 27 | void SubTask::EasliestFinishingTime(){ 28 | if(localO == -1) 29 | FatalError("Requires local offsets to be computed"); 30 | EFT = localO + c; 31 | } 32 | 33 | void SubTask::localDeadline(const float task_deadline){ 34 | if(succ.size() == 0) 35 | localD = task_deadline; 36 | else{ 37 | localD = 99999; 38 | float temp_local_d = 0; 39 | for(int i=0; ilocalD - succ[i]->c; 41 | if(temp_local_d < localD) localD = temp_local_d; 42 | } 43 | } 44 | } 45 | 46 | void SubTask::LatestStartingTime(){ 47 | if(localD == -1) 48 | FatalError("Requires local deadlines to be computed"); 49 | LST = localD - c; 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /src/Taskset.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/Taskset.h" 2 | 3 | namespace dagSched{ 4 | 5 | void Taskset::print() const{ 6 | for(int i=0; i maxDelta) 31 | maxDelta = task.getDensity(); 32 | } 33 | 34 | void Taskset::readTasksetFromYaml(const std::string& params_path){ 35 | YAML::Node config = YAML::LoadFile(params_path); 36 | YAML::Node tasks_node = config["tasks"]; 37 | 38 | for(size_t i=0; i std::ceil(t.getWCW() / U_part)){ 91 | r = ((double) rand() / (RAND_MAX)); 92 | next_sum_U = sum_U * std::pow(r, 1./(n_tasks-i-1)); 93 | U_part = sum_U - next_sum_U; 94 | } 95 | sum_U = next_sum_U; 96 | } 97 | else 98 | U_part = sum_U; 99 | 100 | return U_part; 101 | } 102 | 103 | void Taskset::generate_taskset_Melani(int n_tasks, const float U_tot, const int n_proc, GeneratorParams& gp){ 104 | 105 | float U_part = 0; 106 | float sum_U = U_tot; 107 | U = 0; 108 | 109 | for(int i=0; icore = rand() % n_proc; 127 | 128 | if(gp.DAGType == DAGType_t::TDAG){ 129 | //random assignment of core types to subnodes 130 | for(int j=0; jgamma = rand() % gp.typedProc.size(); 132 | } 133 | 134 | if(gp.gType == GenerationType_t::VARYING_N){ 135 | 136 | U_part = UUniFast_Upart(sum_U, i, n_tasks, t) ; 137 | // std::cout<<"U_part "< U_tot || i == n_tasks - 1){ 168 | float U_prev = U - t.getWCW() / t.getPeriod(); 169 | float U_target = U_tot - U_prev; 170 | float t_to_assign = std::floor(t.getWCW() / U_target); 171 | float d_to_assign = floatRandMaxMin(std::min(t.getLength(), t_to_assign), t_to_assign);; 172 | if(gp.dtype == DeadlinesType_t::IMPLICIT) 173 | d_to_assign = t_to_assign; 174 | t.assignFixedSchedParameters(t_to_assign, d_to_assign); 175 | t.computeDensity(); 176 | t.computeUtilization(); 177 | U = U_prev + t.getWCW() / t.getPeriod(); 178 | n_tasks = i; 179 | tasks.push_back(t); 180 | break; 181 | } 182 | } 183 | } 184 | 185 | tasks.push_back(t); 186 | } 187 | 188 | // computeUtilization(); 189 | computeHyperPeriod(); 190 | computeMaxDensity(); 191 | } 192 | 193 | } -------------------------------------------------------------------------------- /src/tests/Baruah2012.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | // "A generalized parallel task model for recurrent real-time processes" Baruah et al. (RTSS 2012) 4 | 5 | namespace dagSched{ 6 | 7 | /* Theorem 1 in the paper */ 8 | bool GP_FP_EDF_Baruah2012_C(const DAGTask& task, const int m){ 9 | 10 | if(!(task.getDeadline() <= task.getPeriod())) 11 | FatalError("This test requires a constrained deadline task"); 12 | 13 | if( (m-1) * task.getLength() / task.getDeadline() + 14 | 2 * task.getVolume() / task.getPeriod() <= m ) 15 | return true; 16 | return false; 17 | 18 | } 19 | 20 | /* Theorem 3 in the paper */ 21 | bool GP_FP_EDF_Baruah2012_A(const DAGTask& task, const int m){ 22 | 23 | if( task.getLength() <= 2./5. * task.getDeadline() && 24 | task.getVolume() <= 2./5. * m * task.getPeriod() ) 25 | return true; 26 | return false; 27 | 28 | } 29 | 30 | } 31 | 32 | //TODO implement EDFSCHEDPP -------------------------------------------------------------------------------- /src/tests/Baruah2014.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | // Improved Multiprocessor Global Schedulability Analysis of Sporadic DAG Task Systems (ECRTS 2014) 4 | 5 | namespace dagSched{ 6 | 7 | float work(const DAGTask& t, const float interval, const float sigma){ 8 | DAGTask t1 = t; 9 | t1.cloneVertices(t.getVertices()); 10 | 11 | for(auto& v:t1.getVertices()) 12 | v->c /= sigma; 13 | 14 | t1.computeVolume(); 15 | t1.computeAccWorkload(); 16 | t1.computeLength(); 17 | t1.computeLocalOffsets(); 18 | 19 | float n_full = 0, n_part = 0, work_part = 0; 20 | 21 | if( interval >= t.getDeadline()){ 22 | n_full = std::floor((interval - t.getDeadline()) / t.getPeriod()) + 1; 23 | n_part = std::ceil(interval / t.getPeriod()) - n_full; 24 | } 25 | 26 | float work_full = n_full * t1.getVolume(); 27 | 28 | float curr_d = interval - (n_full - 1) * t.getPeriod(); 29 | float curr_r = interval - (t.getDeadline() + (n_full - 1) * t.getPeriod()); 30 | float vert_r = 0; 31 | 32 | for(int i=0; ilocalO; 38 | 39 | if(vert_r >= 0) 40 | work_part += v1->c; 41 | else if(vert_r + v1->c > 0) 42 | work_part += vert_r + v1->c; 43 | } 44 | } 45 | 46 | t1.destroyVerices(); 47 | return work_part + work_full; 48 | } 49 | 50 | float work(const Taskset& taskset, const float interval, const float sigma ){ 51 | float w = 0; 52 | 53 | for(auto& t:taskset.tasks) 54 | w += work(t, interval, sigma); 55 | 56 | return w; 57 | } 58 | 59 | std::vector getTestingSet(const Taskset& taskset, const float sigma, const float bound ){ 60 | std::set interval_set; 61 | 62 | for(const auto&task: taskset.tasks){ 63 | 64 | std::vector lambda_set; 65 | std::vector t_lambda_up; 66 | std::vector t_lambda_down; 67 | std::vector> l_table; 68 | for(const auto&v: task.getVertices()){ 69 | t_lambda_up.push_back(v->localO); 70 | t_lambda_down.push_back(v->localO + v->c); 71 | } 72 | 73 | std::sort(t_lambda_up.begin(), t_lambda_up.end()); 74 | std::sort(t_lambda_down.begin(), t_lambda_down.end()); 75 | 76 | bool pres = false; 77 | int pres_idx = -1; 78 | 79 | l_table.push_back(std::make_pair(0.,1)); 80 | 81 | for(int i=1; i(float(t_lambda_up[i]),1)); 94 | } 95 | 96 | for(int i=1; i= l_table[j].first) 119 | lev = j; 120 | } 121 | 122 | for(int j=lev +1 ; j(float(t_lambda_down[i]),l_table[lev].second -1)); 126 | 127 | std::sort(l_table.begin(), l_table.end()); 128 | } 129 | } 130 | 131 | lambda_set.push_back(l_table[0].first); 132 | for(int i=1; i new_V; 140 | 141 | for(int n=0; true; n++){ 142 | for(int i=0; i(new_V[i], bound) || new_V[i] < bound) 148 | interval_set.insert(new_V[i]); 149 | else{ 150 | exit = true; 151 | break; 152 | } 153 | } 154 | 155 | if(exit) break; 156 | } 157 | } 158 | 159 | std::vector intervals; 160 | 161 | for(const auto& i:interval_set) 162 | intervals.push_back(i); 163 | 164 | std::sort(intervals.begin(), intervals.end()); 165 | return intervals; 166 | } 167 | 168 | bool GP_FP_EDF_Baruah2014_C(Taskset taskset, const int m){ 169 | 170 | std::sort(taskset.tasks.begin(), taskset.tasks.end(), deadlineMonotonicSorting); 171 | 172 | for(auto& task:taskset.tasks){ 173 | if(!(task.getDeadline() <= task.getPeriod())) 174 | FatalError("This test requires constrained deadline tasks"); 175 | 176 | task.computeLocalOffsets(); 177 | } 178 | 179 | bool sched = true; 180 | float sigma_tmp = taskset.getMaxDensity(); 181 | float sigma_inc = 0.025; 182 | float eps = 5e-8; 183 | float interval_tmp = 0; 184 | float U = taskset.getUtilization(); 185 | float HP = taskset.getHyperPeriod(); 186 | 187 | float b1 = 0, b2 = 0; 188 | 189 | float tot_vol = 0; 190 | 191 | for(auto& t:taskset.tasks) 192 | tot_vol += t.getVolume(); 193 | 194 | while(true){ 195 | if (sigma_tmp > ( m - U - eps ) / ( m - 1 )) 196 | return false; 197 | 198 | b2 = tot_vol / ( m - (m-1) * sigma_tmp - U); 199 | 200 | b1 = std::fmin(HP, b2); 201 | 202 | 203 | std::vector ts = getTestingSet(taskset, sigma_tmp, b1); 204 | 205 | for(int i=0; i< ts.size(); ++i){ 206 | if (ts[i] >= interval_tmp){ 207 | float w = work(taskset, ts[i], sigma_tmp); 208 | if( w > ts[i] * ( m - (m-1) * sigma_tmp) ){ 209 | interval_tmp = ts[i]; 210 | sched = false; 211 | break; 212 | } 213 | } 214 | } 215 | 216 | if(sched) return true; 217 | sigma_tmp += sigma_inc; 218 | } 219 | } 220 | 221 | } -------------------------------------------------------------------------------- /src/tests/Bonifaci2013.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | // "Feasibility Analysis in the Sporadic DAG Task Model" Bonifaci et al. (ECRTS 2013) 4 | 5 | namespace dagSched{ 6 | 7 | /* Theorem 21 in the paper */ 8 | bool GP_FP_EDF_Bonifaci2013_A(const Taskset& taskset, const int m){ 9 | float constr_contrib = 0, unconstr_contrib = 0; 10 | for(const auto& task:taskset.tasks){ 11 | if(task.getPeriod() <= task.getDeadline()) 12 | unconstr_contrib += task.getVolume() / task.getPeriod(); 13 | else 14 | constr_contrib += task.getVolume() / task.getDeadline(); 15 | 16 | if(task.getLength() > task.getDeadline() / 3. ) 17 | return false; 18 | } 19 | 20 | if(unconstr_contrib + constr_contrib < (m+0.5)/3.) 21 | return true; 22 | return false; 23 | } 24 | 25 | /* Theorem 22 in the paper */ 26 | bool GP_FP_DM_Bonifaci2013_A(const Taskset& taskset, const int m){ 27 | float constr_contrib = 0, unconstr_contrib = 0; 28 | for(const auto& task:taskset.tasks){ 29 | if(task.getPeriod() <= 2 * task.getDeadline()) 30 | unconstr_contrib += task.getVolume() / task.getPeriod(); 31 | else 32 | constr_contrib += task.getVolume() / (4. * task.getDeadline()); 33 | 34 | if(task.getLength() > task.getDeadline() / 5. ) 35 | return false; 36 | } 37 | 38 | if(unconstr_contrib + constr_contrib < (m+0.25)/5.) 39 | return true; 40 | return false; 41 | } 42 | 43 | /* Theorem 23 in the paper */ 44 | bool GP_FP_DM_Bonifaci2013_C(const Taskset& taskset, const int m){ 45 | float constr_contrib = 0, unconstr_contrib = 0; 46 | for(const auto& task:taskset.tasks){ 47 | if(!(task.getDeadline() <= task.getPeriod())){ 48 | std::cout< task.getDeadline() / 4. ) 58 | return false; 59 | } 60 | 61 | if(unconstr_contrib + constr_contrib < (m+1./3.)/4.) 62 | return true; 63 | return false; 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /src/tests/Chang2020.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | // Shuangshuang Chang et al. “Real-Time scheduling and analysis of paralleltasks on heterogeneous multi-cores”. (Journal of Systems Architecture 2020) 3 | namespace dagSched{ 4 | 5 | bool GP_FP_Chang2020_C(const DAGTask& task, const int m){ 6 | return false; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/tests/Fonseca2016.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | namespace dagSched{ 4 | 5 | std::vector computeSelfOfPath(const std::vector& path, std::vector V){ 6 | //equation 4 7 | std::vector self; 8 | std::vector path_cores; 9 | 10 | for(int i=0; icore); 12 | 13 | for(int i=0; iid) == path.end() && //does not belong to the path 15 | std::find(path_cores.begin(), path_cores.end(), V[i]->core) != path_cores.end() && // if shares the core with at least one node in the path 16 | std::find(V[path[0]]->pred.begin(), V[path[0]]->pred.end(), V[i]) == V[path[0]]->pred.end() && // is not a predecessor of the start 17 | std::find(V[path.back()]->succ.begin(), V[path.back()]->succ.end(), V[i]) == V[path.back()]->succ.end() )// is not a successor of the end 18 | self.push_back(V[i]->id); 19 | } 20 | return self; 21 | } 22 | 23 | SSTask deriveSSTask(const std::vector& V, const std::vector& path_ss, const int core_id, const std::vector>& RTs){ 24 | //setSuspendingTask procedure 25 | SSTask task_ss; 26 | bool flag = false; 27 | for(int i=0; icore == core_id){ 29 | if(flag) 30 | task_ss.S.push_back(0); 31 | task_ss.C.push_back(V[path_ss[i]]->c); 32 | task_ss.CvID.push_back(V[path_ss[i]]->id); 33 | flag = true; 34 | } 35 | else{ 36 | if(flag || task_ss.S.empty()) 37 | task_ss.S.push_back(RTs[path_ss[i]][path_ss[i]]); 38 | else 39 | task_ss.S.back() += RTs[path_ss[i]][path_ss[i]]; 40 | 41 | flag = false; 42 | } 43 | } 44 | 45 | task_ss.Sub = 0; 46 | std::set path_cores; 47 | for(int i=0; icore != core_id) 49 | path_cores.insert(V[path_ss[i]]->core); 50 | 51 | if(METHOD_VERBOSE) printSet(path_cores, "path_cores"); 52 | 53 | int first = 0, last = 0; 54 | for(const auto& core:path_cores){ 55 | //first node allocate to core i 56 | for(first=0; firstcore == core) 58 | break; 59 | //first node allocate to core j 60 | for(last=path_ss.size()-1; last>=0;--last) 61 | if(V[path_ss[last]]->core == core) 62 | break; 63 | 64 | task_ss.Sub += RTs[path_ss[first]][path_ss[last]]; 65 | } 66 | 67 | task_ss.coreId = core_id; 68 | 69 | if(METHOD_VERBOSE) task_ss.print(); 70 | 71 | 72 | return task_ss; 73 | } 74 | 75 | float computeWCRT(const float base, const std::vector& self_ss, const std::vector& hp_ss, const int core_id, const Taskset& taskset, const int task_idx){ 76 | float R_ss = 0; 77 | float new_R_ss = base; 78 | float self_int = 0; 79 | float high_int = 0; 80 | 81 | //equation 7 82 | std::vector V = taskset.tasks[task_idx].getVertices(); 83 | // while(R_ss != new_R_ss){ 84 | R_ss = new_R_ss; 85 | 86 | self_int = 0; 87 | for(const auto s:self_ss) 88 | self_int += V[s]->c; 89 | 90 | high_int = 0; 91 | 92 | for(const auto hp:hp_ss) 93 | high_int+= std::ceil( R_ss / taskset.tasks[hp].getPeriod()) * taskset.tasks[hp].getpVolume()[core_id]; 94 | 95 | if(METHOD_VERBOSE) std::cout<<"self_int: "<& self_ss, const std::vector& hp_ss, const int core_id, const Taskset& taskset, const int task_idx, const bool joint){ 103 | 104 | float WCRT_ss = 0; 105 | if (joint){ 106 | // equation 8 107 | WCRT_ss += tau_ss.Sub; 108 | for(int i=0; i& path_ss, const std::vector& self, const Taskset& taskset, const int task_idx, std::vector>& RTs, const bool joint, bool is_root ){ 125 | //algorithm 1 126 | if(METHOD_VERBOSE) std::cout<<"starting path analysis"<(path_ss, "path ss"); 128 | 129 | std::vector V = taskset.tasks[task_idx].getVertices(); 130 | SubTask* first = V[path_ss[0]]; 131 | SubTask* last = V[path_ss.back()]; 132 | 133 | 134 | 135 | std::vector hp_ss; 136 | std::vector self_ss; 137 | 138 | for(int i=0; icore == first->core) 140 | self_ss.push_back(self[i]); 141 | } 142 | 143 | for(int i=0; i V_cur = taskset.tasks[i].getVertices(); 145 | for(int j=0; jcore == first->core){ 147 | hp_ss.push_back(i); 148 | break; 149 | } 150 | } 151 | } 152 | 153 | if(METHOD_VERBOSE) printVector(hp_ss, "hp tasks"); 154 | if(METHOD_VERBOSE) printVector(self_ss, "self ss"); 155 | 156 | 157 | 158 | if(path_ss.size() == 1){ 159 | float new_R_path_ss = computeWCRT(first->c, self_ss, hp_ss, first->core, taskset, task_idx); 160 | RTs[first->id][last->id] = new_R_path_ss; 161 | if(METHOD_VERBOSE) std::cout<<"RT "<id<<", "<id<<": "<core == last->core){ 165 | std::vector path_sub (path_ss.begin()+1, path_ss.end()-1); 166 | if(path_sub.size() > 0) 167 | pathAnalysis(path_sub, self, taskset, task_idx, RTs, joint, false); 168 | SSTask task_ss = deriveSSTask(V, path_ss, first->core, RTs); 169 | float R_task_ss = computeWCRTss(task_ss, self_ss, hp_ss, first->core, taskset, task_idx, joint); 170 | if(R_task_ss > RTs[first->id][last->id]) 171 | RTs[first->id][last->id] = R_task_ss; 172 | if(METHOD_VERBOSE) std::cout<<"RT "<id<<", "<id<<": "<core == last->core) 179 | break; 180 | } 181 | std::vector path_sub (path_ss.begin()+i, path_ss.end()); 182 | pathAnalysis(path_sub, self, taskset, task_idx, RTs, joint, false); 183 | std::vector path_sub_2 (path_ss.begin(), path_ss.end()-1); 184 | pathAnalysis(path_sub_2, self, taskset, task_idx, RTs, joint, false); 185 | } 186 | } 187 | 188 | if(is_root){ 189 | float RT = 0; 190 | std::set path_cores; 191 | for(int i=0; icore); 193 | 194 | if(METHOD_VERBOSE) printSet(path_cores, "path_cores"); 195 | 196 | int first_ofc = 0, last_ofc = 0; 197 | for(const auto& core:path_cores){ 198 | //first node allocate to core i 199 | for(first_ofc=0; first_ofccore == core) 201 | break; 202 | //first node allocate to core j 203 | for(last_ofc=path_ss.size()-1; last_ofc>=0;--last_ofc) 204 | if(V[path_ss[last_ofc]]->core == core) 205 | break; 206 | 207 | RT += RTs[path_ss[first_ofc]][path_ss[last_ofc]]; 208 | } 209 | 210 | if(METHOD_VERBOSE) std::cout<<"RT: "< RTs[first->id][last->id]) 212 | RTs[first->id][last->id] = RT; 213 | } 214 | 215 | } 216 | 217 | float computeWCRTDAG(const Taskset& taskset, const int task_idx, const bool joint){ 218 | //corollary 1 219 | 220 | std::vector V = taskset.tasks[task_idx].getVertices(); 221 | std::vector> RTs (V.size(), std::vector(V.size(), 0)); 222 | 223 | //analyze each path 224 | std::vector> all_paths= taskset.tasks[task_idx].computeAllPaths(); 225 | for(const auto& p:all_paths){ 226 | auto self = computeSelfOfPath(p,V); 227 | pathAnalysis(p, self, taskset, task_idx, RTs, joint, true); 228 | } 229 | 230 | // compute max response time of paths 231 | int R_DAG = 0; 232 | for(int i=0;i R_DAG) 237 | R_DAG = RTs[i][j]; 238 | } 239 | } 240 | 241 | return R_DAG; 242 | } 243 | 244 | bool P_FP_FTP_Fonseca2016_C(Taskset taskset, const int m, const bool joint){ 245 | std::sort(taskset.tasks.begin(), taskset.tasks.end(), deadlineMonotonicSorting); 246 | // std::vector> R(taskset.tasks.size()); 247 | 248 | std::map pVol; 249 | for(int i=0; i taskset.tasks[i].getDeadline()) 256 | return false; 257 | } 258 | 259 | bool at_least_one_update = true; 260 | if(at_least_one_update){ 261 | at_least_one_update = false; 262 | 263 | for(int i=0; i taskset.tasks[i].getDeadline()) 267 | return false; 268 | 269 | if(!areEqual(R, taskset.tasks[i].R)) 270 | at_least_one_update = true; 271 | 272 | if (R > taskset.tasks[i].R) 273 | taskset.tasks[i].R = R; 274 | } 275 | } 276 | 277 | return true; 278 | } 279 | 280 | } -------------------------------------------------------------------------------- /src/tests/Fonseca2017.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | #include "dagSched/SP-Tree.h" 3 | 4 | namespace dagSched{ 5 | 6 | //Fonseca et al. “Improved response time analysis of sporadic dag tasks for global fp scheduling”. (RTNS 2017) 7 | 8 | std::vector> computeWorkloadDistributionCI(const DAGTask& task){ 9 | 10 | std::vector> WD; 11 | auto V = task.getVertices(); 12 | 13 | std::vector F; 14 | std::set F_set; 15 | 16 | F_set.insert(0); 17 | 18 | for(int i=0; iEFT); 20 | 21 | for(const auto& f:F_set) 22 | F.push_back(f); 23 | std::sort(F.begin(), F.end()); 24 | 25 | float w, h; 26 | for(int t=1; t= V[i]->localO && F[t-1] < V[i]->EFT) 35 | h++; 36 | 37 | WD.push_back(std::make_pair(w,h)); 38 | 39 | } 40 | 41 | return WD; 42 | } 43 | 44 | float computeCarryInUpperBound(const DAGTask& task, const int interval, const std::vector>& WD_UCI_y){ 45 | 46 | //equation 6 in the paper 47 | 48 | float CI = 0, CI_tmp = 0; 49 | 50 | for(int i=0; i< WD_UCI_y.size();++i){ 51 | CI_tmp = interval - task.getPeriod() + task.R; 52 | 53 | for(int j=i+1; j< WD_UCI_y.size();++j) 54 | CI_tmp -= WD_UCI_y[j].first; 55 | 56 | CI += WD_UCI_y[i].second * std::max( float(0), std::min (WD_UCI_y[i].first, CI_tmp)); 57 | } 58 | 59 | return CI; 60 | 61 | } 62 | 63 | 64 | float computeImprovedCarryInUpperBound(const DAGTask& task, const int interval, const std::vector>& WD_UCI_y, const int m){ 65 | //theorem 2 in the paper 66 | 67 | float CI_up = computeCarryInUpperBound(task, interval, WD_UCI_y); 68 | return std::min( CI_up, m * std::max( float(0) , interval - task.getPeriod() + task.R )); 69 | } 70 | 71 | 72 | 73 | 74 | void removeConflictingEdge(std::vector & V, const int i, const int j, const std::vector ordIDs){ 75 | 76 | // std::cout<<"removing:"<< V[j]->id <<" to "<< V[i]->id<pred.erase(std::remove(V[i]->pred.begin(), V[i]->pred.end(), V[j]), V[i]->pred.end()); 79 | V[j]->succ.erase(std::remove(V[j]->succ.begin(), V[j]->succ.end(), V[i]), V[j]->succ.end()); 80 | 81 | // if V_j has no successor, link it to the end 82 | if(V[j]->succ.size() == 0 && j != ordIDs[ordIDs.size() - 1]){ 83 | // std::cout<<"adding:"<< V[j]->id <<" to "<< V[ordIDs[ordIDs.size() - 1]]->id<succ.push_back(V[ordIDs[ordIDs.size() - 1]]); 85 | V[ordIDs[ordIDs.size() - 1]]->pred.push_back(V[j]); 86 | } 87 | } 88 | 89 | void convertDAGintoNFJDAG(DAGTask& t1, const int task_idx, bool save=false){ 90 | 91 | auto V = t1.getVertices(); 92 | auto ordIDs = t1.getTopologicalOrder(); 93 | bool is_succ = false; 94 | bool confl_edge = true; 95 | bool same_fork = false, same_join = false; 96 | 97 | confl_edge = false; 98 | 99 | for(int idx_1=ordIDs.size() -1 , i; idx_1>=0 ; --idx_1 ){ 100 | i = ordIDs[idx_1]; 101 | if(V[i]->pred.size() > 1){ 102 | 103 | // std::cout<<"join:"<id<pred.size(); ++j){ 106 | for(int idx_2=0, k; idx_2 < idx_1; ++idx_2 ){ 107 | 108 | k = ordIDs[idx_2]; 109 | is_succ = false; 110 | t1.isSuccessor(V[i]->pred[j], V[k], is_succ); 111 | if(V[k]->succ.size() > 1 && is_succ){ 112 | // if Vk is a fork node and Vj one of its successors 113 | 114 | // std::cout<<"fork:"<id<pred[j]->succ.size(); ++s){ 117 | 118 | if(V[i]->pred[j]->succ[s] == V[i]) 119 | continue; 120 | 121 | same_fork = same_join = false; 122 | t1.isSuccessor(V[i]->pred[j]->succ[s], V[k], same_fork); 123 | t1.isSuccessor(V[i], V[i]->pred[j]->succ[s], same_join); 124 | if(!same_fork || !same_join){ 125 | confl_edge = true; 126 | removeConflictingEdge(V, i, V[i]->pred[j]->id, ordIDs); 127 | } 128 | } 129 | 130 | for(int p=0; ppred[j]->pred.size(); ++p){ 131 | 132 | if(V[i]->pred[j]->pred[p] == V[k]) 133 | continue; 134 | 135 | same_fork = same_join = false; 136 | 137 | t1.isSuccessor(V[i]->pred[j]->pred[p], V[k], same_fork); 138 | t1.isSuccessor(V[i], V[i]->pred[j]->pred[p], same_join); 139 | 140 | if(!same_fork || !same_join){ 141 | confl_edge = true; 142 | removeConflictingEdge(V, i, V[i]->pred[j]->id, ordIDs); 143 | } 144 | } 145 | } 146 | } 147 | } 148 | } 149 | } 150 | 151 | t1.setVertices(V); 152 | 153 | if(save){ 154 | t1.saveAsDot("test_transf"+std::to_string(task_idx)+".dot"); 155 | std::string dot_command = "dot -Tpng test_transf"+std::to_string(task_idx)+".dot > test_transf"+std::to_string(task_idx)+".png"; 156 | system(dot_command.c_str()); 157 | } 158 | 159 | } 160 | 161 | std::vector> computeWorkloadDistributionCO(const DAGTask& t, const int task_idx){ 162 | // algorithm 1 163 | 164 | //clone task 165 | DAGTask t1 = t; 166 | t1.cloneVertices(t.getVertices()); 167 | 168 | //convert DAG into NFJ DAG 169 | convertDAGintoNFJDAG(t1, task_idx); 170 | 171 | // convert NFJ DAG into SP-Tree decomposition 172 | SPTree tree; 173 | tree.convertNFJDAGtoSPTree(t1, task_idx); 174 | 175 | //compute WD_UCO 176 | auto WD_UCO_y = tree.computeWDUCO(t1, task_idx); 177 | 178 | //destroy new task (tree will call deconstructor) 179 | t1.destroyVerices(); 180 | 181 | return WD_UCO_y; 182 | } 183 | 184 | float computeCarryOutUpperBound(const DAGTask& task, const int interval, const std::vector>& WD_UCO_y){ 185 | 186 | //equation 9 in the paper 187 | float CO = 0, CO_tmp = 0; 188 | 189 | for(int i=0; i< WD_UCO_y.size();++i){ 190 | CO_tmp = interval; 191 | 192 | for(int j=0; j < i;++j) 193 | CO_tmp -= WD_UCO_y[j].first; 194 | 195 | CO += WD_UCO_y[i].second * std::max( float(0), std::min (WD_UCO_y[i].first, CO_tmp)); 196 | } 197 | 198 | return CO; 199 | 200 | } 201 | 202 | float computeImprovedCarryOutUpperBound(const DAGTask& task, const float interval, const std::vector>& WD_UCO_y, const int m){ 203 | //theorem 4 in the paper 204 | 205 | float CO_up = computeCarryOutUpperBound(task, interval, WD_UCO_y); 206 | float CO = std::min( CO_up, interval * m); 207 | CO = std::min( CO, task.getVolume() - std::max( float(0) ,task.getLength() - interval )); 208 | 209 | return CO; 210 | } 211 | 212 | float computeCarryWorkload(const DAGTask& task, const float interval, const std::vector>& WD_UCO_y, const std::vector>& WD_UCI_y){ 213 | // Algorithm 2 214 | 215 | float WyC = computeCarryOutUpperBound(task, interval, WD_UCO_y ); 216 | float x1 = task.getPeriod() - task.R, x2; 217 | float CI = 0, CO = 0; 218 | 219 | for(int i=WD_UCI_y.size() -1; i>=0; --i){ 220 | x1 += WD_UCI_y[i].first; 221 | x2 = interval - x1; 222 | CI = computeCarryInUpperBound(task, x1, WD_UCI_y); 223 | CO = computeCarryOutUpperBound(task, x2, WD_UCO_y); 224 | WyC = std::max(WyC, CI + CO); 225 | } 226 | 227 | CI = computeCarryInUpperBound(task, interval, WD_UCI_y); 228 | WyC = std::max(WyC, CI); 229 | 230 | x2= 0; 231 | 232 | for(int i=0; i>& WD_UCO_y, const std::vector>& WD_UCI_y){ 252 | // equation 10 253 | 254 | float delta_c = computeDeltaC(task, interval); 255 | float carry_workload = computeCarryWorkload(task, delta_c, WD_UCO_y, WD_UCI_y); 256 | float T = task.getPeriod(); 257 | float vol = task.getVolume(); 258 | 259 | return carry_workload + std::max( float(0), std::floor( (interval - delta_c) / T )) * vol; 260 | } 261 | 262 | bool GP_FP_FTP_Fonseca2017_C(Taskset taskset, const int m){ 263 | std::sort(taskset.tasks.begin(), taskset.tasks.end(), deadlineMonotonicSorting); 264 | 265 | std::vector R_old (taskset.tasks.size(), 0); 266 | std::vector R (taskset.tasks.size(), 0); 267 | 268 | std::vector>> WD_UCO (taskset.tasks.size()); 269 | std::vector>> WD_UCI (taskset.tasks.size()); 270 | for(int i=0; i taskset.tasks[i].getDeadline()) 282 | return false; 283 | 284 | bool init = true; 285 | while(!areEqual(R[i], R_old[i]) && R[i] <= taskset.tasks[i].getDeadline()){ 286 | 287 | if(!init) 288 | R_old[i] = R[i]; 289 | 290 | //higher prio tasks interference 291 | float hp_int = 0; 292 | for(int j=0; j(R[i], R_old[i])) 306 | taskset.tasks[i].R = R[i]; 307 | if (taskset.tasks[i].R > taskset.tasks[i].getDeadline()) 308 | return false; 309 | } 310 | 311 | return true; 312 | } 313 | 314 | } -------------------------------------------------------------------------------- /src/tests/Fonseca2019.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | //Fonseca et al. “Schedulability Analysis of DAG Tasks with Arbitrary Deadlines under Global Fixed-Priority Scheduling”. (Real-Time Systems 2019) 4 | 5 | namespace dagSched{ 6 | 7 | float computeCarryWorkload_C(const DAGTask& task, const float interval, const std::vector>& WD_UCO_y, const std::vector>& WD_UCI_y, const int m){ 8 | // Algorithm 2 9 | 10 | float B_y = std::max(task.getLength(), task.getVolume() / m); 11 | 12 | float x2 = std::min(interval, B_y); 13 | float x1 = interval - x2; 14 | float CI = computeCarryInUpperBound(task, x1, WD_UCI_y ); 15 | float CO = computeCarryOutUpperBound(task, x2, WD_UCO_y); 16 | float WyC = CI + CO; 17 | 18 | x1 = std::min(interval, B_y + (task.getPeriod() - task.R)); 19 | x2 = interval - x1; 20 | CI = computeCarryInUpperBound(task, x1, WD_UCI_y ); 21 | CO = computeCarryOutUpperBound(task, x2, WD_UCO_y); 22 | WyC = std::max(WyC, CI + CO ); 23 | 24 | x1 = (task.getPeriod() - task.R); 25 | 26 | for(int i=WD_UCI_y.size() -1; i>=0; --i){ 27 | x1 += WD_UCI_y[i].first; 28 | x2 = interval - x1; 29 | if(x2 >= 0){ 30 | CI = computeCarryInUpperBound(task, x1, WD_UCI_y); 31 | CO = computeCarryOutUpperBound(task, x2, WD_UCO_y); 32 | WyC = std::max(WyC, CI + CO); 33 | } 34 | } 35 | 36 | x2= 0; 37 | 38 | for(int i=0; i= 0){ 42 | CI = computeCarryInUpperBound(task, x1, WD_UCI_y); 43 | CO = computeCarryOutUpperBound(task, x2, WD_UCO_y); 44 | WyC = std::max(WyC, CI + CO); 45 | } 46 | } 47 | return WyC; 48 | } 49 | 50 | float computeCarryWorkload_A(const DAGTask& task, const float interval, const std::vector>& WD_UCO_y, const std::vector>& WD_UCI_y, const int m){ 51 | // Algorithm 3 52 | 53 | float B_y = std::max(task.getLength(), task.getVolume() / m); 54 | 55 | float x2 = std::min(interval, B_y); 56 | float x1 = interval - x2; 57 | float CI = computeCarryInUpperBound(task, x1, WD_UCI_y ); 58 | float CO = computeCarryOutUpperBound(task, x2, WD_UCO_y); 59 | float WyC = CI + CO; 60 | 61 | float ceil_D_over_T = std::ceil(task.getDeadline() / task.getPeriod()); 62 | 63 | x1 = std::min(interval, B_y + ceil_D_over_T * task.getPeriod() - task.R); 64 | x2 = interval - x1; 65 | CI = computeCarryInUpperBound(task, x1, WD_UCI_y ); 66 | CO = computeCarryOutUpperBound(task, x2, WD_UCO_y); 67 | WyC = std::max(WyC, CI + CO ); 68 | 69 | for(int j = 0; j < ceil_D_over_T; ++j){ 70 | x1 = (task.getPeriod() * j - task.R); 71 | for(int i=WD_UCI_y.size() -1; i>=0; --i){ 72 | x1 += WD_UCI_y[i].first; 73 | x2 = interval - x1; 74 | if(x2 >= 0 && x1 >= 0){ 75 | CI = computeCarryInUpperBound(task, x1, WD_UCI_y); 76 | CO = computeCarryOutUpperBound(task, x2, WD_UCO_y); 77 | WyC = std::max(WyC, CI + CO); 78 | } 79 | } 80 | } 81 | 82 | x2= 0; 83 | for(int i=0; i= 0){ 87 | CI = computeCarryInUpperBound(task, x1, WD_UCI_y); 88 | CO = computeCarryOutUpperBound(task, x2, WD_UCO_y); 89 | WyC = std::max(WyC, CI + CO); 90 | } 91 | } 92 | return WyC; 93 | } 94 | 95 | float computeDeltaC_B(const DAGTask& task, const float interval, const int m){ 96 | // equation 11 97 | float L = task.getLength(); 98 | float T = task.getPeriod(); 99 | float B = std::max(L, task.getVolume() / m); 100 | return interval - std::max( float(0), std::floor( (interval - B) / T )) * T; 101 | } 102 | 103 | 104 | float interTaskWorkload_C(const DAGTask& task, const float interval, const std::vector>& WD_UCO_y, const std::vector>& WD_UCI_y, const int m, bool constrained_deadlines = true){ 105 | // equation 14 106 | 107 | float delta_c = computeDeltaC_B(task, interval, m); 108 | float carry_workload; 109 | if( constrained_deadlines) 110 | carry_workload = computeCarryWorkload_C(task, delta_c, WD_UCO_y, WD_UCI_y, m); 111 | else 112 | carry_workload = computeCarryWorkload_A(task, delta_c, WD_UCO_y, WD_UCI_y, m); 113 | 114 | float T = task.getPeriod(); 115 | float vol = task.getVolume(); 116 | 117 | return carry_workload + std::max( float(0), std::floor( (interval - delta_c) / T )) * vol; 118 | } 119 | 120 | bool GP_FP_FTP_Fonseca2019(Taskset taskset, const int m, bool constrained_deadlines){ 121 | std::sort(taskset.tasks.begin(), taskset.tasks.end(), deadlineMonotonicSorting); 122 | 123 | std::vector R_old (taskset.tasks.size(), 0); 124 | std::vector R (taskset.tasks.size(), 0); 125 | 126 | std::vector>> WD_UCO (taskset.tasks.size()); 127 | std::vector>> WD_UCI (taskset.tasks.size()); 128 | for(int i=0; i taskset.tasks[i].getDeadline()) 140 | return false; 141 | 142 | bool init = true; 143 | while(!areEqual(R[i], R_old[i]) && R[i] <= taskset.tasks[i].getDeadline()){ 144 | if(!init) 145 | R_old[i] = R[i]; 146 | 147 | //higher prio tasks interference 148 | R[i] = 0; 149 | for(int j=0; j(R[i], R_old[i])) 163 | taskset.tasks[i].R = R[i]; 164 | if (R[i] > taskset.tasks[i].getDeadline()) 165 | return false; 166 | } 167 | 168 | return true; 169 | } 170 | 171 | } -------------------------------------------------------------------------------- /src/tests/Graham1969.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | // Bounds on Multiprocessing Timing Anomalies, Garham (SIAM Journal on Applied Mathematics 1969) 4 | 5 | namespace dagSched{ 6 | 7 | bool Graham1969(const DAGTask& task, const int m){ 8 | if(task.getLength() + 1. / m * (task.getVolume() - task.getLength()) > task.getDeadline()){ 9 | return false; 10 | } 11 | return true; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/tests/Han2019.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | // Meiling Han et al. “Response time bounds for typed dag parallel tasks on heterogeneous multi-cores”. (IEEE Transactions on Parallel and DistributedSystems 2019) 4 | 5 | namespace dagSched{ 6 | 7 | bool GP_FP_Han2019_C_1(const DAGTask& task, const std::vector m){ 8 | //theorem 3.1 9 | 10 | DAGTask task1 = task; 11 | task1.cloneVertices(task.getVertices()); 12 | 13 | task1.computeTypedVolume(); 14 | auto typed_vol = task.getTypedVolume(); 15 | auto V = task1.getVertices(); 16 | 17 | // std::cout<<"L: "<gamma > m.size()) 21 | FatalError("Problem with types of core"); 22 | V[i]->c *= (1. - 1. / m[V[i]->gamma]); 23 | } 24 | 25 | task1.computeLength(); 26 | 27 | float L_scaled = task1.getLength(); 28 | 29 | // std::cout<<"L_scaled: "< m){ } //TODO -------------------------------------------------------------------------------- /src/tests/He2019.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | // Qingqiang He et al. “Intra-task priority assignmentin real-time scheduling of dag tasks on multi-cores”. (IEEE Transactions on Parallel and Distributed Systems 2019) 4 | 5 | namespace dagSched{ 6 | 7 | std::set computeInferenceSet( const DAGTask & task, const int i){ 8 | // definition 3 9 | std::vector V = task.getVertices(); 10 | auto ancst = task.getSubTaskAncestors(i); 11 | auto desc = task.getSubTaskDescendants(i); 12 | 13 | std::set int_set; 14 | 15 | for(int j=0; jprio < V[i]->prio && // greater prio 18 | std::find(ancst.begin(), ancst.end(), V[j]) == ancst.end() && // not an ancestor 19 | std::find(desc.begin(), desc.end(), V[j]) == desc.end() ) // not a descendant 20 | int_set.insert(j); 21 | } 22 | 23 | return int_set; 24 | 25 | } 26 | 27 | std::set computePathInferenceSet( const std::set& path, const std::vector>& int_sets){ 28 | 29 | std::set path_int_set; 30 | for(const auto&p: path){ 31 | for(const auto i: int_sets[p]) 32 | path_int_set.insert(i); 33 | } 34 | return path_int_set; 35 | } 36 | 37 | float computePathLen(const std::set& path, const std::vector& V){ 38 | float len = 0; 39 | for(const auto& p:path){ 40 | len += V[p]->c; 41 | } 42 | return len; 43 | } 44 | 45 | float computeR(const int i, const std::set& path, const std::vector& V, const std::vector>& int_sets, const int m){ 46 | 47 | auto path_int = computePathInferenceSet(path, int_sets); 48 | 49 | std::set union_int; 50 | union_int.insert(int_sets[i].begin(), int_sets[i].end()); 51 | union_int.insert(path_int.begin(), path_int.end()); 52 | 53 | float vol = 0; 54 | for(const auto& ui:union_int) 55 | if(ui != i) 56 | vol += V[ui]->c; 57 | 58 | float R = computePathLen(path, V) + V[i]->c + 1. / m * vol; 59 | return R; 60 | 61 | } 62 | 63 | float computeResponseTimeBound(DAGTask& task, const int m){ 64 | //algorithm 1 65 | 66 | std::vector V = task.getVertices(); 67 | std::vector R(V.size()); 68 | std::vector> paths(V.size()); 69 | std::vector ordIDs = task.getTopologicalOrder(); 70 | 71 | //assign priority wrt topological order 72 | for(int idx = 0, i; idx < ordIDs.size() ; ++idx ){ 73 | i = ordIDs[idx]; // vertex index 74 | V[i]->prio = idx; 75 | } 76 | 77 | std::vector> int_sets(V.size()); 78 | for(int i = 0; i < V.size() ; ++i ){ 79 | int_sets[i] = computeInferenceSet(task, i); 80 | } 81 | 82 | //compute response time 83 | for(int idx = 0, i; idx < ordIDs.size() ; ++idx ){ 84 | i = ordIDs[idx]; // vertex index 85 | 86 | if(V[i]->pred.size() != 0){ 87 | int max_id = V[i]->pred[0]->id; 88 | float max_R = R[V[i]->pred[0]->id]; 89 | for(int j=1; jpred.size(); ++j){ 90 | if(R[V[i]->pred[j]->id] > max_R){ 91 | max_R = R[V[i]->pred[j]->id]; 92 | max_id = V[i]->pred[j]->id; 93 | } 94 | } 95 | paths[i].insert(paths[max_id].begin(), paths[max_id].end()); 96 | } 97 | 98 | R[i] = computeR(i, paths[i],V, int_sets, m); 99 | paths[i].insert(i); 100 | 101 | } 102 | 103 | 104 | return R[ordIDs[ordIDs.size() -1]]; 105 | } 106 | 107 | bool GP_FP_He2019_C(DAGTask task, const int m){ 108 | if (computeResponseTimeBound(task, m) <= task.getDeadline()) 109 | return true; 110 | return false; 111 | } 112 | 113 | bool GP_FP_FTP_He2019_C(Taskset taskset, const int m){ 114 | std::sort(taskset.tasks.begin(), taskset.tasks.end(), deadlineMonotonicSorting); 115 | 116 | 117 | std::vector R_old (taskset.tasks.size(), 0); 118 | std::vector R (taskset.tasks.size(), 0); 119 | for(int i=0; i taskset.tasks[i].getDeadline()) 127 | return false; 128 | 129 | bool init = true; 130 | while(!areEqual(R[i], R_old[i]) && R[i] <= taskset.tasks[i].getDeadline()){ 131 | if(!init){ 132 | R_old[i] = R[i]; 133 | R[i] = 0; 134 | } 135 | 136 | R[i] = computeResponseTimeBound(taskset.tasks[i], m); 137 | for(int j=0; j(R[i], R_old[i])) 144 | taskset.tasks[i].R = R[i]; 145 | else if (R[i] > taskset.tasks[i].getDeadline()) 146 | return false; 147 | } 148 | 149 | return true; 150 | 151 | } 152 | 153 | } -------------------------------------------------------------------------------- /src/tests/Li2013.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | // "Outstanding Paper Award: Analysis of Global EDF for Parallel Tasks" Li et al. (ECRTS 2013) 4 | 5 | namespace dagSched{ 6 | 7 | /* Corollary 6 in the paper*/ 8 | bool GP_FP_EDF_Li2013_I(const Taskset& taskset, const int m){ 9 | for(const auto& task:taskset.tasks){ 10 | if(!( areEqual (task.getDeadline() , task.getPeriod()))) 11 | FatalError("This test requires implicit deadline tasks"); 12 | 13 | if(task.getLength() > task.getPeriod() / ( 4. - 2. / m) ) 14 | return false; 15 | } 16 | 17 | if(taskset.getUtilization() <= m / (4. - 2. / m )) 18 | return true; 19 | return false; 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/tests/Melani2015.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | // Alessandra Melani et al. “Response-time analysis of conditional dag tasks in multiprocessor systems”. (ECRTS 2015) 3 | 4 | namespace dagSched{ 5 | 6 | float computeZk(DAGTask task, const int n_proc){ 7 | // Algorithm 2 8 | 9 | auto V = task.getVertices(); 10 | auto ordIDs = task.getTopologicalOrder(); 11 | 12 | if(!ordIDs.size()){ 13 | task.topologicalSort(); 14 | ordIDs = task.getTopologicalOrder(); 15 | } 16 | std::vector> S (V.size()); 17 | std::vector> T (V.size()); 18 | std::vector f (V.size()); 19 | S[ordIDs[ordIDs.size()-1]].insert(ordIDs[ordIDs.size()-1]); 20 | T[ordIDs[ordIDs.size()-1]].insert(ordIDs[ordIDs.size()-1]); 21 | f[ordIDs[ordIDs.size()-1]] = V[ordIDs[ordIDs.size()-1]]->c; 22 | 23 | int idx; 24 | float C = 0; 25 | std::set D; 26 | for(int i = ordIDs.size()-2; i >= 0; --i ){ 27 | idx = ordIDs[i]; 28 | 29 | if(V[idx]->succ.size()){ 30 | S[idx].insert(idx); 31 | if(V[idx]->mode != C_SOURCE_T){ //if not conditional source 32 | std::vector U (V[idx]->succ.size(),0); 33 | for(int j=0; jsucc.size(); ++j){ 34 | S[idx].insert(S[V[idx]->succ[j]->id].begin(), S[V[idx]->succ[j]->id].end()); 35 | U[j] = f[V[idx]->succ[j]->id]; 36 | for(int k=0; ksucc.size(); ++k){ 37 | if(k!=j){ 38 | C = 0; 39 | D.clear(); 40 | std::set_difference(S[V[idx]->succ[k]->id].begin(), 41 | S[V[idx]->succ[k]->id].end(), 42 | T[V[idx]->succ[j]->id].begin(), 43 | T[V[idx]->succ[j]->id].end(), 44 | std::inserter(D, D.begin()) ); 45 | 46 | for (const auto& d:D) 47 | C+= V[d]->c / n_proc; 48 | 49 | U[j]+=C; 50 | } 51 | } 52 | } 53 | int max_U_idx = std::max_element(U.begin(),U.end()) - U.begin(); 54 | T[idx].clear(); 55 | T[idx].insert(idx); 56 | T[idx].insert(T[V[idx]->succ[max_U_idx]->id].begin(), T[V[idx]->succ[max_U_idx]->id].end()); 57 | f[idx] = V[idx]->c + U[max_U_idx]; 58 | } 59 | else{ 60 | std::vector C (V[idx]->succ.size(),0); 61 | std::vector ff (V[idx]->succ.size(),0); 62 | 63 | for(int j=0; jsucc.size(); ++j){ 64 | for(auto k: S[V[idx]->succ[j]->id]){ 65 | C[j] += V[k]->c; 66 | } 67 | 68 | ff[j] = f[V[idx]->succ[j]->id]; 69 | } 70 | 71 | int max_C_idx = std::max_element(C.begin(),C.end()) - C.begin(); 72 | S[idx].insert(S[V[idx]->succ[max_C_idx]->id].begin(), S[V[idx]->succ[max_C_idx]->id].end()); 73 | 74 | int max_ff_idx = std::max_element(ff.begin(),ff.end()) - ff.begin(); 75 | T[idx].clear(); 76 | T[idx].insert(idx); 77 | T[idx].insert(T[V[idx]->succ[max_ff_idx]->id].begin(), T[V[idx]->succ[max_ff_idx]->id].end()); 78 | 79 | f[idx] = V[idx]->c + f[V[idx]->succ[max_ff_idx]->id]; 80 | 81 | } 82 | } 83 | } 84 | return f[ordIDs[0]]; 85 | } 86 | 87 | void maximizeMakespan(const std::vector& V, const SubTask* v, const std::vector& mksp, const std::vector>& mksp_set, const std::vector>& w_set, std::set& mkspset_tmp, float& max_mksp, const int n_proc){ 88 | max_mksp = 0; 89 | for(int j=0; jsucc.size(); ++j){ 90 | float sum_w = 0; 91 | std::set wset_tmp; 92 | 93 | for(int k=0; ksucc.size(); ++k){ 94 | if(k != j){ 95 | std::set new_vert; 96 | std::set_difference(w_set[v->succ[k]->id].begin(), 97 | w_set[v->succ[k]->id].end(), 98 | wset_tmp.begin(), 99 | wset_tmp.end(), 100 | std::inserter(new_vert, new_vert.begin()) ); 101 | set_difference_inplace(new_vert, mksp_set[v->succ[j]->id]); 102 | wset_tmp.insert(new_vert.begin(), new_vert.end()); 103 | 104 | for(const auto& nv:new_vert) 105 | sum_w+= V[nv]->c; 106 | 107 | } 108 | } 109 | 110 | if(mksp[v->succ[j]->id] + sum_w / n_proc > max_mksp){ 111 | max_mksp = mksp[v->succ[j]->id] + sum_w / n_proc; 112 | mkspset_tmp.insert(mksp_set[v->succ[j]->id].begin(), mksp_set[v->succ[j]->id].end()); 113 | mkspset_tmp.insert(wset_tmp.begin(), wset_tmp.end()); 114 | } 115 | } 116 | } 117 | 118 | float computeMakespanUB(DAGTask task, const int n_proc){ 119 | std::vector V = task.getVertices(); 120 | std::vector ordIDs = task.getTopologicalOrder(); 121 | 122 | if(!ordIDs.size()){ 123 | task.topologicalSort(); 124 | ordIDs = task.getTopologicalOrder(); 125 | } 126 | 127 | std::vector> mksp_set (V.size()); 128 | std::vector> w_set (V.size()); 129 | std::vector w (V.size()); 130 | std::vector mksp (V.size()); 131 | 132 | mksp_set[ordIDs[ordIDs.size()-1]].insert(ordIDs[ordIDs.size()-1]); 133 | w_set[ordIDs[ordIDs.size()-1]].insert(ordIDs[ordIDs.size()-1]); 134 | mksp[ordIDs[ordIDs.size()-1]] = V[ordIDs[ordIDs.size()-1]]->c; 135 | w[ordIDs[ordIDs.size()-1]] = V[ordIDs[ordIDs.size()-1]]->c; 136 | 137 | int idx; 138 | float C = 0; 139 | std::set D; 140 | for(int i = ordIDs.size()-2; i >= 0; --i ){ 141 | idx = ordIDs[i]; 142 | mksp_set[idx].insert(idx); 143 | w_set[idx].insert(idx); 144 | mksp[idx] = V[idx]->c; 145 | w[idx] = V[idx]->c; 146 | 147 | if(V[idx]->succ.size()){ 148 | 149 | if(V[idx]->mode != C_SOURCE_T){ //if not conditional source 150 | 151 | float max_mksp = 0; 152 | float w_tmp = 0; 153 | std::set wset_tmp, mkspset_tmp; 154 | maximizeMakespan(V, V[idx], mksp, mksp_set, w_set, mkspset_tmp, max_mksp, n_proc); 155 | 156 | mksp[idx] = max_mksp + V[idx]->c; 157 | mksp_set[idx].insert(idx); 158 | mksp_set[idx].insert(mkspset_tmp.begin(), mkspset_tmp.end()); 159 | 160 | for(int j=0; jsucc.size(); ++j){ 161 | std::set new_vert; 162 | std::set_difference(w_set[V[idx]->succ[j]->id].begin(), 163 | w_set[V[idx]->succ[j]->id].end(), 164 | wset_tmp.begin(), 165 | wset_tmp.end(), 166 | std::inserter(new_vert, new_vert.begin()) ); 167 | wset_tmp.insert(new_vert.begin(), new_vert.end()); 168 | 169 | for(auto nv:new_vert) 170 | w_tmp += V[nv]->c; 171 | } 172 | 173 | w[idx] += w_tmp; 174 | w_set[idx].insert(wset_tmp.begin(), wset_tmp.end()); 175 | 176 | } 177 | else{ 178 | float max_mksp = 0, max_w = 0; 179 | int max_idx = 0; 180 | for(int j=0; jsucc.size(); ++j){ 181 | if(mksp[V[idx]->succ[j]->id] > max_mksp){ 182 | max_mksp = mksp[V[idx]->succ[j]->id]; 183 | max_idx = j; 184 | } 185 | } 186 | mksp[idx] += max_mksp; 187 | mksp_set[idx].insert(mksp_set[V[idx]->succ[max_idx]->id].begin(), mksp_set[V[idx]->succ[max_idx]->id].end()); 188 | 189 | for(int j=0; jsucc.size(); ++j){ 190 | if(w[V[idx]->succ[j]->id] > max_w){ 191 | max_w = w[V[idx]->succ[j]->id]; 192 | max_idx = j; 193 | } 194 | } 195 | 196 | w[idx] += max_w; 197 | w_set[idx].insert(w_set[V[idx]->succ[max_idx]->id].begin(),w_set[V[idx]->succ[max_idx]->id].end()); 198 | } 199 | } 200 | } 201 | 202 | return mksp[ordIDs[0]]; 203 | } 204 | 205 | float workloadUpperBound(const DAGTask& task, const float t, const int m){ 206 | 207 | float wcw = task.getWorstCaseWorkload(); 208 | float T = task.getPeriod(); 209 | 210 | float ci_b = std::floor((t + task.R - wcw / m ) / T ) * wcw; 211 | float co = std::min(wcw, m * std::fmod(t + task.R - wcw / m ,T) ); 212 | 213 | return ci_b + co; 214 | } 215 | 216 | float interferringWorkload(const DAGTask& task_x, const DAGTask& task_y , const float t, const int m){ 217 | float wcw_y = task_y.getWorstCaseWorkload(); 218 | float D_x = task_x.getDeadline(); 219 | float D_y = task_y.getDeadline(); 220 | float T_y = task_y.getPeriod(); 221 | 222 | float ci_b = ( std::floor((D_x - D_y) / T_y) + 1 ) * wcw_y; 223 | float co = std::min( wcw_y, m * float( std::max(float(0), std::fmod(D_x,T_y) - (D_y - task_y.R)))); 224 | 225 | return ci_b + co; 226 | } 227 | 228 | void test_Melani(Taskset taskset, const int m){ 229 | std::sort(taskset.tasks.begin(), taskset.tasks.end(), deadlineMonotonicSorting); 230 | 231 | for(int i=0; i R_old (taskset.tasks.size(), 0); 239 | std::vector R (taskset.tasks.size(), 0); 240 | std::vector mksp (taskset.tasks.size(), 0); 241 | for(int i=0; i taskset.tasks[i].getDeadline()) 253 | return false; 254 | 255 | if(!init){ 256 | R_old[i] = R[i]; 257 | R[i] = 0; 258 | } 259 | 260 | if(taskset.tasks.size() > 1){ 261 | for(int j=0; j(R[i], R_old[i]) ) 276 | changed = true; 277 | 278 | if(R[i] > taskset.tasks[i].getDeadline()) 279 | return false; 280 | 281 | } 282 | init = false; 283 | } 284 | 285 | for(int i=0; i R_old (taskset.tasks.size(), 0); 297 | std::vector R (taskset.tasks.size(), 0); 298 | std::vector mksp (taskset.tasks.size(), 0); 299 | for(int i=0; i taskset.tasks[i].getDeadline()) 308 | return false; 309 | 310 | bool init = true; 311 | while(!areEqual(R[i], R_old[i]) && R[i] <= taskset.tasks[i].getDeadline()){ 312 | if(!init){ 313 | R_old[i] = R[i]; 314 | R[i] = 0; 315 | } 316 | 317 | if(i > 0){ 318 | for(int j=0; j(R[i], R_old[i])) 331 | taskset.tasks[i].R = R[i]; 332 | else if (R[i] > taskset.tasks[i].getDeadline()) 333 | return false; 334 | } 335 | 336 | return true; 337 | } 338 | 339 | } -------------------------------------------------------------------------------- /src/tests/Nasri2019.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | #include"problem.hpp" 4 | #include "io.hpp" 5 | #include "global/space.hpp" 6 | 7 | #include "tbb/task_scheduler_init.h" 8 | 9 | namespace dagSched{ 10 | 11 | bool test(std::istream &in, 12 | std::istream &dag_in, 13 | std::istream &aborts_in, const int m){ 14 | 15 | tbb::task_scheduler_init init(8); 16 | 17 | NP::Scheduling_problem problem{ 18 | NP::parse_file(in), 19 | NP::parse_dag_file(dag_in), 20 | NP::parse_abort_file(aborts_in), 21 | m}; 22 | 23 | // Set common analysis options 24 | NP::Analysis_options opts; 25 | opts.timeout = 0; 26 | opts.max_depth = 0; 27 | opts.early_exit = true; 28 | opts.num_buckets = problem.jobs.size(); 29 | opts.be_naive = 0; 30 | 31 | // Actually call the analysis engine 32 | auto space = NP::Global::State_space::explore(problem, opts); 33 | 34 | // Extract the analysis results 35 | // auto graph = std::ostringstream(); 36 | // auto rta = std::ostringstream(); 37 | 38 | if(space.is_schedulable() && METHOD_VERBOSE){ 39 | 40 | std::cout<<"\tBCRT: "; 41 | for (const auto& j : problem.jobs) { 42 | Interval finish = space.get_finish_times(j); 43 | std::cout<<"["<< j.get_task_id() << ", " << j.get_job_id() << "] "; 44 | std::cout<(0,(finish.from() - j.earliest_arrival()))<<" "; 45 | // std::cout<<(finish.until() - j.earliest_arrival())<<" "; 46 | } 47 | std::cout< V = taskset.tasks[x].getVertices(); 58 | // taskset.tasks[x].computeEFTs(); 59 | // taskset.tasks[x].computeLSTs(); 60 | 61 | for(int i=0; ic) + //Cost min 67 | ", " + std::to_string((int)V[i]->c) + //Cost max 68 | ", " + std::to_string((int)taskset.tasks[x].getDeadline()) + //Deadline 69 | ", " + std::to_string((int)taskset.tasks[x].getDeadline()) + "\n"; //Priority 70 | 71 | } 72 | } 73 | 74 | return task_set; 75 | 76 | } 77 | 78 | std::string convertDAGsToCsv(const Taskset& taskset){ 79 | std::string prec = "Predecessor TID, Predecessor JID, Successor TID, Successor JID\n"; 80 | for(int x=0; x V = taskset.tasks[x].getVertices(); 82 | for(int i=0; isucc.size(); ++j){ 84 | prec = prec + std::to_string(x) + ", " + std::to_string(i) + ", " + std::to_string(x) + ", " + std::to_string(V[i]->succ[j]->id) + "\n"; 85 | } 86 | } 87 | } 88 | 89 | return prec; 90 | } 91 | 92 | bool G_LP_FTP_Nasri2019_C(Taskset taskset, const int m){ 93 | 94 | 95 | std::string task_set = convertTasksetToCsv(taskset); 96 | std::string prec = convertDAGsToCsv(taskset); 97 | 98 | // std::cout< computeSxi(const DAGTask& tau_x, const int k ){ 8 | //topological order to priorities nodes 9 | std::vector topo_ord = tau_x.getTopologicalOrder(); 10 | auto V = tau_x.getVertices(); 11 | int idx = 0; 12 | bool is_succ = false; 13 | 14 | std::vector S; 15 | for(int i=0; i& ancst_i){ 32 | float max_R = 0; 33 | 34 | for(int j=0; j< ancst_i.size(); ++j){ 35 | if(ancst_i[j]->r > max_R) 36 | max_R = ancst_i[j]->r; 37 | } 38 | 39 | return max_R; 40 | } 41 | 42 | float computeWorloadIntra(const DAGTask& tau_x, const int k, const std::vector& ancst_k ){ 43 | std::vector S = computeSxi(tau_x, k); 44 | auto V = tau_x.getVertices(); 45 | 46 | float W_intra = 0; 47 | float R_part = 0; 48 | int idx = 0; 49 | for(int i=0; i< S.size(); ++i){ 50 | idx = S[i]; 51 | 52 | R_part = std::max( float(0) , V[idx]->r - computeLatestReadyTime(ancst_k) ); 53 | W_intra += std::min(V[idx]->c, R_part); 54 | } 55 | 56 | return W_intra; 57 | } 58 | 59 | float computeX(const DAGTask& tau_y, const DAGTask& tau_x, const int k, const std::vector& ancst_k, const float interval, const int m ){ 60 | auto V = tau_x.getVertices(); 61 | float ci_b = computeLatestReadyTime(ancst_k) + interval - tau_y.getWCW() / m; 62 | return std::max( float(0), ci_b ); 63 | } 64 | 65 | float computeTcin(const DAGTask& tau_y, const DAGTask& tau_x, const int k,const std::vector& ancst_k, const float interval, const int m ){ 66 | 67 | float X_y = computeX(tau_y, tau_x, k, ancst_k, interval, m); 68 | float W_y = tau_x.getWCW(); 69 | float T_y = tau_x.getPeriod(); 70 | 71 | float ci = interval - (T_y - tau_y.R) - std::floor ( X_y / T_y ) * T_y - W_y / m; 72 | return std::max( float(0), ci); 73 | 74 | } 75 | 76 | float computeCR(const DAGTask& tau_y, const DAGTask& tau_x, const int k, const std::vector& ancst_k, const float interval, const int m ){ 77 | auto V_x = tau_x.getVertices(); 78 | auto V_y = tau_y.getVertices(); 79 | float A = 0; 80 | 81 | for(int i=0; ic, std::max(float(0), V_y[i]->r - computeLatestReadyTime(ancst_k))); 83 | 84 | return std::min (m * computeTcin(tau_y, tau_x, k, ancst_k, interval, m) , A); 85 | } 86 | 87 | float computeWorloadInter(const Taskset& taskset, const int x, const int i, const std::vector& ancst_i, const float interval, const int m){ 88 | 89 | //for all hp of tau_x 90 | float W_inter = 0; 91 | float T_y = 0, W_y = 0, t_cin_y = 0, CR_y = 0, X_y = 0; 92 | for(int y=0; y < x; ++y){ 93 | 94 | T_y = taskset.tasks[y].getPeriod(); 95 | W_y = taskset.tasks[y].getWCW(); 96 | t_cin_y = computeTcin(taskset.tasks[y], taskset.tasks[x], i, ancst_i, interval, m); 97 | X_y = computeX(taskset.tasks[y], taskset.tasks[x], i, ancst_i, interval, m); 98 | CR_y = computeCR(taskset.tasks[y], taskset.tasks[x], i, ancst_i, t_cin_y, m); 99 | 100 | W_inter += CR_y + std::floor( X_y / T_y ) * W_y + W_y; 101 | 102 | //NB: doesn't make much sense to account for all the workload of W_y: here's the pessimism 103 | } 104 | 105 | return W_inter; 106 | } 107 | 108 | bool GP_FP_DM_Pathan2017_C(Taskset taskset, const int m){ 109 | 110 | std::sort(taskset.tasks.begin(), taskset.tasks.end(), deadlineMonotonicSorting); 111 | 112 | for(int x=0; x topo_ord = taskset.tasks[x].getTopologicalOrder(); 115 | auto V = taskset.tasks[x].getVertices(); 116 | 117 | std::vector R_old (V.size(), 0); 118 | std::vector R (V.size(), 0); 119 | 120 | // compute the response of a subtask in topological order 121 | for(int idx=0, i; idx ancst_i = taskset.tasks[x].getSubTaskAncestors(i); 125 | 126 | R_old[i] = V[i]->c; 127 | V[i]->r = V[i]->c; 128 | 129 | if(R_old[i] > taskset.tasks[x].getDeadline()) 130 | return false; 131 | 132 | bool init = true; 133 | float W_intra = 0, W_inter = 0; 134 | while(!areEqual(R[i], R_old[i]) && R[i] <= taskset.tasks[x].getDeadline()){ 135 | if(!init){ 136 | R_old[i] = R[i]; 137 | R[i] = 0; 138 | } 139 | 140 | W_inter = computeWorloadInter(taskset, x, i, ancst_i, R_old[i], m); 141 | W_intra = computeWorloadIntra(taskset.tasks[x], i, ancst_i); 142 | 143 | R[i] += computeLatestReadyTime(V[i]->pred) + (1. / m) * (W_intra + W_inter) + V[i]->c; 144 | 145 | init = false; 146 | if(R[i] < R_old[i]) 147 | break; 148 | } 149 | 150 | if(R[i] > taskset.tasks[x].getDeadline()) 151 | return false; 152 | V[i]->r = R[i]; 153 | } 154 | 155 | // the response time of the task is the max response time of one of its nodes 156 | taskset.tasks[x].R = 0; 157 | for(int i=0; ir > taskset.tasks[x].R) 159 | taskset.tasks[x].R = V[i]->r; 160 | } 161 | 162 | if (taskset.tasks[x].R > taskset.tasks[x].getDeadline()) 163 | return false; 164 | 165 | } 166 | return true; 167 | 168 | } 169 | 170 | } -------------------------------------------------------------------------------- /src/tests/Qamhieh2013.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | #include "dagSched/scheduling_utils.h" 3 | 4 | // "Global EDF scheduling of directed acyclic graphs on multiprocessor systems", Qamhieh et al. (RTNS 2013) 5 | 6 | namespace dagSched{ 7 | 8 | /* Theorem 6 in the paper */ 9 | bool GP_FP_EDF_Qamhieh2013_C(Taskset taskset, const int m){ 10 | 11 | float cumulativeDBF = 0; 12 | float cumulativeCarryIn = 0; 13 | 14 | for(auto& task:taskset.tasks){ 15 | if(!(task.getDeadline() <= task.getPeriod())) 16 | FatalError("This test requires constrained deadline tasks"); 17 | 18 | task.computeLocalOffsets(); 19 | task.computeLocalDeadlines(); 20 | } 21 | 22 | for(int x=0; xlocalD, 27 | taskset.tasks[y].getPeriod(), 28 | v->c )); 29 | 30 | if(x != y){ 31 | for(const auto& v: taskset.tasks[y].getVertices()) 32 | cumulativeCarryIn += std::fmin(v->c, std::fmax(0, v->localD)); 33 | } 34 | } 35 | 36 | if(cumulativeDBF + cumulativeCarryIn > taskset.tasks[x].getDeadline()) 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/tests/Serrano2016.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | //Maria A Serrano et al. “Response-time analysis of DAG tasks under fixed priority scheduling with limited preemptions” (DATE 2016) 4 | 5 | namespace dagSched{ 6 | 7 | float computePreemptionNumberUpperBound(const Taskset& taskset, const int x, const float interval){ 8 | float h = 0; 9 | 10 | //for all high priority tasks 11 | for(int y=0; y max_over_taus; 20 | 21 | //for all lower priority tasks 22 | for(int y=x+1; y< taskset.tasks.size(); ++y){ 23 | std::vector max_over_vs; 24 | auto Vy = taskset.tasks[y].getVertices(); 25 | 26 | for(int i=0; i < Vy.size(); ++i){ 27 | max_over_vs.push_back(Vy[i]->c); 28 | } 29 | 30 | std::sort(max_over_vs.begin(), max_over_vs.end(), std::greater()); 31 | for(int i=0; i < m && i < max_over_vs.size(); ++i) 32 | max_over_taus.push_back(max_over_vs[i]); 33 | } 34 | 35 | float delta = 0; 36 | std::sort(max_over_taus.begin(), max_over_taus.end(), std::greater()); 37 | for(int i=0; i < m && i < max_over_taus.size(); ++i) 38 | delta += max_over_taus[i]; 39 | 40 | return delta; 41 | } 42 | 43 | float blockingWorkload(const Taskset& taskset, const int x , const float interval, const float m){ 44 | 45 | float delta_m = computeDeltaM(taskset, x, interval, m); 46 | float delta_m_minus_1 = computeDeltaM(taskset, x, interval, m -1); 47 | float np_x = computePreemptionNumberUpperBound(taskset, x, interval); 48 | 49 | return delta_m + np_x * delta_m_minus_1; 50 | 51 | } 52 | 53 | bool GP_LP_FTP_Serrano16_C(Taskset taskset, const int m){ 54 | std::sort(taskset.tasks.begin(), taskset.tasks.end(), deadlineMonotonicSorting); 55 | 56 | std::vector R_old (taskset.tasks.size(), 0); 57 | std::vector R (taskset.tasks.size(), 0); 58 | 59 | for(int i=0; i taskset.tasks[i].getDeadline()) 77 | return false; 78 | 79 | if(!init){ 80 | R_old[i] = R[i]; 81 | R[i] = 0; 82 | } 83 | 84 | //for all hp 85 | interf = 0; 86 | for(int j=0; j(R[i], R_old[i])) 101 | at_least_one_update = true; 102 | 103 | if (R[i] > taskset.tasks[i].getDeadline()) 104 | return false; 105 | } 106 | init = false; 107 | } 108 | return true; 109 | } 110 | 111 | } -------------------------------------------------------------------------------- /src/tests/Zahaf2019.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | #ifdef ZAHAF2019 4 | 5 | #include "task/task.hpp" 6 | #include "gramm/hdag_driver.hpp" 7 | #include "code_gen/taskset_code.hpp" 8 | #include "platform/platform.hpp" 9 | #include "analysis/hpc_dag/analysis.hpp" 10 | 11 | namespace dagSched{ 12 | 13 | bool P_LP_EDF_Zahaf2019_C(const Taskset& taskset, const int m){ 14 | 15 | std::ofstream output_file; 16 | std::string filename = "cur_zahaf2019.txt"; 17 | output_file.open (filename); 18 | 19 | int prev_v = 0; 20 | 21 | for(int x=0; x V = taskset.tasks[x].getVertices(); 23 | for(int i=0;iid+1)+prev_v<<" (C="<c<<", TAG=CPU);\n"; 25 | 26 | output_file<<"Graph tau"<succ.size(); ++j) 31 | output_file<<"precond( J"<<(V[i]->id+1)+prev_v<<", J"<<(V[i]->succ[j]->id+1)+prev_v<<");\n"; 32 | output_file<<"};\n"; 33 | 34 | prev_v += V.size(); 35 | } 36 | 37 | 38 | // for(int x=0; xparse(filename); 51 | 52 | delete driver; 53 | 54 | return res; 55 | } 56 | 57 | } 58 | 59 | #endif -------------------------------------------------------------------------------- /src/tests/tests_common.cpp: -------------------------------------------------------------------------------- 1 | #include "dagSched/tests.h" 2 | 3 | namespace dagSched{ 4 | 5 | bool deadlineMonotonicSorting (const DAGTask& tau_x, const DAGTask& tau_y) { 6 | return (tau_x.getDeadline() < tau_y.getDeadline()); 7 | } 8 | 9 | bool sortPairProcInc(const std::pair& a, const std::pair& b){ 10 | return a.second < b.second; 11 | } 12 | 13 | bool sortPairProcDec(const std::pair& a, const std::pair& b){ 14 | return a.second > b.second; 15 | } 16 | 17 | std::vector getCandidatesProcInOrder(const std::vector& proc_util, const float cur_util, const PartitioningCoresOrder_t& c_order){ 18 | 19 | std::vector candidates_cores; 20 | 21 | std::vector> proc_val; 22 | 23 | int min_proc_util_diff = 1; 24 | int min_proc_util = 1; 25 | int min_idx = -1; 26 | 27 | switch (c_order){ 28 | case PartitioningCoresOrder_t::FIRST_FIT: 29 | //first processor that can accomodate the current util 30 | for(int p=0; p= cur_util ) // can accomodate 32 | candidates_cores.push_back(p); 33 | // no sorting, first fit 34 | break; 35 | case PartitioningCoresOrder_t::BEST_FIT: 36 | //processor that has the free slot most similar to the current util 37 | for(int p=0; p= cur_util // can accomodate 39 | && 1 - proc_util[p] - cur_util < min_proc_util_diff ) // the difference is smaller than in other processor (best fit) 40 | proc_val.push_back(std::make_pair(p, 1- proc_util[p] - cur_util)); 41 | std::sort(proc_val.begin(), proc_val.end(), sortPairProcInc); // sorting for increasing difference (best fit) 42 | for(const auto& pv:proc_val) 43 | candidates_cores.push_back(pv.first); 44 | break; 45 | 46 | case PartitioningCoresOrder_t::WORST_FIT: 47 | //processor that has the biggest free slot 48 | for(int p=0; p= cur_util // can accomodate 50 | && proc_util[p] < min_proc_util ) // is the one with least used utilization (worst-fit) 51 | proc_val.push_back(std::make_pair(p, 1 - proc_util[p])); 52 | std::sort(proc_val.begin(), proc_val.end(), sortPairProcDec); // sorting for decreasing left capacity (worst fit) 53 | for(const auto& pv:proc_val) 54 | candidates_cores.push_back(pv.first); 55 | break; 56 | 57 | } 58 | return candidates_cores; 59 | } 60 | 61 | class node_infos{ 62 | public: 63 | int task_id = 0; 64 | int v_id = 0; 65 | float utilization = 0; 66 | float density = 0; 67 | 68 | void print(){ 69 | std::cout<<"x: "< b.utilization; 75 | } 76 | 77 | bool sortDensDec(const node_infos& a, const node_infos& b){ 78 | return a.density > b.density; 79 | } 80 | 81 | bool sortUtilDecDensDec(const node_infos& a, const node_infos& b){ 82 | if(areEqual(a.utilization, b.utilization)) 83 | return a.density > b.density; 84 | return a.utilization > b.utilization; 85 | } 86 | 87 | bool sortDensDecUtilDec(const node_infos& a, const node_infos& b){ 88 | if(areEqual(a.density, b.density)) 89 | return a.utilization > b.utilization; 90 | return a.density > b.density ; 91 | } 92 | 93 | bool WorstFitProcessorsAssignment(Taskset& taskset, const int m){ 94 | 95 | std::vector proc_util (m,0); 96 | float min_proc_util = 1; 97 | int min_idx = -1; 98 | 99 | std::vector taskset_nodes; 100 | 101 | for(int x=0; x V = taskset.tasks[x].getVertices(); 103 | for(int i=0; ic / taskset.tasks[x].getPeriod(); 109 | 110 | taskset_nodes.push_back(n); 111 | } 112 | } 113 | 114 | std::sort(taskset_nodes.begin(), taskset_nodes.end(), sortUtilDecDensDec); 115 | 116 | for(int i=0; i= taskset_nodes[i].utilization // can accomodate 121 | && proc_util[p] < min_proc_util){ // is the one with least used utilization (worst-fit) 122 | min_proc_util = proc_util[p]; 123 | min_idx = p; 124 | } 125 | } 126 | 127 | if(min_idx == -1) 128 | return false; 129 | 130 | SubTask *v = taskset.tasks[taskset_nodes[i].task_id].getVertices()[taskset_nodes[i].v_id]; 131 | v->core = min_idx; 132 | proc_util[min_idx] += taskset_nodes[i].utilization; 133 | 134 | } 135 | 136 | return true; 137 | } 138 | 139 | bool BestFitProcessorsAssignment(Taskset& taskset, const int m){ 140 | 141 | std::vector proc_util (m,0); 142 | float min_proc_util = 1; 143 | int min_idx = -1; 144 | 145 | float cur_util; 146 | for(int x=0; x V = taskset.tasks[x].getVertices(); 148 | for(int i=0; ic / taskset.tasks[x].getPeriod(); 150 | 151 | min_proc_util = 1; 152 | min_idx = -1; 153 | for(int p=0; p= cur_util // can accomodate 156 | && 1 - proc_util[p] - cur_util < min_proc_util){ // is the one with least used utilization (worst-fit) 157 | min_proc_util = 1 - proc_util[p] - cur_util; 158 | min_idx = p; 159 | } 160 | } 161 | 162 | if(min_idx == -1) 163 | return false; 164 | 165 | V[i]->core = min_idx; 166 | proc_util[min_idx] += cur_util; 167 | } 168 | 169 | // std::cout<> separateOnComma(const std::string& line){ 38 | std::string left = "", rigth = ""; 39 | bool read_equal = false; 40 | std::vector> pairs; 41 | for(int i=0; i"); 76 | size_t box = line.find("box"); 77 | size_t start_node = line.find("["); 78 | size_t end_node = line.find("]"); 79 | 80 | if( start_graph != std::string::npos) 81 | line_info.lineType = DOTLine_t::DOT_BEGIN; 82 | else if( end_graph != std::string::npos) 83 | line_info.lineType = DOTLine_t::DOT_END; 84 | else if( arrow != std::string::npos){ 85 | line_info.lineType = DOTLine_t::DOT_EDGE; 86 | 87 | std::string id_from_str = line.substr(0, arrow); 88 | line_info.id_from = std::stoi( id_from_str ); 89 | 90 | std::string id_to_str = line.substr(arrow + 2, line.find(";") - (arrow + 2)); 91 | line_info.id_to = std::stoi( id_to_str ); 92 | } 93 | else if( box != std::string::npos){ 94 | line_info.lineType = DOTLine_t::DAG_INFO; 95 | std::string brackets_content = line.substr(start_node + 1 , end_node - (start_node + 1)); 96 | auto pairs = separateOnComma(brackets_content); 97 | for(auto p:pairs){ 98 | if(p.first == "D") 99 | line_info.deadline = std::stof(p.second); 100 | if(p.first == "T") 101 | line_info.period = std::stof(p.second); 102 | } 103 | } 104 | else if( start_node != std::string::npos && end_node != std::string::npos){ 105 | line_info.lineType = DOTLine_t::DOT_NODE; 106 | 107 | std::string node_id_str = line.substr(0, start_node); 108 | line_info.id = std::stoi(node_id_str); 109 | 110 | std::string brackets_content = line.substr(start_node + 1 , end_node - (start_node + 1)); 111 | auto pairs = separateOnComma(brackets_content); 112 | for(auto p:pairs){ 113 | if(p.first == "label") 114 | line_info.wcet = std::stof(p.second); 115 | if(p.first == "p") 116 | line_info.p = std::stof(p.second); 117 | if(p.first == "s") 118 | line_info.s = std::stof(p.second); 119 | } 120 | } 121 | else 122 | line_info.lineType = DOTLine_t::VOID_LINE; 123 | 124 | return line_info; 125 | } --------------------------------------------------------------------------------