diff --git a/src/main/java/mvd/jester/App.java b/src/main/java/mvd/jester/App.java index 1db176a..7edac86 100644 --- a/src/main/java/mvd/jester/App.java +++ b/src/main/java/mvd/jester/App.java @@ -6,9 +6,12 @@ import mvd.jester.model.DagTask; import mvd.jester.model.SystemManager; import mvd.jester.model.SystemManager.DagTaskBuilder; import mvd.jester.tests.AbstractTest; +import mvd.jester.tests.DongLiu; import mvd.jester.tests.FonsecaNelis; import mvd.jester.tests.JiangYi; import mvd.jester.tests.SchmidMottok; +import mvd.jester.tests.Tester; +import mvd.jester.tests.UeterAgrawal; import mvd.jester.tests.TypeFunction.UnknownStructure; @@ -17,68 +20,94 @@ import mvd.jester.tests.TypeFunction.UnknownStructure; * */ public class App { - public static void main(String[] args) { - { - SystemManager manager = new SystemManager<>(DagTaskBuilder.class); - manager.setNumberOfProcessors(8); - TestEnvironment te = new TestEnvironment(); + public static void main(String[] args) { + { + SystemManager manager = + new SystemManager<>(DagTaskBuilder.class); + manager.setNumberOfProcessors(8); + TestEnvironment te = new TestEnvironment(); - List> tests = te.registerTests(Arrays.asList( - /* new SchmidMottok(new KnownStructure(), manager), */ - new SchmidMottok(new UnknownStructure(), manager), - // new Tester(new UnknownStructure(), manager), - // new MelaniButtazzo(manager),, - new FonsecaNelis(manager), // - new JiangYi(manager)// - )); + List> tests = te.registerTests(Arrays.asList( + new SchmidMottok(new UnknownStructure(), manager), // + // new Tester(new UnknownStructure(),manager), + // new MelaniButtazzo(manager),, + // new FonsecaNelis(manager), // + // new DongLiu(manager), // + new UeterAgrawal(manager), // + new JiangYi(manager)// + )); - te.varyRenyiUtilization(manager, tests, 500); - } - { - SystemManager manager = new SystemManager<>(DagTaskBuilder.class); - manager.setNumberOfProcessors(8); - TestEnvironment te = new TestEnvironment(); + te.varyRenyiUtilization(manager, tests, 200); + } + { + SystemManager manager = + new SystemManager<>(DagTaskBuilder.class); + manager.setNumberOfProcessors(16); + TestEnvironment te = new TestEnvironment(); - List> tests = te.registerTests(Arrays.asList( - /* new SchmidMottok(new KnownStructure(), manager), */ - new SchmidMottok(new UnknownStructure(), manager), - // new Tester(new UnknownStructure(), manager), - // new MelaniButtazzo(manager),, - new FonsecaNelis(manager), // - new JiangYi(manager)// - )); + List> tests = te.registerTests(Arrays.asList( + new SchmidMottok(new UnknownStructure(), manager), // + // new Tester(new UnknownStructure(),manager), + // new MelaniButtazzo(manager),, + // new FonsecaNelis(manager), // + // new DongLiu(manager), // + new UeterAgrawal(manager), // + new JiangYi(manager)// + )); - te.varyPropability(manager, tests, 500); - } - { - SystemManager manager = new SystemManager<>(DagTaskBuilder.class); - manager.setNumberOfProcessors(8); - TestEnvironment te = new TestEnvironment(); + te.varyRenyiUtilization(manager, tests, 200); + } + { + SystemManager manager = + new SystemManager<>(DagTaskBuilder.class); + manager.setNumberOfProcessors(32); + TestEnvironment te = new TestEnvironment(); - List> tests = te.registerTests(Arrays.asList( // - // new SchmidMottok(new KnownStructure(), manager), // - new SchmidMottok(new UnknownStructure(), manager), // - // new Tester(new UnknownStructure(), manager), // - // new MelaniButtazzo(manager), // - new FonsecaNelis(manager), // - new JiangYi(manager))); + List> tests = te.registerTests(Arrays.asList( + new SchmidMottok(new UnknownStructure(), manager), // + // new Tester(new UnknownStructure(),manager), + // new MelaniButtazzo(manager),, + // new FonsecaNelis(manager), // + // new DongLiu(manager), // + new UeterAgrawal(manager), // + new JiangYi(manager)// + )); - te.varyNumberOfProcessors(manager, tests, 500); - } - { - SystemManager manager = new SystemManager<>(DagTaskBuilder.class); - manager.setNumberOfProcessors(8); - TestEnvironment te = new TestEnvironment(); + te.varyRenyiUtilization(manager, tests, 200); + } + // { + // SystemManager manager = new + // SystemManager<>(DagTaskBuilder.class); + // manager.setNumberOfProcessors(8); + // TestEnvironment te = new TestEnvironment(); + + // List> tests = te.registerTests(Arrays.asList( // + // // new SchmidMottok(new KnownStructure(), manager), // + // new SchmidMottok(new UnknownStructure(), manager), // + // // new Tester(new UnknownStructure(), manager), // + // // new MelaniButtazzo(manager), // + // new FonsecaNelis(manager), // + // new UeterAgrawal(manager), // + // new JiangYi(manager))); + + // te.varyNumberOfProcessors(manager, tests, 200); + // } + // { + // SystemManager manager = new + // SystemManager<>(DagTaskBuilder.class); + // manager.setNumberOfProcessors(8); + // TestEnvironment te = new TestEnvironment(); - List> tests = te.registerTests(Arrays.asList( // - // new SchmidMottok(new KnownStructure(), manager), // - new SchmidMottok(new UnknownStructure(), manager), // - // new Tester(new UnknownStructure(), manager), // - // new MelaniButtazzo(manager), // - new FonsecaNelis(manager), // - new JiangYi(manager))); + // List> tests = te.registerTests(Arrays.asList( // + // // new SchmidMottok(new KnownStructure(), manager), // + // new SchmidMottok(new UnknownStructure(), manager), // + // // new Tester(new UnknownStructure(), manager), // + // // new MelaniButtazzo(manager), // + // new FonsecaNelis(manager), // + // new UeterAgrawal(manager), // + // new JiangYi(manager))); - te.varyNumberOfTasks(manager, tests, 500); + // te.varyNumberOfTasks(manager, tests, 200); + // } } - } } diff --git a/src/main/java/mvd/jester/ResultLogger.java b/src/main/java/mvd/jester/ResultLogger.java index 87ba8ad..489913e 100644 --- a/src/main/java/mvd/jester/ResultLogger.java +++ b/src/main/java/mvd/jester/ResultLogger.java @@ -35,12 +35,12 @@ public class ResultLogger { public void logLine(final double utilization, - final Map, Long> results) { + final Map, Long> results, long numberOfTestedTasksets) { final Appendable out = new StringBuilder(); try { out.append("" + utilization); for (final Entry, Long> rc : results.entrySet()) { - final long numberOfFeasibleTasks = rc.getValue(); + final long numberOfFeasibleTasks = rc.getValue() / ( numberOfTestedTasksets / 100); out.append("\t" + numberOfFeasibleTasks); } } catch (final Exception e) { diff --git a/src/main/java/mvd/jester/TestEnvironment.java b/src/main/java/mvd/jester/TestEnvironment.java index 60b7e2b..1bb5bef 100644 --- a/src/main/java/mvd/jester/TestEnvironment.java +++ b/src/main/java/mvd/jester/TestEnvironment.java @@ -112,14 +112,14 @@ public class TestEnvironment { final List> abstractTestInstances, final long numberOfTaskSetsPerStep) { long checkedTasksets = 0; - final long numberOfTaskSets = 8 * numberOfTaskSetsPerStep; + final long numberOfTaskSets = 5 * numberOfTaskSetsPerStep; final ResultLogger resultLogger = new ResultLogger("numberOfProcessors"); final Map, Long> resultMap = new LinkedHashMap<>(); abstractTestInstances.forEach(t -> resultMap.put(t, (long) 0)); resultLogger.logHeader(resultMap, "NoOfProcessors"); - for (long numberOfProcessors = 2; numberOfProcessors <= 16; numberOfProcessors += 2) { + for (long numberOfProcessors = 2; numberOfProcessors <= 32; numberOfProcessors *= 2) { manager.setNumberOfProcessors(numberOfProcessors); resultMap.replaceAll((k, v) -> (long) 0); for (int i = 0; i < numberOfTaskSetsPerStep; ++i) { @@ -142,7 +142,7 @@ public class TestEnvironment { } checkedTasksets++; } - resultLogger.logLine(numberOfProcessors, resultMap); + resultLogger.logLine(numberOfProcessors, resultMap, numberOfTaskSetsPerStep); resultLogger.newLine(); } System.out.println(""); @@ -184,7 +184,7 @@ public class TestEnvironment { } checkedTasksets++; } - resultLogger.logLine(numberOfTasks, resultMap); + resultLogger.logLine(numberOfTasks, resultMap, numberOfTaskSetsPerStep); resultLogger.newLine(); } System.out.println(""); @@ -224,7 +224,7 @@ public class TestEnvironment { } checkedTasksets++; } - resultLogger.logLine(util, resultMap); + resultLogger.logLine(util, resultMap, numberOfTaskSetsPerUtil); resultLogger.newLine(); } System.out.println(""); @@ -266,7 +266,7 @@ public class TestEnvironment { } checkedTasksets++; } - resultLogger.logLine(util, resultMap); + resultLogger.logLine(util / numberOfProcessors, resultMap, numberOfTaskSetsPerUtil); resultLogger.newLine(); } System.out.println(""); @@ -306,7 +306,7 @@ public class TestEnvironment { } checkedTasksets++; } - resultLogger.logLine(p_add, resultMap); + resultLogger.logLine(p_add, resultMap, numberOfTaskSetsPerStep); resultLogger.newLine(); } System.out.println(""); diff --git a/src/main/java/mvd/jester/model/DagTask.java b/src/main/java/mvd/jester/model/DagTask.java index 95955f3..fd8a2d9 100644 --- a/src/main/java/mvd/jester/model/DagTask.java +++ b/src/main/java/mvd/jester/model/DagTask.java @@ -20,6 +20,15 @@ public class DagTask extends Task { } public DagTask(final DirectedAcyclicGraph jobDag, final long period, + final long deadline, final long numberOfThreads) { + super(period, deadline, DagUtils.calculateWorkload(jobDag), + DagUtils.calculateCriticalPath(jobDag), numberOfThreads); + this.jobDag = jobDag; + this.workloadDistribution = + DagUtils.calculateWorkloadDistribution(this.jobDag, this.criticalPath); + } + + public DagTask(final DirectedAcyclicGraph jobDag, final long period, final Set workloadDistribution, final long numberOfThreads) { super(period, period, DagUtils.calculateWorkload(jobDag), DagUtils.calculateCriticalPath(jobDag), numberOfThreads); diff --git a/src/main/java/mvd/jester/model/LightTask.java b/src/main/java/mvd/jester/model/LightTask.java new file mode 100644 index 0000000..de040b9 --- /dev/null +++ b/src/main/java/mvd/jester/model/LightTask.java @@ -0,0 +1,26 @@ +package mvd.jester.model; + +import java.util.HashSet; +import java.util.Set; + +public class LightTask extends Task { + + private final Set segments; + + public LightTask(long period, long deadline, long workload) { + super(period, deadline, workload, workload, 1); + segments = new HashSet<>(); + segments.add(new Segment(workload, 1)); + } + + @Override + public long getMaximumParallelism() { + return 1; + } + + @Override + public Set getWorkloadDistribution() { + return segments; + } + +} diff --git a/src/main/java/mvd/jester/model/SystemManager.java b/src/main/java/mvd/jester/model/SystemManager.java index e30b717..d65e8f7 100644 --- a/src/main/java/mvd/jester/model/SystemManager.java +++ b/src/main/java/mvd/jester/model/SystemManager.java @@ -216,17 +216,24 @@ public class SystemManager implements SystemManagerInterface } else { final double remainingUtilization = totalUtilization - currentUtilization; final long period = (long) Math.ceil(task.getWorkload() / remainingUtilization); - if (period >= task.getCriticalPath()) { - long numberOfThreads = - LongMath.divide(task.getWorkload() - task.getCriticalPath(), - period - task.getCriticalPath(), RoundingMode.CEILING); + final long criticalPath = task.getCriticalPath(); + if (period >= criticalPath) { + final long deadline = randomNumberInRange( + criticalPath + (period - criticalPath) / 4, period); // TODO: + // deadline = + // period? + + // final long deadline = period; + + long numberOfThreads = LongMath.divide(task.getWorkload() - criticalPath, + deadline - criticalPath, RoundingMode.CEILING); if (numberOfThreads == 0) { numberOfThreads = 1; } final DagTask modifiedTask = - new DagTask(task.getJobDag(), period, numberOfThreads); + new DagTask(task.getJobDag(), period, deadline, numberOfThreads); taskSet.add(modifiedTask); break; } @@ -324,15 +331,21 @@ public class SystemManager implements SystemManagerInterface final long workload = DagUtils.calculateWorkload(jobDag); final long criticalPath = DagUtils.calculateCriticalPath(jobDag); final long period = randomRenyiPeriod(workload, criticalPath, totalUtilization); + final long deadline = + randomNumberInRange(criticalPath + (period - criticalPath) / 4, period); // TODO: + // oder + // period? + + // final long deadline = period; final long numberOfThreads = LongMath.divide(workload - criticalPath, - period - criticalPath, RoundingMode.CEILING); + deadline - criticalPath, RoundingMode.CEILING); if (numberOfThreads == 0) { - return new DagTask(jobDag, period, 1); + return new DagTask(jobDag, period, deadline, 1); } - return new DagTask(jobDag, period, numberOfThreads); + return new DagTask(jobDag, period, deadline, numberOfThreads); } private long randomRenyiPeriod(final long workload, final long criticalPath, diff --git a/src/main/java/mvd/jester/priority/DeadlineMonotonic.java b/src/main/java/mvd/jester/priority/DeadlineMonotonic.java new file mode 100644 index 0000000..b081525 --- /dev/null +++ b/src/main/java/mvd/jester/priority/DeadlineMonotonic.java @@ -0,0 +1,62 @@ +package mvd.jester.priority; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import mvd.jester.model.Task; +import mvd.jester.simulator.AbstractSimulator; +import mvd.jester.simulator.internals.TaskContextInterface; +import mvd.jester.tests.AbstractTest; + +public class DeadlineMonotonic implements PriorityManager { + + final static Set>> abstractTests = + new HashSet<>(Arrays.asList(mvd.jester.tests.MaiaBertogna.class, + mvd.jester.tests.SchmidMottok.class)); + final static Set> abstractSimulators = + new HashSet<>(Arrays.asList(mvd.jester.simulator.ParallelSynchronous.class, + mvd.jester.simulator.DynamicForkJoin.class)); + + /** + * Compare the priority of two tasks according to the Rate Monotonic policy + * + * @param t1 The first task + * @param t2 The second task + * @return 0 if both tasks have the same priority, negative number if the first task has a + * higher priority, positive number if the second task has a higher priority + */ + @Override + public int compare(Task t1, Task t2) { + return Long.compare(t1.getDeadline(), t2.getDeadline()); + } + + @Override + public int compare(TaskContextInterface t1, TaskContextInterface t2) { + return Long.compare(t1.getTask().getDeadline(), t2.getTask().getDeadline()); + } + + @Override + public boolean hasTest(AbstractTest abstractTest) { + return abstractTests.contains(abstractTest.getClass()); + } + + @Override + public boolean hasTest(Class> abstractTestClass) { + return abstractTests.contains(abstractTestClass); + } + + @Override + public boolean hasSimulator(AbstractSimulator abstractSimulator) { + return abstractSimulators.contains(abstractSimulator.getClass()); + } + + @Override + public boolean hasSimulator(Class abstractSimulatorClass) { + return abstractSimulators.contains(abstractSimulatorClass); + } + + @Override + public String getName() { + return "DM"; + } +} diff --git a/src/main/java/mvd/jester/tests/DongLiu.java b/src/main/java/mvd/jester/tests/DongLiu.java new file mode 100644 index 0000000..de2fe25 --- /dev/null +++ b/src/main/java/mvd/jester/tests/DongLiu.java @@ -0,0 +1,59 @@ +package mvd.jester.tests; + +import mvd.jester.info.SchedulingInfo; +import mvd.jester.info.SchedulingInfo.Feasiblity; +import mvd.jester.model.DagTask; +import mvd.jester.model.SortedTaskSet; +import mvd.jester.model.SystemManagerInterface; +import mvd.jester.priority.EarliestDeadlineFirst; +import mvd.jester.priority.PriorityManager; + +public class DongLiu extends AbstractTest { + + private final EarliestDeadlineFirst priorityManager; + + public DongLiu(SystemManagerInterface manager) { + super(manager); + this.priorityManager = new EarliestDeadlineFirst(); + } + + @Override + public SchedulingInfo runSchedulabilityCheck(SortedTaskSet tasks) { + final long numberOfProcessors = manager.getNumberOfProcessors(); + for (DagTask task : tasks) { + double sumOfWorkloads = 0; + for (DagTask t : tasks) { + sumOfWorkloads += getAverageWorkload(t, task); + } + final double cpUtilization = (double) task.getCriticalPath() / task.getPeriod(); + if (!(sumOfWorkloads <= numberOfProcessors + - ((numberOfProcessors - 1) * cpUtilization))) { + return new SchedulingInfo(Feasiblity.FAILED); + } + } + + return new SchedulingInfo(Feasiblity.SUCCEEDED); + } + + private double getAverageWorkload(DagTask t, DagTask task) { + final double cpUtilization = (double) task.getCriticalPath() / task.getPeriod(); + final double taskUtilization = t.getUtilization(); + if (cpUtilization >= taskUtilization) { + return taskUtilization; + } else { + return taskUtilization + ((double) t.getWorkload() - cpUtilization * t.getPeriod()) + / (task.getPeriod()); + } + } + + @Override + public PriorityManager getPriorityManager() { + return priorityManager; + } + + @Override + public String getName() { + return "DongLiu"; + } + +} diff --git a/src/main/java/mvd/jester/tests/FonsecaNelis.java b/src/main/java/mvd/jester/tests/FonsecaNelis.java index bd03ef0..8621ba8 100644 --- a/src/main/java/mvd/jester/tests/FonsecaNelis.java +++ b/src/main/java/mvd/jester/tests/FonsecaNelis.java @@ -25,6 +25,7 @@ import mvd.jester.model.SystemManagerInterface; import mvd.jester.model.Task; import mvd.jester.model.TreeJob; import mvd.jester.utils.DagUtils; +import mvd.jester.priority.DeadlineMonotonic; import mvd.jester.priority.PriorityManager; import mvd.jester.priority.RateMonotonic; import mvd.jester.utils.BinaryDecompositionTree; @@ -40,7 +41,7 @@ public class FonsecaNelis extends AbstractTest { public FonsecaNelis(final SystemManagerInterface manager) { super(manager); this.responseTimes = new HashMap<>(); - this.priorityManager = new RateMonotonic(); + this.priorityManager = new DeadlineMonotonic(); this.carryOutSegments = new HashMap<>(); } @@ -153,7 +154,7 @@ public class FonsecaNelis extends AbstractTest { previousResponseTime = responseTime; double taskInterference = 0; for (final DagTask t : tasks) { - if (t.getPeriod() < task.getPeriod()) { + if (priorityManager.compare(t, task) < 0) { taskInterference += getTaskInterference(t, responseTime); } } diff --git a/src/main/java/mvd/jester/tests/JiangYi.java b/src/main/java/mvd/jester/tests/JiangYi.java index 0566ed6..4bcbc12 100644 --- a/src/main/java/mvd/jester/tests/JiangYi.java +++ b/src/main/java/mvd/jester/tests/JiangYi.java @@ -34,7 +34,7 @@ public class JiangYi extends AbstractTest { Set lightTasks = new HashSet<>(); for (DagTask t : tasks) { - if (t.getUtilization() < 1) { + if (t.getDensity() < 1) { lightTasks.add(t); } else { heavyTasks.add(t); @@ -68,10 +68,10 @@ public class JiangYi extends AbstractTest { Collections.sort(taskList, (a, b) -> Double.compare(b.getDensity(), a.getDensity())); List bins = new ArrayList<>(); - for (int i = 0; i < numberOfprocessors; ++i) { bins.add((double) 0); } + Iterator taskIterator = taskList.iterator(); while (taskIterator.hasNext()) { Collections.sort(bins); diff --git a/src/main/java/mvd/jester/tests/SchmidMottok.java b/src/main/java/mvd/jester/tests/SchmidMottok.java index 0d56336..02e0c06 100644 --- a/src/main/java/mvd/jester/tests/SchmidMottok.java +++ b/src/main/java/mvd/jester/tests/SchmidMottok.java @@ -11,6 +11,7 @@ import mvd.jester.model.DagTask; import mvd.jester.model.SortedTaskSet; import mvd.jester.model.SystemManagerInterface; import mvd.jester.model.Task; +import mvd.jester.priority.DeadlineMonotonic; import mvd.jester.priority.PriorityManager; import mvd.jester.priority.RateMonotonic; @@ -26,7 +27,7 @@ public class SchmidMottok extends AbstractTest { public SchmidMottok(TypeFunction structure, final SystemManagerInterface manager) { super(manager); this.responseTimes = new HashMap<>(); - this.priorityManager = new RateMonotonic(); + this.priorityManager = new DeadlineMonotonic(); this.structure = structure; } @@ -56,10 +57,11 @@ public class SchmidMottok extends AbstractTest { long numberOfProcessors = manager.getNumberOfProcessors(); long occupiedProcessors = 0; for (DagTask t : tasks) { - if (occupiedProcessors >= numberOfProcessors) { - t.setNumberOfThreads(numberOfProcessors); + if (occupiedProcessors + t.getNumberOfThreads() <= numberOfProcessors) { + occupiedProcessors += t.getNumberOfThreads(); } else { occupiedProcessors += t.getNumberOfThreads(); + t.setNumberOfThreads(numberOfProcessors); } } } @@ -72,7 +74,7 @@ public class SchmidMottok extends AbstractTest { long occupiedProcessors = 0; for (final DagTask t : tasks) { - if (t.getPeriod() < task.getPeriod()) { + if (priorityManager.compare(t, task) < 0) { final long numberOfThreads = structure.getNumberOfThreads(t); occupiedProcessors += numberOfThreads; } @@ -88,7 +90,7 @@ public class SchmidMottok extends AbstractTest { double taskInterference = 0; for (final DagTask t : tasks) { - if (t.getPeriod() < task.getPeriod()) { + if (priorityManager.compare(t, task) < 0) { final long numberOfThreads = structure.getNumberOfThreads(t); for (int p = 0; p < numberOfThreads; ++p) { taskInterference += @@ -104,17 +106,17 @@ public class SchmidMottok extends AbstractTest { long totalInterference = (long) Math.floor(taskInterference + selfInterference); - if (occupiedProcessors < numberOfProcessors) { - long workloadAmongRemainingProcessors = - LongMath.divide(task.getWorkload() - task.getCriticalPath(), - numberOfProcessors - occupiedProcessors, RoundingMode.FLOOR); - totalInterference = - Math.min(totalInterference, workloadAmongRemainingProcessors); - } - responseTime = minimumWcet + totalInterference; } while (previousResponseTime != responseTime); + if (occupiedProcessors < numberOfProcessors) { + long workloadAmongRemainingProcessors = + LongMath.divide(task.getWorkload() - task.getCriticalPath(), + numberOfProcessors - occupiedProcessors, RoundingMode.FLOOR); + responseTime = + Math.min(responseTime, workloadAmongRemainingProcessors + minimumWcet); + } + return responseTime; } } diff --git a/src/main/java/mvd/jester/tests/Tester.java b/src/main/java/mvd/jester/tests/Tester.java index e5b30d0..763e9b0 100644 --- a/src/main/java/mvd/jester/tests/Tester.java +++ b/src/main/java/mvd/jester/tests/Tester.java @@ -1,128 +1,116 @@ package mvd.jester.tests; import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.math.LongMath; import mvd.jester.info.SchedulingInfo; import mvd.jester.info.TerminationInfo; +import mvd.jester.info.SchedulingInfo.Feasiblity; import mvd.jester.model.DagTask; +import mvd.jester.model.LightTask; import mvd.jester.model.SortedTaskSet; import mvd.jester.model.SystemManagerInterface; import mvd.jester.model.Task; +import mvd.jester.priority.DeadlineMonotonic; import mvd.jester.priority.PriorityManager; import mvd.jester.priority.RateMonotonic; public class Tester extends AbstractTest { - private final Map responseTimes; private final PriorityManager priorityManager; - private final TypeFunction structure; public Tester(TypeFunction structure, final SystemManagerInterface manager) { super(manager); - this.responseTimes = new HashMap<>(); - this.priorityManager = new RateMonotonic(); - this.structure = structure; + this.priorityManager = new DeadlineMonotonic(); } - @Override - public SchedulingInfo runSchedulabilityCheck(SortedTaskSet tasks) { - responseTimes.clear(); - assignNumberOfThreads(tasks); - for (final DagTask t : tasks) { - final long responseTime = calculateResponseTime(tasks, t); - responseTimes.put(t, new TerminationInfo(t.getDeadline(), responseTime)); - } + public SchedulingInfo runSchedulabilityCheck(final SortedTaskSet tasks) { + reassignNumberOfThreads(tasks); - return new SchedulingInfo(responseTimes.values()); - } + List processorBins = new ArrayList<>(); - @Override - public PriorityManager getPriorityManager() { - return priorityManager; - } + for (int i = 0; i < manager.getNumberOfProcessors(); ++i) { + processorBins.add((double) 0); + } - private void assignNumberOfThreads(Set tasks) { - long occupiedProcessors = 0; - long numberOfProcessors = manager.getNumberOfProcessors(); - for (DagTask t : tasks) { - long workload = t.getWorkload(); - long criticalPath = t.getCriticalPath(); - long period = t.getPeriod(); - if (period == criticalPath) { - t.setNumberOfThreads(1); - } else if (occupiedProcessors >= numberOfProcessors) { - t.setNumberOfThreads(numberOfProcessors); - } else { - final long numberOfThreads = LongMath.divide(workload - criticalPath, - period - criticalPath, RoundingMode.CEILING); - t.setNumberOfThreads(numberOfThreads); - occupiedProcessors += numberOfThreads; + nextTask: for (DagTask t : tasks) { + final long minimumNumberOfThreads = t.getNumberOfThreads(); + for (long numberOfThreads = minimumNumberOfThreads; numberOfThreads < manager + .getNumberOfProcessors(); ++numberOfThreads) { + List copiedProcessorBins = copyBins(processorBins); + Collections.sort(copiedProcessorBins); + + final long criticalPath = t.getCriticalPath(); + final long workload = t.getWorkload(); + + final long processorWorkload = + (long) Math.ceil(copiedProcessorBins.get(0) * t.getDeadline()); + + final long workloadPerThread = + LongMath.divide(workload, numberOfThreads, RoundingMode.CEILING); + + final long threadWorkload = Math.max(workloadPerThread, criticalPath); + + if (threadWorkload + processorWorkload <= t.getDeadline()) { + copiedProcessorBins.set(0, + copiedProcessorBins.get(0) + (double) (threadWorkload) / t.getPeriod()); + + for (int m = 0; m < numberOfThreads - 1; ++m) { + Collections.sort(copiedProcessorBins); + final long nextProcessorWorkload = + (long) Math.ceil(copiedProcessorBins.get(0) * t.getDeadline()); + if (threadWorkload + nextProcessorWorkload <= t.getDeadline()) { + copiedProcessorBins.set(0, copiedProcessorBins.get(0) + + (double) threadWorkload / t.getPeriod()); + } else { + return new SchedulingInfo(Feasiblity.FAILED); + } + } + processorBins = copiedProcessorBins; + continue nextTask; + } } + return new SchedulingInfo(Feasiblity.FAILED); } - } - @Override - public String getName() { - return "Tester_" + structure.getType(); + return new SchedulingInfo(Feasiblity.SUCCEEDED); } - private long calculateResponseTime(final Set tasks, final DagTask task) { - final long minimumWcet = task.getCriticalPath(); - long responseTime = minimumWcet; - long previousResponseTime = 0; - final long numberOfProcessors = manager.getNumberOfProcessors(); - - long occupiedProcessors = 0; - for (final DagTask t : tasks) { - if (t.getPeriod() < task.getPeriod()) { - final long numberOfThreads = structure.getNumberOfThreads(t); - occupiedProcessors += numberOfThreads; - } + private void reassignNumberOfThreads(Set tasks) { + for (DagTask t : tasks) { + final long numberOfThreads = LongMath.divide(t.getWorkload() - t.getCriticalPath(), + t.getDeadline() - t.getCriticalPath(), RoundingMode.CEILING); + t.setNumberOfThreads(numberOfThreads); } + } - final double selfInterference = structure.getSelfInterference(task); - - if (occupiedProcessors + structure.getNumberOfThreads(task) <= numberOfProcessors) { - return minimumWcet + (long) Math.floor(selfInterference); - } else { - do { - previousResponseTime = responseTime; - double taskInterference = 0; - - for (final DagTask t : tasks) { - if (t.getPeriod() < task.getPeriod()) { - final long numberOfThreads = structure.getNumberOfThreads(t); - for (int p = 0; p < numberOfThreads; ++p) { - taskInterference += - Math.min( - structure.getTaskInterference(t, responseTimes, - responseTime, p + 1), - responseTime - minimumWcet + 1); - } - } - } - - taskInterference /= numberOfProcessors; + private List copyBins(List bins) { + List copiedBins = new ArrayList<>(); - long totalInterference = (long) Math.floor(taskInterference + selfInterference); + for (Double b : bins) { + copiedBins.add(b.doubleValue()); + } - if (occupiedProcessors < numberOfProcessors) { - long workloadAmongRemainingProcessors = - LongMath.divide(task.getWorkload() - task.getCriticalPath(), - numberOfProcessors - occupiedProcessors, RoundingMode.FLOOR); - totalInterference = - Math.min(totalInterference, workloadAmongRemainingProcessors); - } + return copiedBins; + } - responseTime = minimumWcet + totalInterference; - } while (previousResponseTime != responseTime); + @Override + public PriorityManager getPriorityManager() { + return priorityManager; + } - return responseTime; - } + @Override + public String getName() { + return "Tester"; } } diff --git a/src/main/java/mvd/jester/tests/UeterAgrawal.java b/src/main/java/mvd/jester/tests/UeterAgrawal.java new file mode 100644 index 0000000..052a970 --- /dev/null +++ b/src/main/java/mvd/jester/tests/UeterAgrawal.java @@ -0,0 +1,191 @@ +package mvd.jester.tests; + +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import com.google.common.math.LongMath; +import mvd.jester.info.SchedulingInfo; +import mvd.jester.info.SchedulingInfo.Feasiblity; +import mvd.jester.model.DagTask; +import mvd.jester.model.LightTask; +import mvd.jester.model.SortedTaskSet; +import mvd.jester.model.SystemManagerInterface; +import mvd.jester.model.Task; +import mvd.jester.priority.EarliestDeadlineFirst; +import mvd.jester.priority.PriorityManager; + +public class UeterAgrawal extends AbstractTest { + + private final EarliestDeadlineFirst priorityManager; + private final Map stretchRatios; + + public UeterAgrawal(SystemManagerInterface manager) { + super(manager); + this.priorityManager = new EarliestDeadlineFirst(); + this.stretchRatios = new HashMap<>(); + } + + @Override + public SchedulingInfo runSchedulabilityCheck(SortedTaskSet tasks) { + stretchRatios.clear(); + assignThreadsAndStretchRatio(tasks); + + List bins = new ArrayList<>(); + + for (int i = 0; i < manager.getNumberOfProcessors(); ++i) { + bins.add((double) 0); + } + + for (DagTask t : tasks) { + if (t.getNumberOfThreads() == 1) { // Light task + if (!bestFitBinPackingOfTask(bins, t)) { + return new SchedulingInfo(Feasiblity.FAILED); + } + } else { // heavy task + boolean failure = true; + long numberOfServers = 0; + List binsWithTask = copyBins(bins); + final List listOfServerTasks = new ArrayList<>(); + listOfServerTasks.add(t); + while (numberOfServers <= checkNumberOfServers(t)) { + if (!binPackingOfServers(binsWithTask, listOfServerTasks)) { + binsWithTask = copyBins(bins); + numberOfServers += 1; + + listOfServerTasks.clear(); + for (int l = 0; l < numberOfServers; ++l) { + long reservationBudget = (long) Math.ceil((double) t.getWorkload() + / numberOfServers + + (1 - (double) 1 / numberOfServers) * t.getCriticalPath()); + + listOfServerTasks.add(new LightTask(t.getPeriod(), t.getDeadline(), + reservationBudget)); + } + } else { + failure = false; + bins = binsWithTask; + break; + } + } + + if (failure) { + return new SchedulingInfo(Feasiblity.FAILED); + } + } + } + + return new SchedulingInfo(Feasiblity.SUCCEEDED); + + } + + private List copyBins(List bins) { + List copiedBins = new ArrayList<>(); + + for (Double b : bins) { + copiedBins.add(b.doubleValue()); + } + + return copiedBins; + } + + private long checkNumberOfServers(DagTask task) { + final long criticalPath = task.getCriticalPath(); + final long workload = task.getWorkload(); + final double strechRatio = stretchRatios.get(task); + + final long first = LongMath.divide(workload, criticalPath, RoundingMode.CEILING); + final long second = (long) Math + .ceil(((double) workload - criticalPath) / (criticalPath * (strechRatio - 1))); + + // TODO: include fucking boundaries + final long max = Math.max(first, second); + + return max; + } + + + private boolean binPackingOfServers(List bins, List tasks) { + for (Task t : tasks) { + if (!bestFitBinPackingOfTask(bins, t)) { + return false; + } + } + return true; + } + + private boolean bestFitBinPackingOfTask(List bins, Task task) { + int bestFit = 0; // No one at first + for (int b = 0; b < bins.size(); ++b) { + if (bins.get(b) + task.getDensity() <= 1) { + double currentBin = bins.get(b); + double bestBin = bins.get(bestFit); + + if (currentBin + task.getDensity() > bestBin + task.getDensity() || bestBin + task.getDensity() > 1) { + bestFit = b; + } + } + } + if (bins.get(bestFit) + task.getDensity() <= 1) { + bins.set(bestFit, bins.get(bestFit) + task.getDensity()); + return true; + } + return false; + } + + private boolean firstFitBinPackingOfTask(List bins, Task task) { + Collections.sort(bins); + Collections.reverse(bins); + for (int b = 0; b < bins.size(); ++b) { + if (bins.get(b) + task.getDensity() <= 1) { + bins.set(b, bins.get(b) + task.getDensity()); + return true; + } + } + return false; + } + + private boolean worstFitBinPackingOfTask(List bins, Task task) { + Collections.sort(bins); + if (bins.get(0) + task.getDensity() <= 1) { + bins.set(0, bins.get(0) + task.getDensity()); + return true; + } else { + return false; + } + } + + private void assignThreadsAndStretchRatio(Set tasks) { + for (DagTask t : tasks) { + final long criticalPath = t.getCriticalPath(); + final long workload = t.getWorkload(); + long numberOfThreads = LongMath.divide(workload - criticalPath, + t.getDeadline() - criticalPath, RoundingMode.CEILING); + + if (numberOfThreads == 0) { + numberOfThreads = 1; + } + t.setNumberOfThreads(numberOfThreads); + + final double stretchRatio = + 1 + ((double) workload - criticalPath) / (numberOfThreads * criticalPath); + + stretchRatios.put(t, stretchRatio); + } + + } + + @Override + public PriorityManager getPriorityManager() { + return priorityManager; + } + + @Override + public String getName() { + return "UeterAgrawal"; + } + +}