diff --git a/src/main/java/mvd/jester/App.java b/src/main/java/mvd/jester/App.java index cb7d80b..7bb1714 100644 --- a/src/main/java/mvd/jester/App.java +++ b/src/main/java/mvd/jester/App.java @@ -2,14 +2,18 @@ package mvd.jester; import java.util.Arrays; import java.util.List; +import java.util.Set; import mvd.jester.model.DagTask; +import mvd.jester.model.SortedTaskSet; import mvd.jester.model.SystemManager; import mvd.jester.model.SystemManager.DagTaskBuilder; import mvd.jester.tests.AbstractTest; import mvd.jester.tests.FonsecaNelis; +import mvd.jester.tests.JiangYi; import mvd.jester.tests.MelaniButtazzo; import mvd.jester.tests.SchmidMottok; -import mvd.jester.tests.TypeFunction.KownStructure; +import mvd.jester.tests.TypeFunction.KnownStructureWithMaxThreads; +import mvd.jester.tests.TypeFunction.KnownStructure; import mvd.jester.tests.TypeFunction.UnkownStructure; @@ -20,51 +24,81 @@ import mvd.jester.tests.TypeFunction.UnkownStructure; public class App { public static void main(String[] args) { // { - // SystemManager manager = new SystemManager(8); - // DagTaskBuilder builder = new DagTaskBuilder(); - // TestEnvironment te = new TestEnvironment(); + // SystemManager manager = new SystemManager(8); + // DagTaskBuilder builder = new DagTaskBuilder(); + // TestEnvironment te = new TestEnvironment(); - // List> tests = - // te.registerTests(Arrays.asList(new SchmidMottok(new UnkownStructure(), manager), - // new SchmidMottok(new KownStructure(), manager), - // new MelaniButtazzo(manager), new FonsecaNelis(manager))); + // // SchmidMottok sm = new SchmidMottok(new KnownStructure(), manager); + // // JiangYi jy = new JiangYi(manager); - // te.varyUtilization(builder, tests, 8, 500); + // // Set set = builder.generateRenyiTaskSet(7.0); + // // final SortedTaskSet rmTasks = new SortedTaskSet<>(sm.getPriorityManager()); + // // rmTasks.addAll(set); + + // // final SortedTaskSet edfTasks = new SortedTaskSet<>(jy.getPriorityManager()); + // // edfTasks.addAll(set); + + // // jy.runSchedulabilityCheck(edfTasks); + // // sm.runSchedulabilityCheck(rmTasks); + + + // List> tests = te.registerTests(Arrays.asList( + // new SchmidMottok(new KnownStructureWithMaxThreads(manager), manager), + // new SchmidMottok(new KnownStructure(), manager), + // // new MelaniButtazzo(manager), + // // new FonsecaNelis(manager), + // new JiangYi(manager))); + + // te.varyRenyiUtilization(builder, tests, 8, 500); + // } + // { + // SystemManager manager = new SystemManager(8); + // DagTaskBuilder builder = new DagTaskBuilder(); + // TestEnvironment te = new TestEnvironment(); + + // List> tests = te.registerTests(Arrays.asList( + // new SchmidMottok(new KnownStructureWithMaxThreads(manager), manager), + // new SchmidMottok(new KnownStructure(), manager) + // // new MelaniButtazzo(manager) + // // , new FonsecaNelis(manager) + // )); + + // te.varyUtilization(builder, tests, 8, 500); + // } + // { + // SystemManager manager = new SystemManager(8); + // DagTaskBuilder builder = new DagTaskBuilder(); + // TestEnvironment te = new TestEnvironment(); + + // List> tests = + // te.registerTests(Arrays.asList(new SchmidMottok(new UnkownStructure(), manager), + // new SchmidMottok(new KownStructure(), manager), + // new MelaniButtazzo(manager), new FonsecaNelis(manager))); + + // te.varyNumberOfProcessors(builder, tests, manager, 500); // } // { - // SystemManager manager = new SystemManager(8); - // DagTaskBuilder builder = new DagTaskBuilder(); - // TestEnvironment te = new TestEnvironment(); + // SystemManager manager = new SystemManager(8); + // DagTaskBuilder builder = new DagTaskBuilder(); + // TestEnvironment te = new TestEnvironment(); - // List> tests = - // te.registerTests(Arrays.asList(new SchmidMottok(new UnkownStructure(), manager), - // new SchmidMottok(new KownStructure(), manager), - // new MelaniButtazzo(manager), new FonsecaNelis(manager))); + // List> tests = + // te.registerTests(Arrays.asList(new SchmidMottok(new UnkownStructure(), manager), + // new SchmidMottok(new KownStructure(), manager), + // new MelaniButtazzo(manager), new FonsecaNelis(manager))); - // te.varyNumberOfProcessors(builder, tests, manager, 500); + // te.varyNumberOfTasks(builder, tests, 8, 500); // } - { - SystemManager manager = new SystemManager(8); - DagTaskBuilder builder = new DagTaskBuilder(); - TestEnvironment te = new TestEnvironment(); - - List> tests = - te.registerTests(Arrays.asList(new SchmidMottok(new UnkownStructure(), manager), - new SchmidMottok(new KownStructure(), manager), - new MelaniButtazzo(manager), new FonsecaNelis(manager))); - - te.varyNumberOfTasks(builder, tests, 8, 500); - } // { - // SystemManager manager = new SystemManager(8); - // DagTaskBuilder builder = new DagTaskBuilder(); - // TestEnvironment te = new TestEnvironment(); + // SystemManager manager = new SystemManager(8); + // DagTaskBuilder builder = new DagTaskBuilder(); + // TestEnvironment te = new TestEnvironment(); - // List> tests = - // te.registerTests(Arrays.asList(new SchmidMottok(manager), - // new MelaniButtazzo(manager), new FonsecaNelis(manager))); + // List> tests = + // te.registerTests(Arrays.asList(new SchmidMottok(manager), + // new MelaniButtazzo(manager), new FonsecaNelis(manager))); - // te.measureExecutionTimes(builder, tests, manager, 500); + // te.measureExecutionTimes(builder, tests, manager, 500); // } } } diff --git a/src/main/java/mvd/jester/TestEnvironment.java b/src/main/java/mvd/jester/TestEnvironment.java index 8d57ad0..28a60bb 100644 --- a/src/main/java/mvd/jester/TestEnvironment.java +++ b/src/main/java/mvd/jester/TestEnvironment.java @@ -79,12 +79,13 @@ public class TestEnvironment { } public void measureExecutionTimes(final DagTaskBuilder builder, - final List> abstractTestInstances, - SystemManager manager, final long numberOfMeasurements) { + final List> abstractTestInstances, SystemManager manager, + final long numberOfMeasurements) { Map, List> results = new LinkedHashMap<>(); abstractTestInstances.forEach(t -> results.put(t, new ArrayList<>())); for (int i = 0; i < numberOfMeasurements; ++i) { - double utilization = ThreadLocalRandom.current().nextDouble(1, manager.getNumberOfProcessors()); + double utilization = + ThreadLocalRandom.current().nextDouble(1, manager.getNumberOfProcessors()); Set taskSet = builder.generateTaskSet(utilization); for (AbstractTest testInstance : abstractTestInstances) { final PriorityManager priorityManager = testInstance.getPriorityManager(); @@ -94,7 +95,7 @@ public class TestEnvironment { long timeBefore = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime(); testInstance.runSchedulabilityCheck(sortedTaskSet); long timeAfter = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime(); - long micros = (timeAfter-timeBefore)/1000; + long micros = (timeAfter - timeBefore) / 1000; results.get(testInstance).add(micros); } } @@ -125,7 +126,7 @@ public class TestEnvironment { final Set taskSet = builder.generateUUnifastTaskSet( (long) (1.5 * numberOfProcessors), (double) numberOfProcessors * 0.5); - System.out.print(checkedTasksets +"/"+ numberOfTaskSets + " tasksets tested!\r"); + System.out.print(checkedTasksets + "/" + numberOfTaskSets + " tasksets tested!\r"); for (final AbstractTest testInstance : abstractTestInstances) { final PriorityManager priorityManager = testInstance.getPriorityManager(); @@ -166,7 +167,7 @@ public class TestEnvironment { final Set taskSet = builder.generateUUnifastTaskSet(numberOfTasks, (double) numberOfProcessors * 0.5); - System.out.print(checkedTasksets +"/"+ numberOfTaskSets + " tasksets tested!\r"); + System.out.print(checkedTasksets + "/" + numberOfTaskSets + " tasksets tested!\r"); for (final AbstractTest testInstance : abstractTestInstances) { final PriorityManager priorityManager = testInstance.getPriorityManager(); @@ -206,7 +207,47 @@ public class TestEnvironment { for (int i = 0; i < numberOfTaskSetsPerUtil; ++i) { final Set taskSet = builder.generateTaskSet(util); - System.out.print(checkedTasksets +"/"+ numberOfTaskSets + " tasksets tested!\r"); + System.out.print(checkedTasksets + "/" + numberOfTaskSets + " tasksets tested!\r"); + for (final AbstractTest testInstance : abstractTestInstances) { + final PriorityManager priorityManager = testInstance.getPriorityManager(); + + final SortedTaskSet sortedTaskSet = + new SortedTaskSet<>(priorityManager); + sortedTaskSet.addAll(taskSet); + final SchedulingInfo schedulingInfo = + testInstance.runSchedulabilityCheck(sortedTaskSet); + + if (schedulingInfo.getFeasibility() == Feasiblity.SUCCEEDED) { + resultMap.computeIfPresent(testInstance, (k, v) -> v + 1); + } + } + checkedTasksets++; + } + resultLogger.logLine(util, resultMap); + resultLogger.newLine(); + } + System.out.println(""); + resultLogger.finalize(); + } + + public void varyRenyiUtilization(final DagTaskBuilder builder, + final List> abstractTestInstances, final long numberOfProcessors, + final long numberOfTaskSetsPerUtil) { + + long checkedTasksets = 0; + final long numberOfTaskSets = ((numberOfProcessors * 4) - 3) * numberOfTaskSetsPerUtil; + + final ResultLogger resultLogger = new ResultLogger("utilization_" + numberOfProcessors); + final Map, Long> resultMap = new LinkedHashMap<>(); + abstractTestInstances.forEach(t -> resultMap.put(t, (long) 0)); + resultLogger.logHeader(resultMap, "Utilization"); + + for (double util = 5; util <= numberOfProcessors; util += 0.25) { + resultMap.replaceAll((k, v) -> (long) 0); + for (int i = 0; i < numberOfTaskSetsPerUtil; ++i) { + final Set taskSet = builder.generateRenyiTaskSet(util); + + System.out.print(checkedTasksets + "/" + numberOfTaskSets + " tasksets tested!\r"); for (final AbstractTest testInstance : abstractTestInstances) { final PriorityManager priorityManager = testInstance.getPriorityManager(); diff --git a/src/main/java/mvd/jester/info/SchedulingInfo.java b/src/main/java/mvd/jester/info/SchedulingInfo.java index f83f2e0..64710db 100644 --- a/src/main/java/mvd/jester/info/SchedulingInfo.java +++ b/src/main/java/mvd/jester/info/SchedulingInfo.java @@ -15,6 +15,10 @@ public class SchedulingInfo { feasiblity = failedTerminationInfo.isPresent() ? Feasiblity.FAILED : Feasiblity.SUCCEEDED; } + public SchedulingInfo(Feasiblity feasiblity) { + this.feasiblity = feasiblity; + } + /** * @return the feasiblity */ @@ -25,72 +29,5 @@ public class SchedulingInfo { public enum Feasiblity { FAILED, SUCCEEDED, } - - - // private final double parallelTaskRatio; - // private final double utilization; - // private final Set terminationInfos; - // private Optional failedTerminationInfo; - - // public SchedulingInfo(double parallelTaskRatio, double utilization) { - // this.parallelTaskRatio = parallelTaskRatio; - // this.utilization = utilization; - // this.terminationInfos = new HashSet<>(); - // this.failedTerminationInfo = Optional.empty(); - // } - - // /** - // * @return the utilization - // */ - // public double getUtilization() { - // return utilization; - // } - - // /** - // * @return the parallelTaskRatio - // */ - // public double getParallelTaskRatio() { - // return parallelTaskRatio; - // } - - // public SchedulingInfo(Set terminationInfos, double parallelTaskRatio, - // double utilization) { - // this.terminationInfos = terminationInfos; - // this.parallelTaskRatio = parallelTaskRatio; - // this.utilization = utilization; - // failedTerminationInfo = - // terminationInfos.stream().filter(t -> t.getLateness() > 0).findFirst(); - // } - - // public boolean checkLevelFail(Level level) { - // return terminationInfos.stream() - // .anyMatch(t -> t.getLateness() > 0 && t.getTaskLevel() == level); - // } - - // public boolean checkTasksetFeasible() { - // // return terminationInfos.isEmpty(); - // return !terminationInfos.stream().anyMatch(t -> t.getLateness() > 0); - // } - - // public boolean addTerminationInfo(TerminationInfo terminationInfo) { - // return terminationInfos.add(terminationInfo); - // } - - // /** - // * @return the terminationInfos - // */ - // public Set getTerminationInfos() { - // return terminationInfos; - // } - - // /** - // * @return the failedTerminationInfo - // */ - // public Optional getFailedTerminationInfo() { - // return failedTerminationInfo; - // } - - // public void setFailedTerminationInfo(TerminationInfo failedTerminationInfo) { - // this.failedTerminationInfo = Optional.of(failedTerminationInfo); - // } } + diff --git a/src/main/java/mvd/jester/model/ContainerTask.java b/src/main/java/mvd/jester/model/ContainerTask.java new file mode 100644 index 0000000..4cac1f7 --- /dev/null +++ b/src/main/java/mvd/jester/model/ContainerTask.java @@ -0,0 +1,35 @@ +package mvd.jester.model; + +import java.util.HashSet; +import java.util.Set; + +public class ContainerTask extends Task { + + private final Set segments; + private final double loadBound; + + public ContainerTask(final long period, final long deadline, final double loadBound) { + super(period, deadline, (long) Math.ceil(loadBound * period), + (long) Math.ceil(loadBound * period), 1); + this.loadBound = loadBound; + segments = new HashSet<>(); + segments.add(new Segment(workload, 1)); + } + + + @Override + public Set getWorkloadDistribution() { + return segments; + } + + @Override + public double getDensity() { + return loadBound; + } + + @Override + public long getMaximumParallelism() { + return 1; + } + +} diff --git a/src/main/java/mvd/jester/model/DagTask.java b/src/main/java/mvd/jester/model/DagTask.java index 3c8163e..dfa30f3 100644 --- a/src/main/java/mvd/jester/model/DagTask.java +++ b/src/main/java/mvd/jester/model/DagTask.java @@ -5,38 +5,28 @@ import org.jgrapht.experimental.dag.DirectedAcyclicGraph; import org.jgrapht.graph.DefaultEdge; import mvd.jester.utils.DagUtils; -public class DagTask implements Task { +public class DagTask extends Task { private DirectedAcyclicGraph jobDag; private final Set workloadDistribution; - private final long workload; - private final long criticalPath; - private final long period; - private final long deadline; - private final long numberOfThreads; public DagTask(final DirectedAcyclicGraph jobDag, final long period, final long numberOfThreads) { + super(period, period, DagUtils.calculateWorkload(jobDag), + DagUtils.calculateCriticalPath(jobDag), numberOfThreads); this.jobDag = jobDag; - this.period = period; - this.deadline = period; - this.numberOfThreads = numberOfThreads; - this.workload = DagUtils.calculateWorkload(this.jobDag); - this.criticalPath = DagUtils.calculateCriticalPath(this.jobDag); this.workloadDistribution = DagUtils.calculateWorkloadDistribution(this.jobDag, this.criticalPath); } - public double getUtilization() { - return (double) workload / period; + public DagTask(final DirectedAcyclicGraph jobDag, final long period, + final Set workloadDistribution, final long numberOfThreads) { + super(period, period, DagUtils.calculateWorkload(jobDag), + DagUtils.calculateCriticalPath(jobDag), numberOfThreads); + this.jobDag = jobDag; + this.workloadDistribution = workloadDistribution; } - /** - * @return the deadline - */ - public long getDeadline() { - return deadline; - } /** * @return the jobDag @@ -53,30 +43,9 @@ public class DagTask implements Task { } /** - * @return the period - */ - public long getPeriod() { - return period; - } - - /** - * @return the workload - */ - public long getWorkload() { - return workload; - } - - /** - * @return the criticalPath - */ - public long getCriticalPath() { - return criticalPath; - } - - - /** * @return the workloadDistribution */ + @Override public Set getWorkloadDistribution() { return workloadDistribution; } @@ -92,10 +61,4 @@ public class DagTask implements Task { return max; } - - @Override - public long getNumberOfThreads() { - return numberOfThreads; - } - } diff --git a/src/main/java/mvd/jester/model/SynchronousTask.java b/src/main/java/mvd/jester/model/SynchronousTask.java index a37fca3..9427337 100644 --- a/src/main/java/mvd/jester/model/SynchronousTask.java +++ b/src/main/java/mvd/jester/model/SynchronousTask.java @@ -5,23 +5,15 @@ import java.util.Set; /** * Task */ -public class SynchronousTask implements Task { +public class SynchronousTask extends Task { - private final long deadline; - private final long period; private final Set segments; - private final long workload; - private final long criticalPath; - private final long numberOfThreads; public SynchronousTask(final long period, final long deadline, final long numberOfThreads, final Set segments) { - this.deadline = deadline; - this.period = period; - this.numberOfThreads = numberOfThreads; + super(period, deadline, SynchronousUtils.calculateWorkload(segments), + SynchronousUtils.calculateCriticalPath(segments), numberOfThreads); this.segments = segments; - this.workload = SynchronousUtils.calculateWorkload(segments); - this.criticalPath = SynchronousUtils.calculateCriticalPath(segments); } public SynchronousTask(final Set segments, final long period, diff --git a/src/main/java/mvd/jester/model/SystemManager.java b/src/main/java/mvd/jester/model/SystemManager.java index 97ba7d5..b02d357 100644 --- a/src/main/java/mvd/jester/model/SystemManager.java +++ b/src/main/java/mvd/jester/model/SystemManager.java @@ -1,5 +1,6 @@ package mvd.jester.model; +import java.math.RoundingMode; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map; @@ -8,6 +9,8 @@ import java.util.Set; import java.util.concurrent.ThreadLocalRandom; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; +import com.google.common.math.LongMath; +import org.apache.commons.math3.distribution.GammaDistribution; import org.jgrapht.experimental.dag.DirectedAcyclicGraph; import org.jgrapht.graph.DefaultEdge; import mvd.jester.utils.DagUtils; @@ -161,9 +164,10 @@ public class SystemManager { private long minimumWcet = 1; private long maximumWcet = 100; private long maxNumberOfBranches = 5; + private long maxNumberOfThreads = numberOfProcessors; private long depth = 2; private long p_par = 80; - private long p_add = 20; + private long p_add = 10; // TODO: Change back to 0.2 public DagTaskBuilder() { } @@ -176,6 +180,32 @@ public class SystemManager { return ThreadLocalRandom.current().nextLong(0, 100); } + public Set generateRenyiTaskSet(final double totalUtilization) { + final LinkedHashSet taskSet = new LinkedHashSet<>(); + + double currentUtilization = 0; + while (currentUtilization <= totalUtilization) { + final DagTask dagTask = generateRenyiTask(totalUtilization); + + if (currentUtilization + dagTask.getUtilization() < totalUtilization) { + currentUtilization += dagTask.getUtilization(); + taskSet.add(dagTask); + } else { + final double remainingUtilization = totalUtilization - currentUtilization; + final long period = + (long) Math.ceil(dagTask.getWorkload() / remainingUtilization); + if (period >= dagTask.getCriticalPath()) { + final DagTask modifiedTask = + new DagTask(dagTask.getJobDag(), period, numberOfProcessors); + taskSet.add(modifiedTask); + break; + } + } + } + + return taskSet; + } + public Set generateUUnifastTaskSet(final long numberOfTasks, final double totalUtilization) { final LinkedHashSet taskSet = new LinkedHashSet<>(); @@ -221,6 +251,65 @@ public class SystemManager { return taskSet; } + public DagTask generateRenyiTask(final double totalUtilization) { + final DirectedAcyclicGraph jobDag = + new DirectedAcyclicGraph<>(DefaultEdge.class); + final long numberOfVertices = randomNumberInRange(50, 250); + for (int i = 0; i < numberOfVertices - 2; ++i) { + final long wcet = randomNumberInRange(50, 100); + Job j = new Job(wcet); + jobDag.addVertex(j); + } + + randomEdgesRenyi(jobDag); + addSourceAndSink(jobDag); + + final long workload = DagUtils.calculateWorkload(jobDag); + final long criticalPath = DagUtils.calculateCriticalPath(jobDag); + final long period = randomRenyiPeriod(workload, criticalPath, totalUtilization); + + // final long numberOfThreads = LongMath.divide(workload - criticalPath, + // period - criticalPath, RoundingMode.CEILING) + 1; + + final long numberOfThreads = randomNumberOfThreads(numberOfProcessors / 2); + + return new DagTask(jobDag, period, numberOfThreads); + } + + private long randomRenyiPeriod(final long workload, final long criticalPath, + final double totalUtilization) { + final double firstPart = + (criticalPath + (double) (workload) / (0.4 * totalUtilization)); + final double gamma = new GammaDistribution(2, 1).sample(); + final double secondPart = 1 + 0.25 * gamma; + + return (long) Math.ceil(firstPart * secondPart); + } + + private void addSourceAndSink(final DirectedAcyclicGraph jobDag) { + final Multimap edgePairs = ArrayListMultimap.create(); + Job source = new Job(randomNumberInRange(50, 100)); + Job sink = new Job(randomNumberInRange(50, 100)); + jobDag.addVertex(source); + jobDag.addVertex(sink); + for (Job j : jobDag) { + if (jobDag.inDegreeOf(j) == 0) { + edgePairs.put(source, j); + } + if (jobDag.outDegreeOf(j) == 0) { + edgePairs.put(j, sink); + } + } + + for (final Map.Entry pairs : edgePairs.entries()) { + try { + jobDag.addDagEdge(pairs.getKey(), pairs.getValue()); + } catch (final Exception e) { + // nothing to do here + } + } + } + public DagTask generateTask(double utilization) { final DirectedAcyclicGraph jobDag = new DirectedAcyclicGraph<>(DefaultEdge.class); @@ -231,7 +320,7 @@ public class SystemManager { final long workload = DagUtils.calculateWorkload(jobDag); - final long period = Math.round(workload / utilization); + final long period = (long) Math.ceil(workload / utilization); return new DagTask(jobDag, period, numberOfProcessors); } @@ -249,7 +338,10 @@ public class SystemManager { final long period = randomTaskPeriod(criticalPath, workload); - return new DagTask(jobDag, period, numberOfProcessors); + final long minNumberOfThreads = LongMath.divide(workload, period, RoundingMode.CEILING); + final long numberOfThreads = randomNumberOfThreads(minNumberOfThreads); + + return new DagTask(jobDag, period, numberOfThreads); } private Job join(final DirectedAcyclicGraph jobDag, final Job current, @@ -310,6 +402,32 @@ public class SystemManager { } } + private void randomEdgesRenyi(final DirectedAcyclicGraph jobDag) { + final Multimap edgePairs = ArrayListMultimap.create(); + for (final Job j1 : jobDag) { + for (final Job j2 : jobDag) { + if (j2 == j1) { + break; + } + if (randomProbability() < p_add) { + edgePairs.put(j1, j2); + } + } + } + + for (final Map.Entry pairs : edgePairs.entries()) { + try { + jobDag.addDagEdge(pairs.getKey(), pairs.getValue()); + } catch (final Exception e) { + // nothing to do here + } + } + } + + private long randomNumberOfThreads(final long minNumberOfThreads) { + return ThreadLocalRandom.current().nextLong(minNumberOfThreads, maxNumberOfThreads); + } + private long randomTaskPeriod(final long criticalPathLength, final long workload) { return ThreadLocalRandom.current().nextLong(criticalPathLength, (long) (workload / getBeta())); @@ -319,6 +437,10 @@ public class SystemManager { return ThreadLocalRandom.current().nextLong(2, maxNumberOfBranches); } + private long randomNumberInRange(final long min, final long max) { + return ThreadLocalRandom.current().nextLong(min, max); + } + private long randomWcet() { return ThreadLocalRandom.current().nextLong(minimumWcet, maximumWcet); } @@ -358,6 +480,12 @@ public class SystemManager { return this; } + public DagTaskBuilder setNumberOfThreads(final long maxNumberOfThreads) { + this.maxNumberOfThreads = maxNumberOfThreads; + + return this; + } + /** * @param depth the depth to set */ diff --git a/src/main/java/mvd/jester/model/Task.java b/src/main/java/mvd/jester/model/Task.java index 640abb7..61cef5f 100644 --- a/src/main/java/mvd/jester/model/Task.java +++ b/src/main/java/mvd/jester/model/Task.java @@ -2,21 +2,53 @@ package mvd.jester.model; import java.util.Set; -public interface Task { - public long getWorkload(); +public abstract class Task { + protected final long period; + protected final long deadline; + protected final long workload; + protected final long criticalPath; + protected final long numberOfThreads; - public long getCriticalPath(); + public Task(final long period, final long deadline, final long workload, + final long criticalPath, final long numberOfThreads) { + this.period = period; + this.deadline = deadline; + this.workload = workload; + this.criticalPath = criticalPath; + this.numberOfThreads = numberOfThreads; - public double getUtilization(); + } - public long getMaximumParallelism(); + public long getWorkload() { + return workload; + } - public long getDeadline(); + public long getCriticalPath() { + return criticalPath; + } - public long getPeriod(); + public double getUtilization() { + return (double) workload / period; + } - public long getNumberOfThreads(); + public double getDensity() { + return (double) workload / deadline; + } - public Set getWorkloadDistribution(); + public long getDeadline() { + return deadline; + } + public long getPeriod() { + return period; + } + + public long getNumberOfThreads() { + return numberOfThreads; + } + + + abstract public long getMaximumParallelism(); + + abstract public Set getWorkloadDistribution(); } diff --git a/src/main/java/mvd/jester/simulator/internals/dynamicforkjoin/TaskContext.java b/src/main/java/mvd/jester/simulator/internals/dynamicforkjoin/TaskContext.java index e5648e1..de9c586 100644 --- a/src/main/java/mvd/jester/simulator/internals/dynamicforkjoin/TaskContext.java +++ b/src/main/java/mvd/jester/simulator/internals/dynamicforkjoin/TaskContext.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.Optional; import mvd.jester.model.Segment; import mvd.jester.model.SynchronousTask; -import mvd.jester.simulator.EventPrinter; import mvd.jester.simulator.internals.JobContextInterface; import mvd.jester.simulator.internals.TaskContextInterface; diff --git a/src/main/java/mvd/jester/tests/JiangYi.java b/src/main/java/mvd/jester/tests/JiangYi.java new file mode 100644 index 0000000..bcea409 --- /dev/null +++ b/src/main/java/mvd/jester/tests/JiangYi.java @@ -0,0 +1,102 @@ +package mvd.jester.tests; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import mvd.jester.info.SchedulingInfo; +import mvd.jester.info.SchedulingInfo.Feasiblity; +import mvd.jester.model.ContainerTask; +import mvd.jester.model.DagTask; +import mvd.jester.model.SortedTaskSet; +import mvd.jester.model.SystemManager; +import mvd.jester.model.Task; +import mvd.jester.priority.EarliestDeadlineFirst; +import mvd.jester.priority.PriorityManager; + +public class JiangYi extends AbstractTest { + + private final EarliestDeadlineFirst priorityManager; + + public JiangYi(SystemManager manager) { + super(manager); + this.priorityManager = new EarliestDeadlineFirst(); + } + + + + @Override + public SchedulingInfo runSchedulabilityCheck(SortedTaskSet tasks) { + Set heavyTasks = new HashSet<>(); + Set lightTasks = new HashSet<>(); + + for (DagTask t : tasks) { + if (t.getUtilization() < 1) { + lightTasks.add(t); + } else { + heavyTasks.add(t); + } + } + + long remainingProcessors = manager.getNumberOfProcessors(); + + for (DagTask t : heavyTasks) { + double processingCapacity = ((double) t.getWorkload() - t.getCriticalPath()) + / (t.getDeadline() - t.getCriticalPath()); + long minimumProcessingCapacity = (long) Math.floor(processingCapacity); + if (remainingProcessors < minimumProcessingCapacity) { + return new SchedulingInfo(Feasiblity.FAILED); + } + remainingProcessors -= minimumProcessingCapacity; + + double loadBound = processingCapacity - minimumProcessingCapacity; + + lightTasks.add(new ContainerTask(t.getPeriod(), t.getDeadline(), loadBound)); + } + + return scheduleLightTasks(lightTasks, remainingProcessors); + } + + private SchedulingInfo scheduleLightTasks(Set tasks, long numberOfprocessors) { + if (numberOfprocessors == 0 && tasks.size() > 0) { + return new SchedulingInfo(Feasiblity.FAILED); + } + List taskList = new LinkedList<>(tasks); + 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); + Task t = taskIterator.next(); + taskIterator.remove(); + if (bins.get(0) + t.getDensity() <= 1) { + bins.set(0, bins.get(0) + t.getDensity()); + } else { + return new SchedulingInfo(Feasiblity.FAILED); + } + + } + + return new SchedulingInfo(Feasiblity.SUCCEEDED); + } + + + @Override + public PriorityManager getPriorityManager() { + return priorityManager; + } + + @Override + public String getName() { + return "JiangYi"; + } + +} diff --git a/src/main/java/mvd/jester/tests/SchmidMottok.java b/src/main/java/mvd/jester/tests/SchmidMottok.java index 82396ba..0fb1383 100644 --- a/src/main/java/mvd/jester/tests/SchmidMottok.java +++ b/src/main/java/mvd/jester/tests/SchmidMottok.java @@ -46,7 +46,7 @@ public class SchmidMottok extends AbstractTest { @Override public String getName() { - return "SchmidMottok"+ "_" + structure.getType(); + return "SchmidMottok" + "_" + structure.getType(); } private long calculateResponseTime(final Set tasks, final DagTask task) { @@ -58,18 +58,31 @@ public class SchmidMottok extends AbstractTest { previousResponseTime = responseTime; double taskInterference = 0; + long occupiedProcessors = manager.getNumberOfProcessors() + 1; + // for (final DagTask t : tasks) { + // if (t.getPeriod() < task.getPeriod()) { + // final long numberOfProcessors = structure.getNumerOfThreads(t); + // occupiedProcessors += numberOfProcessors; + // } + // } + for (final DagTask t : tasks) { if (t.getPeriod() < task.getPeriod()) { - final long numberOfThreads = t.getNumberOfThreads(); - for (int p = 0; p < numberOfThreads; ++p) { - taskInterference += Math.min(structure.getTaskInterference(t, responseTimes, responseTime, p + 1), - responseTime - minimumWcet + 1); + final long numberOfProcessors = structure.getNumerOfThreads(t); + for (int p = 0; p < numberOfProcessors; ++p) { + if (occupiedProcessors > manager.getNumberOfProcessors()) { + taskInterference += + Math.min( + structure.getTaskInterference(t, responseTimes, + responseTime, p + 1), + responseTime - minimumWcet + 1); + } } } } taskInterference /= manager.getNumberOfProcessors(); - final double selfInterference = getSelfInterference(task); + final double selfInterference = structure.getSelfInterference(task); final long totalInterference = (long) Math.floor(taskInterference + selfInterference); @@ -79,45 +92,4 @@ public class SchmidMottok extends AbstractTest { return responseTime; } - - private double getSelfInterference(final DagTask task) { - // final long numberOfThreads = task.getNumberOfThreads(); - // TODO: Change back to number of threads - final long numberOfThreads = manager.getNumberOfProcessors(); - - double interference = task.getWorkload() - task.getCriticalPath(); - interference /= numberOfThreads; - - return interference; - } - - - // private double getTaskInterference(final DagTask task, final long interval, - // final long parallelism) { - // if (responseTimes.containsKey(task)) { - // final long responseTime = responseTimes.get(task).getResponseTime(); - // final long minWcet = task.getCriticalPath(); - // final long period = task.getPeriod(); - // final long amountOfJobs = - // (LongMath.divide(interval + responseTime - minWcet, period, RoundingMode.FLOOR) - // + 1); - - // double workload = 0; - - // for (final Segment s : task.getWorkloadDistribution()) { - // final long numberOfThreads = - // s.getNumberOfJobs() > 1 ? task.getNumberOfThreads() : 1; - // if (numberOfThreads >= parallelism) { - // workload += (double)(s.getNumberOfJobs() * s.getJobWcet()) / numberOfThreads; - // } - // } - - // final double interference = amountOfJobs * workload; - - // return interference; - // } else { - // throw new RuntimeException("Task was not found in task set!"); - // } - // } - } diff --git a/src/main/java/mvd/jester/tests/TypeFunction.java b/src/main/java/mvd/jester/tests/TypeFunction.java index 5b4f142..a972f02 100644 --- a/src/main/java/mvd/jester/tests/TypeFunction.java +++ b/src/main/java/mvd/jester/tests/TypeFunction.java @@ -6,39 +6,48 @@ import com.google.common.math.LongMath; import mvd.jester.info.TerminationInfo; import mvd.jester.model.DagTask; import mvd.jester.model.Segment; +import mvd.jester.model.SystemManager; import mvd.jester.model.Task; public interface TypeFunction { public double getTaskInterference(final DagTask task, - final Map responseTimes, - final long interval, + final Map responseTimes, final long interval, final long parallelism); + public double getSelfInterference(final DagTask task); + + public long getNumerOfThreads(final DagTask task); + public String getType(); - public class UnkownStructure implements TypeFunction { - + public class KnownStructureWithMaxThreads implements TypeFunction { + + private final SystemManager manager; + + public KnownStructureWithMaxThreads(final SystemManager manager) { + this.manager = manager; + } + @Override public double getTaskInterference(final DagTask task, - final Map responseTimes, - final long interval, + final Map responseTimes, final long interval, final long parallelism) { if (responseTimes.containsKey(task)) { final long responseTime = responseTimes.get(task).getResponseTime(); final long minWcet = task.getCriticalPath(); final long period = task.getPeriod(); - final long amountOfJobs = - (LongMath.divide(interval + responseTime - minWcet, period, RoundingMode.FLOOR) - + 1); + final long amountOfJobs = (LongMath.divide(interval + responseTime - minWcet, + period, RoundingMode.FLOOR) + 1); double workload = 0; for (final Segment s : task.getWorkloadDistribution()) { final long numberOfThreads = - task.getNumberOfThreads(); + s.getNumberOfJobs() > 1 ? manager.getNumberOfProcessors() : 1; if (numberOfThreads >= parallelism) { - workload += (double)(s.getNumberOfJobs() * s.getJobWcet()) / numberOfThreads; + workload += + (double) (s.getNumberOfJobs() * s.getJobWcet()) / numberOfThreads; } } @@ -51,25 +60,90 @@ public interface TypeFunction { } @Override + public double getSelfInterference(final DagTask task) { + final long numberOfThreads = manager.getNumberOfProcessors(); + + double interference = task.getWorkload() - task.getCriticalPath(); + interference /= numberOfThreads; + + return interference; + } + + @Override + public String getType() { + return "SKP"; + } + + @Override + public long getNumerOfThreads(final DagTask task) { + return manager.getNumberOfProcessors(); + } + } + + public class UnkownStructure implements TypeFunction { + + @Override + public double getTaskInterference(final DagTask task, + final Map responseTimes, final long interval, + final long parallelism) { + if (responseTimes.containsKey(task)) { + final long responseTime = responseTimes.get(task).getResponseTime(); + final long minWcet = task.getCriticalPath(); + final long period = task.getPeriod(); + final long amountOfJobs = (LongMath.divide(interval + responseTime - minWcet, + period, RoundingMode.FLOOR) + 1); + + double workload = 0; + + for (final Segment s : task.getWorkloadDistribution()) { + final long numberOfThreads = task.getNumberOfThreads(); + if (numberOfThreads >= parallelism) { + workload += + (double) (s.getNumberOfJobs() * s.getJobWcet()) / numberOfThreads; + } + } + + final double interference = amountOfJobs * workload; + + return interference; + } else { + throw new RuntimeException("Task was not found in task set!"); + } + } + + @Override + public double getSelfInterference(final DagTask task) { + final long numberOfThreads = task.getNumberOfThreads(); + + double interference = task.getWorkload() - task.getCriticalPath(); + interference /= numberOfThreads; + + return interference; + } + + @Override public String getType() { return "SU"; } + + @Override + public long getNumerOfThreads(final DagTask task) { + return task.getNumberOfThreads(); + } } - public class KownStructure implements TypeFunction { - + public class KnownStructure implements TypeFunction { + @Override public double getTaskInterference(final DagTask task, - final Map responseTimes, - final long interval, + final Map responseTimes, final long interval, final long parallelism) { if (responseTimes.containsKey(task)) { final long responseTime = responseTimes.get(task).getResponseTime(); final long minWcet = task.getCriticalPath(); final long period = task.getPeriod(); - final long amountOfJobs = - (LongMath.divide(interval + responseTime - minWcet, period, RoundingMode.FLOOR) - + 1); + final long amountOfJobs = (LongMath.divide(interval + responseTime - minWcet, + period, RoundingMode.FLOOR) + 1); double workload = 0; @@ -77,7 +151,8 @@ public interface TypeFunction { final long numberOfThreads = s.getNumberOfJobs() > 1 ? task.getNumberOfThreads() : 1; if (numberOfThreads >= parallelism) { - workload += (double)(s.getNumberOfJobs() * s.getJobWcet()) / numberOfThreads; + workload += + (double) (s.getNumberOfJobs() * s.getJobWcet()) / numberOfThreads; } } @@ -90,9 +165,24 @@ public interface TypeFunction { } @Override + public double getSelfInterference(final DagTask task) { + final long numberOfThreads = task.getNumberOfThreads(); + + double interference = task.getWorkload() - task.getCriticalPath(); + interference /= numberOfThreads; + + return interference; + } + + @Override public String getType() { return "SK"; } + + @Override + public long getNumerOfThreads(final DagTask task) { + return task.getNumberOfThreads(); + } } - -} \ No newline at end of file + +} diff --git a/src/test/java/mvd/jester/priority/TestEarliestDeadlineFirst.java b/src/test/java/mvd/jester/priority/TestEarliestDeadlineFirst.java index 341ae7f..517f580 100644 --- a/src/test/java/mvd/jester/priority/TestEarliestDeadlineFirst.java +++ b/src/test/java/mvd/jester/priority/TestEarliestDeadlineFirst.java @@ -57,7 +57,7 @@ public class TestEarliestDeadlineFirst { assertTrue(edf.hasSimulator(DynamicForkJoin.class)); assertTrue(edf.hasTest(new ChwaLee(manager))); - assertFalse(edf.hasTest(new SchmidMottok(new TypeFunction.KownStructure(), manager))); + assertFalse(edf.hasTest(new SchmidMottok(new TypeFunction.KnownStructure(), manager))); assertFalse(edf.hasTest(new MaiaBertogna(manager))); // assertTrue(edf.hasSimulator(new ParallelSynchronous(mock(SystemSetup.class)))); // assertTrue(edf.hasSimulator(new DynamicForkJoin(mock(SystemSetup.class))));