FonsecaNelis.java 11.7 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;
24
import mvd.jester.model.SystemManagerInterface;
25
import mvd.jester.model.Task;
26
import mvd.jester.model.TreeJob;
27
import mvd.jester.utils.DagUtils;
28
import mvd.jester.priority.DeadlineMonotonic;
29 30
import mvd.jester.priority.PriorityManager;
import mvd.jester.priority.RateMonotonic;
31
import mvd.jester.utils.BinaryDecompositionTree;
32 33
import mvd.jester.utils.BinaryDecompositionTree.Node;
import mvd.jester.utils.BinaryDecompositionTree.NodeType;
34 35 36 37 38

public class FonsecaNelis extends AbstractTest<DagTask> {

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

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

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

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

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

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

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

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

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

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

        return carryOutWorkload;
    }


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

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

125 126
    private Set<TreeJob> getMaximumParallelism(final Node<TreeJob> node) {
        final NodeType nodeType = node.getNodeType();
127
        if (nodeType.equals(NodeType.PAR)) {
128 129
            final Set<TreeJob> left = getMaximumParallelism(node.getLeftNode());
            final Set<TreeJob> right = getMaximumParallelism(node.getRightNode());
130 131
            return Sets.union(left, right);
        } else if (nodeType.equals(NodeType.SEQ)) {
132 133
            final Set<TreeJob> left = getMaximumParallelism(node.getLeftNode());
            final Set<TreeJob> right = getMaximumParallelism(node.getRightNode());
134 135 136 137 138 139 140 141 142 143
            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<>();
144
            }
Michael Schmid committed
145
        }
146 147
    }

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

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

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

164
            final double selfInterference = getSelfInterference(task);
165

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

        } while (responseTime != previousResponseTime);

        return responseTime;
    }

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

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


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

        return carryInAndOutWorkload + bodyWorkload;
    }

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

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

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

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

        return workload;
    }

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

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

243
            workload += Math.max(Math.min(width, s.getWidth()), 0) * s.getHeight();
244 245
        }

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

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

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

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

270
            workload += Math.max(Math.min(width, s.getWidth()), 0) * s.getHeight();
271 272
        }

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

        return Math.min(improvedWorkload, workload);
    }

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

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

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


}