FonsecaNelis.java 11.6 KB
Newer Older
1 2 3
package mvd.jester.tests;

import java.math.RoundingMode;
4
import java.util.Arrays;
5 6 7
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
8
import java.util.LinkedHashSet;
9 10
import java.util.List;
import java.util.Map;
11
import java.util.Optional;
12 13
import java.util.Set;
import com.google.common.collect.Lists;
14
import com.google.common.collect.Sets;
15
import com.google.common.math.LongMath;
Michael Schmid committed
16 17
import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge;
18 19 20
import mvd.jester.info.SchedulingInfo;
import mvd.jester.info.TerminationInfo;
import mvd.jester.model.DagTask;
Michael Schmid committed
21
import mvd.jester.model.Job;
22 23
import mvd.jester.model.Segment;
import mvd.jester.model.SortedTaskSet;
Michael Schmid committed
24
import mvd.jester.model.SystemManager;
25
import mvd.jester.model.Task;
26
import mvd.jester.model.TreeJob;
27
import mvd.jester.utils.DagUtils;
28 29
import mvd.jester.priority.PriorityManager;
import mvd.jester.priority.RateMonotonic;
30
import mvd.jester.utils.BinaryDecompositionTree;
31 32
import mvd.jester.utils.BinaryDecompositionTree.Node;
import mvd.jester.utils.BinaryDecompositionTree.NodeType;
33 34 35 36 37

public class FonsecaNelis extends AbstractTest<DagTask> {

    private final Map<Task, TerminationInfo> responseTimes;
    private final PriorityManager priorityManager;
38
    private final Map<Task, Set<Segment>> carryOutSegments;
39

Michael Schmid committed
40 41
    public FonsecaNelis(final SystemManager manager) {
        super(manager);
42 43
        this.responseTimes = new HashMap<>();
        this.priorityManager = new RateMonotonic();
44
        this.carryOutSegments = new HashMap<>();
45 46 47 48 49 50 51 52
    }

    @Override
    public PriorityManager getPriorityManager() {
        return priorityManager;
    }

    @Override
53
    public SchedulingInfo runSchedulabilityCheck(final SortedTaskSet<DagTask> tasks) {
54
        carryOutSegments.clear();
55
        responseTimes.clear();
Michael Schmid committed
56
        createNFJandDecompositionTree(tasks);
57 58 59
        for (final DagTask t : tasks) {
            final long responseTime = calculateResponseTime(tasks, t);
            responseTimes.put(t, new TerminationInfo(t.getDeadline(), responseTime));
60 61
        }

62
        return new SchedulingInfo(responseTimes.values());
63 64
    }

65 66 67
    private void createNFJandDecompositionTree(final SortedTaskSet<DagTask> tasks) {
        for (final DagTask t : tasks) {
            final DirectedAcyclicGraph<Job, DefaultEdge> jobDag = t.getJobDag();
68

69 70 71
            final DirectedAcyclicGraph<Job, DefaultEdge> nfjJobDag =
                    DagUtils.createNFJGraph(jobDag);
            final BinaryDecompositionTree<Job> tree = DagUtils.createDecompositionTree(nfjJobDag);
72

73
            carryOutSegments.put(t, constructCarryOutDistribution(nfjJobDag, tree));
74 75 76
        }
    }

77
    private Set<Segment> constructCarryOutDistribution(
78 79
            final DirectedAcyclicGraph<Job, DefaultEdge> nfjDag,
            final BinaryDecompositionTree<Job> tree) {
Michael Schmid committed
80
        // List statt Set
81 82
        final Set<Segment> carryOutWorkload = new LinkedHashSet<>();
        final BinaryDecompositionTree<TreeJob> modifiedTree = transformTree(tree);
83 84 85

        boolean isEmpty = false;
        do {
86 87
            final Set<TreeJob> parallelJobs = getMaximumParallelism(modifiedTree.getRootNode());
            final Optional<TreeJob> min =
88 89
                    parallelJobs.stream().min((p1, p2) -> Long.compare(p1.getWcet(), p2.getWcet()));
            if (min.isPresent()) {
90
                final long width = min.get().getWcet();
91
                carryOutWorkload.add(new Segment(width, parallelJobs.size()));
92
                for (final TreeJob p : parallelJobs) {
93
                    p.setWcet(p.getWcet() - width);
94
                }
95 96 97 98 99 100 101 102 103 104
            } else {
                break;
            }
            isEmpty = parallelJobs.isEmpty();
        } while (!isEmpty);

        return carryOutWorkload;
    }


105 106 107 108
    private BinaryDecompositionTree<TreeJob> transformTree(
            final BinaryDecompositionTree<Job> tree) {
        final BinaryDecompositionTree<TreeJob> modifiedTree = new BinaryDecompositionTree<>();
        final Node<TreeJob> root = transformNode(null, tree.getRootNode());
109 110 111 112
        modifiedTree.setRoot(root);
        return modifiedTree;
    }

113
    private Node<TreeJob> transformNode(final Node<TreeJob> parent, final Node<Job> node) {
114 115 116
        if (node.getNodeType().equals(NodeType.LEAF)) {
            return new Node<TreeJob>(parent, new TreeJob(node.getObject()));
        } else {
117
            final Node<TreeJob> modifiedNode = new Node<TreeJob>(parent, node.getNodeType());
118 119 120 121 122 123
            modifiedNode.setLeftNode(transformNode(modifiedNode, node.getLeftNode()));
            modifiedNode.setRightNode(transformNode(modifiedNode, node.getRightNode()));
            return modifiedNode;
        }
    }

124 125
    private Set<TreeJob> getMaximumParallelism(final Node<TreeJob> node) {
        final NodeType nodeType = node.getNodeType();
126
        if (nodeType.equals(NodeType.PAR)) {
127 128
            final Set<TreeJob> left = getMaximumParallelism(node.getLeftNode());
            final Set<TreeJob> right = getMaximumParallelism(node.getRightNode());
129 130
            return Sets.union(left, right);
        } else if (nodeType.equals(NodeType.SEQ)) {
131 132
            final Set<TreeJob> left = getMaximumParallelism(node.getLeftNode());
            final Set<TreeJob> right = getMaximumParallelism(node.getRightNode());
133 134 135 136 137 138 139 140 141 142
            if (left.size() >= right.size()) {
                return left;
            } else {
                return right;
            }
        } else {
            if (node.getObject().getWcet() > 0) {
                return new HashSet<>(Arrays.asList(node.getObject()));
            } else {
                return new HashSet<>();
143
            }
Michael Schmid committed
144
        }
145 146
    }

147 148
    private long calculateResponseTime(final SortedTaskSet<DagTask> tasks, final DagTask task) {
        final long criticalPath = task.getCriticalPath();
149 150 151 152 153 154
        long responseTime = criticalPath;
        long previousResponseTime = 0;

        do {
            previousResponseTime = responseTime;
            double taskInterference = 0;
155
            for (final DagTask t : tasks) {
156 157 158 159 160
                if (t.getPeriod() < task.getPeriod()) {
                    taskInterference += getTaskInterference(t, responseTime);
                }
            }

Michael Schmid committed
161
            taskInterference /= manager.getNumberOfProcessors();
162

163
            final double selfInterference = getSelfInterference(task);
164

165
            final long totalInterference = (long) Math.floor(taskInterference + selfInterference);
166 167 168 169 170 171 172
            responseTime = criticalPath + totalInterference;

        } while (responseTime != previousResponseTime);

        return responseTime;
    }

173 174 175
    private double getTaskInterference(final DagTask task, final long interval) {
        final long period = task.getPeriod();
        final long criticalPath = task.getCriticalPath();
176
        final long numberOfPeriods =
177
                LongMath.divide(interval - criticalPath, period, RoundingMode.FLOOR);
178
        final long carryInAndOutInterval = interval - Math.max(0, numberOfPeriods) * period;
179
        final long numberOfBodyJobs =
180 181
                LongMath.divide(interval - carryInAndOutInterval, period, RoundingMode.FLOOR);

182
        final long bodyWorkload = Math.max(0, numberOfBodyJobs) * task.getWorkload();
183 184


185
        final long carryInAndOutWorkload = getCarryInAndOutWorkload(task,
186
                task.getWorkloadDistribution(), carryOutSegments.get(task), carryInAndOutInterval);
187 188 189 190

        return carryInAndOutWorkload + bodyWorkload;
    }

191 192 193
    private long getCarryInAndOutWorkload(final DagTask task,
            final Set<Segment> carryInDistribution, final Set<Segment> carryOutDistribution,
            final long carryInAndOutPeriod) {
194 195 196
        long workload = getCarryOutWorkload(task, carryOutDistribution, carryInAndOutPeriod);
        long carryInPeriod = task.getPeriod() - responseTimes.get(task).getResponseTime();
        long carryOutPeriod = 0;
Michael Schmid committed
197 198
        final List<Segment> reverseCarryInList = Lists.newArrayList(carryInDistribution);
        Collections.reverse(reverseCarryInList);
199

Michael Schmid committed
200
        for (final Segment s : reverseCarryInList) {
201 202
            carryInPeriod += s.getJobWcet();
            carryOutPeriod = carryInAndOutPeriod - carryInPeriod;
203 204 205 206
            final long carryInWorkload =
                    getCarryInWorkload(task, carryInDistribution, carryInPeriod);
            final long carryOutWorkload =
                    getCarryOutWorkload(task, carryOutDistribution, carryOutPeriod);
207 208 209 210 211 212 213
            workload = Math.max(workload, carryInWorkload + carryOutWorkload);
        }

        workload = Math.max(workload,
                getCarryInWorkload(task, carryInDistribution, carryInAndOutPeriod));
        carryOutPeriod = 0;

214
        for (final Segment s : carryOutDistribution) {
215 216
            carryOutPeriod += s.getJobWcet();
            carryInPeriod = carryInAndOutPeriod - carryOutPeriod;
217 218 219 220
            final long carryInWorkload =
                    getCarryInWorkload(task, carryInDistribution, carryInPeriod);
            final long carryOutWorkload =
                    getCarryOutWorkload(task, carryOutDistribution, carryOutPeriod);
221 222 223 224 225 226
            workload = Math.max(workload, carryInWorkload + carryOutWorkload);
        }

        return workload;
    }

227 228
    private long getCarryOutWorkload(final DagTask task, final Set<Segment> carryOutDistribution,
            final long carryOutPeriod) {
229
        long workload = 0;
230 231
        final long taskWorkload = task.getWorkload();
        final long criticalPath = task.getCriticalPath();
232
        final List<Segment> distributionList = Lists.newArrayList(carryOutDistribution);
233 234

        for (int i = 0; i < distributionList.size(); ++i) {
235
            final Segment s = distributionList.get(i);
236 237 238 239
            long weightOfPreviousSegments = 0;
            for (int j = 0; j < i; ++j) {
                weightOfPreviousSegments += distributionList.get(j).getJobWcet();
            }
240
            final long width = carryOutPeriod - weightOfPreviousSegments;
241 242 243 244

            workload += Math.max(Math.min(width, s.getJobWcet()), 0) * s.getNumberOfJobs();
        }

245 246
        final long improvedWorkloadFromTask =
                taskWorkload - Math.max(0, criticalPath - carryOutPeriod);
Michael Schmid committed
247 248
        final long improvedWorkloadFromProcessors =
                carryOutPeriod * manager.getNumberOfProcessors();
249

250 251
        return Math.min(Math.min(improvedWorkloadFromTask, improvedWorkloadFromProcessors),
                workload);
252 253
    }

254 255
    private long getCarryInWorkload(final DagTask task, final Set<Segment> carryInDistribution,
            final long carryInPeriod) {
256
        long workload = 0;
257 258 259
        final long period = task.getPeriod();
        final long responseTime = responseTimes.get(task).getResponseTime();
        final List<Segment> distributionList = Lists.newArrayList(carryInDistribution);
260

Michael Schmid committed
261 262
        for (int b = 0; b < carryInDistribution.size(); ++b) {
            final Segment s = distributionList.get(b);
263
            long weightOfRemainingSegments = 0;
Michael Schmid committed
264 265
            for (int p = b + 1; p < carryInDistribution.size(); ++p) {
                weightOfRemainingSegments += distributionList.get(p).getJobWcet();
266
            }
267
            final long width = carryInPeriod - period + responseTime - weightOfRemainingSegments;
268 269 270 271

            workload += Math.max(Math.min(width, s.getJobWcet()), 0) * s.getNumberOfJobs();
        }

Michael Schmid committed
272 273
        final long improvedWorkload = Math.max(carryInPeriod - (period - responseTime), 0)
                * manager.getNumberOfProcessors();
274 275 276 277

        return Math.min(improvedWorkload, workload);
    }

278 279 280
    private double getSelfInterference(final DagTask task) {
        final long criticalPath = task.getCriticalPath();
        final long workload = task.getWorkload();
281

Michael Schmid committed
282
        return (double) (workload - criticalPath) / manager.getNumberOfProcessors();
283 284 285 286 287 288 289 290 291
    }

    @Override
    public String getName() {
        return "FonsecaNelis";
    }


}