SystemManager.java 13.2 KB
Newer Older
1 2
package mvd.jester.model;

3
import java.util.HashSet;
4
import java.util.LinkedHashSet;
5 6
import java.util.Map;
import java.util.Optional;
7 8
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
9 10 11 12
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge;
13
import mvd.jester.utils.DagUtils;
14 15 16 17

/**
 * TaskSet
 */
Michael Schmid committed
18 19
public class SystemManager {
    private long numberOfProcessors;
20

Michael Schmid committed
21
    public SystemManager(final long numberOfProcessors) {
22 23 24 25 26 27 28 29 30 31
        this.numberOfProcessors = numberOfProcessors;
    }

    /**
     * @return the numberOfProcessors
     */
    public long getNumberOfProcessors() {
        return numberOfProcessors;
    }

Michael Schmid committed
32 33 34 35 36
    /**
     * @param numberOfProcessors the numberOfProcessors to set
     */
    public void setNumberOfProcessors(long numberOfProcessors) {
        this.numberOfProcessors = numberOfProcessors;
37 38
    }

39
    public static class SynchronousTaskBuilder {
40 41
        private long numberOfProcessors = 4;
        private long minPeriod = 100;
Michael Schmid committed
42 43
        private long maxSequentialPeriod = 1000;
        private long maxParallelPeriod = 10000;
44 45 46 47
        private long minNumberOfSegments = 3;
        private long maxNumberOfSegments = 7;
        private long minNumberOfJobs = 2;
        private long maxNumberOfJobs = 3 * numberOfProcessors / 2;
48
        private final long minWcet = 1;
49
        private long ratio = randomTaskRatio(this.parallelTaskRatio);
50
        private final long parallelTaskRatio = 0;
51

52
        public SynchronousTaskBuilder() {
53 54 55

        }

Michael Schmid committed
56 57 58 59 60 61
        private long randomSequentialTaskPeriod() {
            return ThreadLocalRandom.current().nextLong(minPeriod, maxSequentialPeriod);
        }

        private long randomParallelTaskPeriod() {
            return ThreadLocalRandom.current().nextLong(minPeriod, maxParallelPeriod);
62 63
        }

64
        private long randomTaskRatio(final long min) {
65
            return ThreadLocalRandom.current().nextLong(min, 100);
66 67 68 69 70 71 72
        }

        private long randomNumberOfSegments() {
            return ThreadLocalRandom.current().nextLong(minNumberOfSegments, maxNumberOfSegments);
        }

        private long randomNumberOfJobs() {
73
            this.maxNumberOfJobs = 3 * this.numberOfProcessors / 2;
74 75 76
            return ThreadLocalRandom.current().nextLong(minNumberOfJobs, maxNumberOfJobs);
        }

77 78
        private long randomWcet(final long period, final long numberOfSegments) {
            final long maxWcet = period / numberOfSegments;
79 80 81 82

            return ThreadLocalRandom.current().nextLong(minWcet, maxWcet);
        }

83 84 85 86 87 88
        private SynchronousTask generateTask() {
            final boolean serial = randomTaskRatio(0) > this.ratio;
            final long period = serial ? randomSequentialTaskPeriod() : randomParallelTaskPeriod();
            final long numberOfSegments = serial ? 1 : randomNumberOfSegments();
            final long parallelNumberOfJobs = serial ? 1 : randomNumberOfJobs();
            final Set<Segment> segments = new LinkedHashSet<Segment>();
89

90
            for (int i = 0; i < numberOfSegments; ++i) {
91 92
                final long numberOfJobs = i % 2 == 1 ? parallelNumberOfJobs : 1;
                final long wcet = randomWcet(period, numberOfSegments);
93 94
                segments.add(new Segment(wcet, numberOfJobs));
            }
95
            return new SynchronousTask(segments, period, numberOfProcessors);
96 97
        }

98 99 100
        public Set<SynchronousTask> generateTaskSet() {
            this.ratio = randomTaskRatio(this.parallelTaskRatio);
            final Set<SynchronousTask> taskSet = new HashSet<>();
101

102
            for (int i = 0; i < numberOfProcessors; ++i) {
103
                final SynchronousTask task = generateTask();
104 105 106 107 108 109
                taskSet.add(task);
            }

            return taskSet;
        }

110 111 112 113 114
        // public SystemSetup<SynchronousTask> build() {
        // this.ratio = randomTaskRatio(this.parallelTaskRatio);
        // final Set<SynchronousTask> taskSet = generateTaskSet();
        // return new SystemSetup<>(taskSet, numberOfProcessors);
        // }
115

116 117 118 119
        // public Set<SynchronousTask> rebuild(final SystemSetup<SynchronousTask> systemSetup) {
        // this.ratio = randomTaskRatio(this.parallelTaskRatio);
        // return generateTaskSet();
        // }
120

121 122
        public boolean addTask(final Set<SynchronousTask> taskSet) {
            return taskSet.add(generateTask());
123 124
        }

125
        public SynchronousTaskBuilder setNumberOfProcessors(final long numberOfProcessors) {
126 127 128 129
            this.numberOfProcessors = numberOfProcessors;

            return this;
        }
130

131 132
        public SynchronousTaskBuilder setNumberOfSegments(final long minNumberOfSegments,
                final long maxNumberOfSegments) {
133 134 135 136 137 138
            this.minNumberOfSegments = minNumberOfSegments;
            this.maxNumberOfSegments = maxNumberOfSegments;

            return this;
        }

139 140
        public SynchronousTaskBuilder setPeriods(final long minPeriod,
                final long maxSequentialPeriod, final long maxParallelPeriod) {
141
            this.minPeriod = minPeriod;
Michael Schmid committed
142 143
            this.maxSequentialPeriod = maxSequentialPeriod;
            this.maxParallelPeriod = maxParallelPeriod;
144 145 146 147 148 149 150

            return this;
        }

        /**
         * @param maxNumberOfJobs the maxNumberOfJobs to set
         */
151 152
        public SynchronousTaskBuilder setNumberOfJobs(final long minNumberOfJobs,
                final long maxNumberOfJobs) {
153 154 155 156
            this.minNumberOfJobs = minNumberOfJobs;
            this.maxNumberOfJobs = maxNumberOfJobs;
            return this;
        }
157 158 159
    }

    public static class DagTaskBuilder {
Michael Schmid committed
160
        private long numberOfProcessors = 8;
161 162
        private long minimumWcet = 1;
        private long maximumWcet = 100;
Michael Schmid committed
163 164
        private long maxNumberOfBranches = 5;
        private long depth = 2;
165
        private long p_par = 80;
Michael Schmid committed
166
        private long p_add = 20;
167

Michael Schmid committed
168
        public DagTaskBuilder() {
169
        }
170

171
        public double getBeta() {
172 173 174 175
            return 0.035 * numberOfProcessors;
        }

        private long randomProbability() {
Michael Schmid committed
176
            return ThreadLocalRandom.current().nextLong(0, 100);
177 178
        }

Michael Schmid committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
        public Set<DagTask> generateUUnifastTaskSet(final long numberOfTasks,
                final double totalUtilization) {
            final LinkedHashSet<DagTask> taskSet = new LinkedHashSet<>();

            if (numberOfTasks > 0) {
                double sumU = totalUtilization;
                for (int i = 1; i <= numberOfTasks - 1; i++) {
                    Double nextSumU = sumU * Math.pow(ThreadLocalRandom.current().nextDouble(),
                            (1.0 / (double) (numberOfTasks - i)));
                    DagTask task = generateTask(sumU - nextSumU);
                    taskSet.add(task);
                    sumU = nextSumU;
                }
                DagTask task = generateTask(sumU);
                taskSet.add(task);
            }

            return taskSet;
        }

199
        public Set<DagTask> generateTaskSet(final double totalUtilization) {
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
            final LinkedHashSet<DagTask> taskSet = new LinkedHashSet<>();
            double currentUtilization = 0;
            while (currentUtilization <= totalUtilization) {
                final DagTask dagTask = generateTask();

                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;
        }

Michael Schmid committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237
        public DagTask generateTask(double utilization) {
            final DirectedAcyclicGraph<Job, DefaultEdge> jobDag =
                    new DirectedAcyclicGraph<>(DefaultEdge.class);

            final Job j = fork(jobDag, Optional.empty(), this.depth);
            fork(jobDag, Optional.of(j), this.depth);
            randomEdges(jobDag);

            final long workload = DagUtils.calculateWorkload(jobDag);

            final long period = Math.round(workload / utilization);

            return new DagTask(jobDag, period, numberOfProcessors);
        }
238 239 240 241 242 243 244

        public DagTask generateTask() {
            final DirectedAcyclicGraph<Job, DefaultEdge> jobDag =
                    new DirectedAcyclicGraph<>(DefaultEdge.class);

            final Job j = fork(jobDag, Optional.empty(), this.depth);
            fork(jobDag, Optional.of(j), this.depth);
245
            randomEdges(jobDag);
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

            final long workload = DagUtils.calculateWorkload(jobDag);
            final long criticalPath = DagUtils.calculateCriticalPath(jobDag);

            final long period = randomTaskPeriod(criticalPath, workload);

            return new DagTask(jobDag, period, numberOfProcessors);
        }

        private Job join(final DirectedAcyclicGraph<Job, DefaultEdge> jobDag, final Job current,
                final Set<Job> childs) {
            if (childs.size() > 0) {
                final Job job = new Job(randomWcet());
                jobDag.addVertex(job);
                for (final Job c : childs) {
                    try {
                        jobDag.addDagEdge(c, job);
                    } catch (final Exception e) {
                        System.out.println("Failed to join nodes!");
                    }
                }
                return job;
            }
            return current;
        }

        private Job fork(final DirectedAcyclicGraph<Job, DefaultEdge> jobDag,
                final Optional<Job> predecessor, final long depth) {
            final Job job = new Job(randomWcet());
            jobDag.addVertex(job);
            final Set<Job> childs = new HashSet<>();
            if (predecessor.isPresent()) {
                try {
                    jobDag.addDagEdge(predecessor.get(), job);
                } catch (final Exception e) {
                    System.out.println("Adding fork edge failed!");
                }
            }
284
            if (depth >= 0 && randomProbability() < p_par) {
285 286 287 288 289 290 291 292 293 294 295 296 297
                final long numberOfJobs = randomNumberOfBranches();
                for (int i = 0; i < numberOfJobs; ++i) {
                    childs.add(fork(jobDag, Optional.of(job), depth - 1));
                }
            }

            return join(jobDag, job, childs);
        }

        private void randomEdges(final DirectedAcyclicGraph<Job, DefaultEdge> jobDag) {
            final Multimap<Job, Job> edgePairs = ArrayListMultimap.create();
            for (final Job j1 : jobDag) {
                for (final Job j2 : jobDag) {
298
                    if (randomProbability() < p_add) {
299 300 301 302 303 304 305 306 307
                        edgePairs.put(j1, j2);
                    }
                }
            }

            for (final Map.Entry<Job, Job> pairs : edgePairs.entries()) {
                try {
                    jobDag.addDagEdge(pairs.getKey(), pairs.getValue());
                } catch (final Exception e) {
308
                    // nothing to do here
309 310 311 312 313
                }
            }
        }

        private long randomTaskPeriod(final long criticalPathLength, final long workload) {
Michael Schmid committed
314 315
            return ThreadLocalRandom.current().nextLong(criticalPathLength,
                    (long) (workload / getBeta()));
316 317 318
        }

        private long randomNumberOfBranches() {
Michael Schmid committed
319
            return ThreadLocalRandom.current().nextLong(2, maxNumberOfBranches);
320 321 322
        }

        private long randomWcet() {
Michael Schmid committed
323
            return ThreadLocalRandom.current().nextLong(minimumWcet, maximumWcet);
324 325 326 327 328 329 330 331 332 333
        }

        /**
         * @param numberOfProcessors the numberOfProcessors to set
         */
        public DagTaskBuilder setNumberOfProcessors(final long numberOfProcessors) {
            this.numberOfProcessors = numberOfProcessors;
            return this;
        }

Michael Schmid committed
334 335 336 337 338 339 340
        /**
         * @return the numberOfProcessors
         */
        public long getNumberOfProcessors() {
            return numberOfProcessors;
        }

341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
        public DagTaskBuilder setWcets(final long minimumWcet, final long maximumWcet) {
            this.minimumWcet = minimumWcet;
            this.maximumWcet = maximumWcet;
            return this;
        }

        /**
         * @param maxNumberOfBranches the maxNumberOfBranches to set
         */
        public DagTaskBuilder setMaxNumberOfBranches(final long maxNumberOfBranches) {
            this.maxNumberOfBranches = maxNumberOfBranches;
            return this;
        }

        public DagTaskBuilder setPropabilities(final long p_par, final long p_add) {
            this.p_par = p_par;
            this.p_add = p_add;
            return this;
        }
360

361 362 363 364 365 366 367
        /**
         * @param depth the depth to set
         */
        public DagTaskBuilder setDepth(final long depth) {
            this.depth = depth;
            return this;
        }
368 369
    }
}