Java tutorial
/* * TURNUS, the co-exploration framework * * Copyright (C) 2014 EPFL SCI STI MM * * This file is part of TURNUS. * * TURNUS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * TURNUS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with TURNUS. If not, see <http://www.gnu.org/licenses/>. * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining it * with Eclipse (or a modified version of Eclipse or an Eclipse plugin or * an Eclipse library), containing parts covered by the terms of the * Eclipse Public License (EPL), the licensors of this Program grant you * additional permission to convey the resulting work. Corresponding Source * for a non-source form of such a combination shall include the source code * for the parts of Eclipse libraries used as well as that of the covered work. * */ package co.turnus.analysis.pipelining; import static co.turnus.trace.TraceOptions.SENS_FSM; import static co.turnus.trace.TraceOptions.SENS_GUARD; import static co.turnus.trace.TraceOptions.SENS_PORT; import static co.turnus.trace.TraceOptions.SENS_STATEVAR; import static co.turnus.trace.TraceOptions.SENS_TOKENS; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.configuration.BaseConfiguration; import org.apache.commons.configuration.Configuration; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; import co.turnus.analysis.Analysis; import co.turnus.analysis.data.pipelining.PipeliningFactory; import co.turnus.analysis.data.pipelining.SimpleActionPipeliningData; import co.turnus.analysis.data.pipelining.SimplePipelingData; import co.turnus.common.util.CommonDataUtil; import co.turnus.dataflow.Action; import co.turnus.dataflow.Actor; import co.turnus.dataflow.Network; import co.turnus.generic.Pair; import co.turnus.trace.Dependency; import co.turnus.trace.Dependency.Direction; import co.turnus.trace.Dependency.Kind; import co.turnus.trace.Step; import co.turnus.trace.Trace; import co.turnus.trace.TraceDecorator; import co.turnus.trace.TraceProject; import co.turnus.util.ProgressTheadPrinter; import co.turnus.util.TurnusLogger; public class SimplePipelining extends Analysis { private class ActorData { private class ActionData { long firings; Map<Action, Boolean> splittable; SummaryStatistics statsUnconstrained; SummaryStatistics statsPipelinabled; ActionData() { splittable = new HashMap<>(); statsPipelinabled = new SummaryStatistics(); statsUnconstrained = new SummaryStatistics(); firings = 0; } void addFiring(Iterable<Dependency> incomings) { firings++; for (Dependency d : incomings) { Pair<Actor, Action> pair = traceDecorator.getActorActionPair(d.getSource()); if (pair.a == actor) { Action action = pair.b; if (d.getKind() != Kind.STATEVAR) { if (!splittable.containsKey(action)) { splittable.put(action, true); } else { boolean val = splittable.get(action) & true; splittable.put(action, val); } } else { if (d.getDirection() == Direction.READ_READ) { if (!splittable.containsKey(action)) { splittable.put(action, true); } else { boolean val = splittable.get(action) & true; splittable.put(action, val); } } else { splittable.put(action, false); } } } } } void addStatistics(long unconstrained, long pipelinable) { statsUnconstrained.addValue(unconstrained); statsPipelinabled.addValue(pipelinable); } SimpleActionPipeliningData collectResults() { SimpleActionPipeliningData data = PipeliningFactory.eINSTANCE.createSimpleActionPipeliningData(); data.setFirings(firings); data.setPipelinableRepetitions(CommonDataUtil.createFrom(statsPipelinabled)); data.setUnconstrainedRepetitions(CommonDataUtil.createFrom(statsUnconstrained)); for (Entry<Action, Boolean> entry : splittable.entrySet()) { if (entry.getValue().booleanValue()) { data.getSplittableActions().add(entry.getKey()); } } return data; } } final Actor actor; Map<Action, ActionData> actionsData; Action lastFiredAction; long uncostrainedConsecFirinings; long pipelinableConsecFirinings; ActorData(Actor actor) { this.actor = actor; } void addFiring(Pair<Actor, Action> pair, Iterable<Dependency> incomings) { // update the last firings Action action = pair.getB(); if (lastFiredAction != action) { if (lastFiredAction != null) { actionsData.get(lastFiredAction).addStatistics(uncostrainedConsecFirinings, pipelinableConsecFirinings); } lastFiredAction = action; uncostrainedConsecFirinings = 1; pipelinableConsecFirinings = 0; } else { boolean pipelieable = true; for (Dependency d : incomings) { if ((d.getKind() == Kind.STATEVAR) && (d.getDirection() != Direction.READ_READ)) { pipelieable = false; break; } } // update counters uncostrainedConsecFirinings++; if (pipelieable) { pipelinableConsecFirinings++; } else { pipelinableConsecFirinings = 0; } } // update action data actionsData.get(action).addFiring(incomings); } Collection<SimpleActionPipeliningData> collectResults() { Collection<SimpleActionPipeliningData> dataSet = new HashSet<>(); for (Entry<Action, ActionData> entry : actionsData.entrySet()) { SimpleActionPipeliningData data = entry.getValue().collectResults(); data.setActor(actor); data.setAction(entry.getKey()); dataSet.add(data); } return dataSet; } void endAnalysis() { if (lastFiredAction != null) { actionsData.get(lastFiredAction).addStatistics(uncostrainedConsecFirinings, pipelinableConsecFirinings); } lastFiredAction = null; uncostrainedConsecFirinings = 0; uncostrainedConsecFirinings = 0; } void initData() { uncostrainedConsecFirinings = 0; pipelinableConsecFirinings = 0; lastFiredAction = null; actionsData = new HashMap<>(); for (Action a : actor.getActorClass().getActions()) { actionsData.put(a, new ActionData()); } } } private TraceProject traceProject; private TraceDecorator traceDecorator; private Map<Actor, ActorData> actorsData; private Network network; public SimplePipelining(TraceProject traceProject) { this.traceProject = traceProject; network = traceProject.getNetwork(); traceDecorator = traceProject.getTraceDecorator(); actorsData = new HashMap<>(); for (Actor a : network.getActors()) { actorsData.put(a, new ActorData(a)); } } private SimplePipelingData collectResults() { SimplePipelingData report = PipeliningFactory.eINSTANCE.createSimplePipelingData(); report.setNetwork(network); report.setName("Simple Pipelining Analysis Report Data"); report.setAlgorithm(SimplePipelining.class.getName()); for (ActorData data : actorsData.values()) { report.getActionsData().addAll(data.collectResults()); } // FIXME should be replaced with report.toString() ? TurnusLogger.debug("Simple Pipelining Analysis Report Data:"); for (SimpleActionPipeliningData data : report.getActionsData()) { TurnusLogger.debug("Actor: " + data.getActor().getId() + ", action: " + data.getAction().getId()); TurnusLogger.debug("-> firings: " + data.getFirings() + ", consec (p, u): " + data.getPipelinableRepetitions().getMean() + ", " + data.getUnconstrainedRepetitions().getMean()); TurnusLogger.debug("-> splittable actions: "); for (Action a : data.getSplittableActions()) { TurnusLogger.debug(" " + a.getId()); } } return report; } private void initTrace() { if (!traceProject.isTraceLoaded()) { Configuration config = new BaseConfiguration(); config.setProperty(SENS_STATEVAR, true); config.setProperty(SENS_FSM, false); config.setProperty(SENS_PORT, false); config.setProperty(SENS_GUARD, false); config.setProperty(SENS_TOKENS, false); traceProject.loadTrace(config); } } @Override public SimplePipelingData run() { // check if the trace should be loaded initTrace(); Trace trace = traceProject.getTrace(); long traceSize = trace.getLength(); // launch the thread status printer ProgressTheadPrinter progressPrinter = new ProgressTheadPrinter("Trace Graph post-processing", traceSize); progressPrinter.start(); // init the actors data for (ActorData d : actorsData.values()) { d.initData(); } // start the trace analysis for (long stepId = 0; stepId < traceSize; stepId++) { Step step = trace.getStep(stepId); Pair<Actor, Action> pair = traceDecorator.getActorActionPair(step); actorsData.get(pair.getA()).addFiring(pair, step.getIncomings()); progressPrinter.increment(); } // end the analysis for (ActorData d : actorsData.values()) { d.endAnalysis(); } // stop the progress monitor try { progressPrinter.finish(); progressPrinter.join(); } catch (InterruptedException e) { TurnusLogger.warning("Progress monitor stopping error: " + e.getMessage()); } return collectResults(); } }