From 4e934ca9edd35a53cb42efe2ac159fa4ed7c7b5f Mon Sep 17 00:00:00 2001 From: Michael Schmid Date: Sun, 24 May 2020 16:14:51 +0200 Subject: [PATCH] FonsecaNelis test works now --- src/main/java/mvd/jester/App.java | 2 +- src/main/java/mvd/jester/model/DagTask.java | 99 +++++++++++++++++++++------------------------------------------------------------------------------ src/main/java/mvd/jester/model/TreeJob.java | 32 ++++++++++++++++++++++++++++++++ src/main/java/mvd/jester/tests/FonsecaNelis.java | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------- src/main/java/mvd/jester/utils/BinaryDecompositionTree.java | 5 +++-- src/test/java/mvd/jester/model/TestDagUtils.java | 4 +++- 6 files changed, 142 insertions(+), 99 deletions(-) create mode 100644 src/main/java/mvd/jester/model/TreeJob.java diff --git a/src/main/java/mvd/jester/App.java b/src/main/java/mvd/jester/App.java index 8d05e8c..e95aa03 100644 --- a/src/main/java/mvd/jester/App.java +++ b/src/main/java/mvd/jester/App.java @@ -22,7 +22,7 @@ public class App { TestEnvironment te = new TestEnvironment(); Set>> tests = te.registerTests( - Arrays.asList(new SchmidMottok(p), new MelaniButtazzo(p), new FonsecaNelis(p))); + Arrays.asList(new SchmidMottok(p), /* new MelaniButtazzo(p), */ new FonsecaNelis(p))); te.runExperiments(builder, tests, p, 500); } diff --git a/src/main/java/mvd/jester/model/DagTask.java b/src/main/java/mvd/jester/model/DagTask.java index 893a791..537e84c 100644 --- a/src/main/java/mvd/jester/model/DagTask.java +++ b/src/main/java/mvd/jester/model/DagTask.java @@ -1,6 +1,7 @@ package mvd.jester.model; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; @@ -188,6 +189,12 @@ public class DagTask implements Task { forkNodes.add(j); } } + + for (Job j : forkNodes) { + if (jobDag.outDegreeOf(j) <= 1) { + int test = 3; + } + } } public static DirectedAcyclicGraph createNFJGraph( @@ -259,13 +266,14 @@ public class DagTask implements Task { if (source.isPresent() && sink.isPresent()) { Job current = source.get(); - DagUtils.treeDec(jobDag, null, current, tree, forkNodes, joinNodes, sink.get()); + DagUtils.constructTree(jobDag, null, current, tree, forkNodes, joinNodes, + sink.get()); } return tree; } - private static Node treeDec(DirectedAcyclicGraph jobDag, + private static Node constructTree(DirectedAcyclicGraph jobDag, Node parentNode, Job currentJob, BinaryDecompositionTree tree, LinkedList forkVertices, LinkedList joinVertices, Job sinkJob) { if (forkVertices.contains(currentJob)) { @@ -282,7 +290,7 @@ public class DagTask implements Task { Node seqJoinNode = seqForkNode.setRightNode(new Node(seqForkNode, NodeType.SEQ)); - Node subTreeOfJoin = treeDec(jobDag, seqJoinNode, joinJob, tree, + Node subTreeOfJoin = constructTree(jobDag, seqJoinNode, joinJob, tree, forkVertices, joinVertices, sinkJob); seqJoinNode.setRightNode(subTreeOfJoin); @@ -296,11 +304,14 @@ public class DagTask implements Task { Node successorParent = parContinuationNode; List successors = Graphs.successorListOf(jobDag, currentJob); + if (successors.size() == 1) { + int test = 3; + } // create leftSide of joinNode for (int i = 0; i < successors.size(); ++i) { Job succ = successors.get(i); - Node thisNode = treeDec(jobDag, successorParent, succ, tree, forkVertices, - joinVertices, sinkJob); + Node thisNode = constructTree(jobDag, successorParent, succ, tree, + forkVertices, joinVertices, sinkJob); if (i == successors.size() - 1) { successorParent.setRightNode(thisNode); } else if (i == successors.size() - 2) { @@ -323,7 +334,7 @@ public class DagTask implements Task { tree.setRoot(seqJobNode); } seqJobNode.setLeftNode(new Node(seqJobNode, currentJob)); - Node contNode = treeDec(jobDag, seqJobNode, successor, tree, + Node contNode = constructTree(jobDag, seqJobNode, successor, tree, forkVertices, joinVertices, sinkJob); seqJobNode.setRightNode(contNode); return seqJobNode; @@ -337,69 +348,6 @@ public class DagTask implements Task { } } - // private static Node constructTree(DirectedAcyclicGraph jobDag, - // Node parent, Job currentFork, BinaryDecompositionTree tree, - // LinkedList forkVertices, LinkedList joinVertices, Job sink) { - // if (forkVertices.contains(currentFork)) { - // Job join = findJoin(jobDag, currentFork, sink, joinVertices); - - // Node forkNode = new Node(parent, NodeType.SEQ); - // if (tree.isEmpty()) { - // tree.setRoot(forkNode); - // } - // forkNode.setLeftNode(new Node(forkNode, currentFork)); - // final Node continuationNode; - // if (!tree.contains(join)) { - // forkNode.setRightNode(new Node(forkNode, NodeType.SEQ)); - // Node joinNode = forkNode.getRightNode(); - // Iterator successorIterator = - // Graphs.successorListOf(jobDag, join).iterator(); - // if (successorIterator.hasNext()) { - // Job successor = successorIterator.next(); - // if (!tree.contains(successor)) { - // joinNode.setRightNode(new Node<>(joinNode, NodeType.SEQ)); - // Node successorNode = joinNode.getRightNode(); - // successorNode.setLeftNode(new Node<>(successorNode, join)); - // Node subTree = constructTree(jobDag, successorNode, successor, - // tree, forkVertices, joinVertices, sink); - // successorNode.setRightNode(subTree); - // } else { - // joinNode.setRightNode(new Node<>(joinNode, join)); - // } - // } else { - // joinNode.setRightNode(new Node<>(joinNode, join)); - // } - // joinNode.setLeftNode(new Node<>(joinNode, NodeType.PAR)); - // continuationNode = joinNode.getLeftNode(); - // } else { - // forkNode.setRightNode(new Node<>(forkNode, NodeType.PAR)); - // continuationNode = forkNode.getRightNode(); - // } - - // Node successorParent = continuationNode; - // List successors = Graphs.successorListOf(jobDag, currentFork); - // // create leftSide of joinNode - // for (int i = 0; i < successors.size(); ++i) { - // Job succ = successors.get(i); - // Node thisNode = constructTree(jobDag, successorParent, succ, tree, - // forkVertices, joinVertices, sink); - // if (i == successors.size() - 1) { - // successorParent.setRightNode(thisNode); - // } else if (i == successors.size() - 2) { - // successorParent.setLeftNode(thisNode); - // } else { - // successorParent.setLeftNode(thisNode); - // successorParent.setRightNode(new Node<>(successorParent, NodeType.PAR)); - // successorParent = successorParent.getRightNode(); - // } - // } - - // return forkNode; - // } else { - // return new Node<>(parent, currentFork); - // } - // } - public static boolean checkNFJProperty(DirectedAcyclicGraph jobDag) { LinkedList joinNodes = new LinkedList<>(); LinkedList forkNodes = new LinkedList<>(); @@ -453,15 +401,6 @@ public class DagTask implements Task { if (inbetweenJobs.containsAll(successorOfFork)) { return j; } - - // final Set edgeSet = new HashSet<>(); - // AllDirectedPaths finder = new AllDirectedPaths<>(jobDag); - // finder.getAllPaths(forkNode, j, true, null) - // .forEach(g -> edgeSet.addAll(g.getEdgeList())); - // Set outgoingEdges = jobDag.outgoingEdgesOf(forkNode); - // if (edgeSet.containsAll(outgoingEdges)) { - // return j; - // } } return sink; @@ -502,6 +441,10 @@ public class DagTask implements Task { private static GraphEndPoints traverseNodes(DirectedAcyclicGraph jobDag, Node node) { + if (node.getNodeType() != NodeType.LEAF + && (node.getLeftNode() == null || node.getRightNode() == null)) { + int test = 3; + } switch (node.getNodeType()) { case LEAF: { Job j = node.getObject(); diff --git a/src/main/java/mvd/jester/model/TreeJob.java b/src/main/java/mvd/jester/model/TreeJob.java new file mode 100644 index 0000000..6052c84 --- /dev/null +++ b/src/main/java/mvd/jester/model/TreeJob.java @@ -0,0 +1,32 @@ +package mvd.jester.model; + +public class TreeJob { + private long wcet; + private final Job job; + + public TreeJob(Job job) { + this.wcet = job.getWcet(); + this.job = job; + } + + /** + * @return the job + */ + public Job getJob() { + return job; + } + + /** + * @return the wcet + */ + public long getWcet() { + return wcet; + } + + /** + * @param wcet the wcet to set + */ + public void setWcet(long wcet) { + this.wcet = wcet; + } +} diff --git a/src/main/java/mvd/jester/tests/FonsecaNelis.java b/src/main/java/mvd/jester/tests/FonsecaNelis.java index ff40b8c..28fa501 100644 --- a/src/main/java/mvd/jester/tests/FonsecaNelis.java +++ b/src/main/java/mvd/jester/tests/FonsecaNelis.java @@ -1,18 +1,22 @@ package mvd.jester.tests; import java.math.RoundingMode; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; +import javax.print.attribute.standard.JobName; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.google.common.math.LongMath; import org.jgrapht.experimental.dag.DirectedAcyclicGraph; import org.jgrapht.graph.DefaultEdge; -import org.jgrapht.traverse.BreadthFirstIterator; import mvd.jester.info.SchedulingInfo; import mvd.jester.info.TerminationInfo; import mvd.jester.info.TerminationInfo.Level; @@ -21,10 +25,13 @@ import mvd.jester.model.Job; import mvd.jester.model.Segment; import mvd.jester.model.SortedTaskSet; import mvd.jester.model.Task; +import mvd.jester.model.TreeJob; import mvd.jester.model.DagTask.DagUtils; import mvd.jester.priority.PriorityManager; import mvd.jester.priority.RateMonotonic; import mvd.jester.utils.BinaryDecompositionTree; +import mvd.jester.utils.BinaryDecompositionTree.Node; +import mvd.jester.utils.BinaryDecompositionTree.NodeType; public class FonsecaNelis extends AbstractTest { @@ -61,24 +68,82 @@ public class FonsecaNelis extends AbstractTest { private void createNFJandDecompositionTree(SortedTaskSet tasks) { for (DagTask t : tasks) { DirectedAcyclicGraph jobDag = t.getJobDag(); - LinkedList joinNodes = new LinkedList<>(); - LinkedList forkNodes = new LinkedList<>(); - - BreadthFirstIterator breadthFirstIterator = - new BreadthFirstIterator<>(jobDag); - while (breadthFirstIterator.hasNext()) { - Job j = breadthFirstIterator.next(); - if (jobDag.inDegreeOf(j) > 1) { - joinNodes.add(j); - } - if (jobDag.outDegreeOf(j) > 1) { - forkNodes.add(j); + + DirectedAcyclicGraph nfjJobDag = DagUtils.createNFJGraph(jobDag); + BinaryDecompositionTree tree = DagUtils.createDecompositionTree(nfjJobDag); + + sortedSegments.put(t, constructCarryOutDistribution(nfjJobDag, tree)); + } + } + + private Set constructCarryOutDistribution( + DirectedAcyclicGraph nfjDag, BinaryDecompositionTree tree) { + Set carryOutWorkload = new LinkedHashSet<>(); + BinaryDecompositionTree modifiedTree = transformTree(tree); + + boolean isEmpty = false; + do { + Set parallelJobs = getMaximumParallelism(modifiedTree.getRootNode()); + Optional min = + parallelJobs.stream().min((p1, p2) -> Long.compare(p1.getWcet(), p2.getWcet())); + if (min.isPresent()) { + long width = min.get().getWcet(); + carryOutWorkload.add(new Segment(width, parallelJobs.size())); + for (TreeJob p : parallelJobs) { + p.setWcet(p.getWcet() - width); } + } else { + break; + } + isEmpty = parallelJobs.isEmpty(); + } while (!isEmpty); + + return carryOutWorkload; + } + + + private BinaryDecompositionTree transformTree(BinaryDecompositionTree tree) { + BinaryDecompositionTree modifiedTree = new BinaryDecompositionTree<>(); + Node root = transformNode(null, tree.getRootNode()); + modifiedTree.setRoot(root); + return modifiedTree; + } + + private Node transformNode(Node parent, Node node) { + if (node.getNodeType() != NodeType.LEAF + && (node.getLeftNode() == null || node.getRightNode() == null)) { + int test = 3; + } + if (node.getNodeType().equals(NodeType.LEAF)) { + return new Node(parent, new TreeJob(node.getObject())); + } else { + Node modifiedNode = new Node(null, node.getNodeType()); + modifiedNode.setLeftNode(transformNode(modifiedNode, node.getLeftNode())); + modifiedNode.setRightNode(transformNode(modifiedNode, node.getRightNode())); + return modifiedNode; + } + } + + private Set getMaximumParallelism(Node node) { + NodeType nodeType = node.getNodeType(); + if (nodeType.equals(NodeType.PAR)) { + Set left = getMaximumParallelism(node.getLeftNode()); + Set right = getMaximumParallelism(node.getRightNode()); + return Sets.union(left, right); + } else if (nodeType.equals(NodeType.SEQ)) { + Set left = getMaximumParallelism(node.getLeftNode()); + Set right = getMaximumParallelism(node.getRightNode()); + 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<>(); } - DirectedAcyclicGraph modifiedJobDag = - DagUtils.createNFJGraph(jobDag, forkNodes, joinNodes); - BinaryDecompositionTree tree = - DagUtils.createDecompositionTree(modifiedJobDag, forkNodes, joinNodes); } } diff --git a/src/main/java/mvd/jester/utils/BinaryDecompositionTree.java b/src/main/java/mvd/jester/utils/BinaryDecompositionTree.java index 96d6191..1a98086 100644 --- a/src/main/java/mvd/jester/utils/BinaryDecompositionTree.java +++ b/src/main/java/mvd/jester/utils/BinaryDecompositionTree.java @@ -31,12 +31,13 @@ public class BinaryDecompositionTree { private final Node parentNode; private Node leftNode; private Node rightNode; - private NodeType nodeType; - private T object; + private final NodeType nodeType; + private final T object; public Node(Node parentNode, NodeType nodeType) { this.parentNode = parentNode; this.nodeType = nodeType; + this.object = null; } public boolean contains(T object) { diff --git a/src/test/java/mvd/jester/model/TestDagUtils.java b/src/test/java/mvd/jester/model/TestDagUtils.java index be35871..9e23425 100644 --- a/src/test/java/mvd/jester/model/TestDagUtils.java +++ b/src/test/java/mvd/jester/model/TestDagUtils.java @@ -1,6 +1,7 @@ package mvd.jester.model; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.concurrent.ThreadLocalRandom; import org.jgrapht.Graphs; import org.jgrapht.experimental.dag.DirectedAcyclicGraph; import org.jgrapht.graph.DefaultEdge; @@ -48,7 +49,8 @@ public class TestDagUtils { @DisplayName("Check if Decomposition Tree is created correctly for NFJ Dag.") void checkDecompositionTreeCreation() { for (int i = 0; i < 100; ++i) { - DagTaskBuilder b = new DagTaskBuilder(); + long numberOfProcessors = ThreadLocalRandom.current().nextLong(4, 16); + DagTaskBuilder b = new DagTaskBuilder().setNumberOfProcessors(numberOfProcessors); DagTask t = b.generateTask(); DirectedAcyclicGraph jobDag = t.getJobDag(); DirectedAcyclicGraph nfjJobDag = DagUtils.createNFJGraph(jobDag); -- libgit2 0.26.0