From: Gary P. <gpa...@gm...> - 2009-07-27 09:45:29
|
Patch has been applied onto next. This should resolve some of the Multi Objective problems. Let us know if there are other issues related to this patch. On Friday 24 July 2009 12:27:43 Gary Pampara wrote: > These changes prevent the leaking of ThreadLocal variables. Previously > the simulation object graphs were created ahead of time and then > executed in threads. This effectively resulted in the ThreadLocal > variable being placed on the main thread and _not_ the intended > simulation thread. Yes, this is BAD. > > Created a logical separation and ensured that the object graph > construction occurs within the simulation thread and not in the main > thread. > > Tested-by: Wiehann Matthysen <wcm...@gm...> > Signed-off-by: Gary Pampara <gpa...@gm...> > --- > .../java/net/sourceforge/cilib/simulator/Main.java | 9 +- > .../sourceforge/cilib/simulator/Simulation.java | 202 > +++++++------------- .../simulator/{Simulation.java => Simulator.java} | > 108 ++++------- .../net/sourceforge/cilib/xml/XMLFileTest.java | 4 > +- > 4 files changed, 114 insertions(+), 209 deletions(-) > copy src/main/java/net/sourceforge/cilib/simulator/{Simulation.java => > Simulator.java} (52%) > > diff --git a/src/main/java/net/sourceforge/cilib/simulator/Main.java > b/src/main/java/net/sourceforge/cilib/simulator/Main.java index > 452702a..88246cb 100644 > --- a/src/main/java/net/sourceforge/cilib/simulator/Main.java > +++ b/src/main/java/net/sourceforge/cilib/simulator/Main.java > @@ -58,14 +58,13 @@ public final class Main { > XMLProblemFactory problemFactory = new > XMLProblemFactory(config, (Element) > current.getElementsByTagName("problem").item(0)); XMLObjectFactory > measurementsFactory = new XMLObjectFactory(config, (Element) > current.getElementsByTagName("measurements").item(0)); MeasurementSuite > suite = (MeasurementSuite) measurementsFactory.newObject(); - > Simulation simulation = new Simulation(algorithmFactory, problemFactory, > suite); + Simulator simulator = new Simulator(algorithmFactory, > problemFactory, suite); if(progress != null) { > - simulation.addProgressListener(progress); > + simulator.addProgressListener(progress); > } > > - simulation.initialise(); > - simulation.run(); > - simulation = null; > + simulator.execute(); > + simulator = null; > System.gc(); > } > } > diff --git a/src/main/java/net/sourceforge/cilib/simulator/Simulation.java > b/src/main/java/net/sourceforge/cilib/simulator/Simulation.java index > 377dd5c..57dc736 100644 > --- a/src/main/java/net/sourceforge/cilib/simulator/Simulation.java > +++ b/src/main/java/net/sourceforge/cilib/simulator/Simulation.java > @@ -22,9 +22,6 @@ > package net.sourceforge.cilib.simulator; > > import java.lang.reflect.Method; > -import java.util.Hashtable; > -import java.util.Vector; > - > import net.sourceforge.cilib.algorithm.Algorithm; > import net.sourceforge.cilib.algorithm.AlgorithmEvent; > import net.sourceforge.cilib.algorithm.AlgorithmFactory; > @@ -34,164 +31,111 @@ import net.sourceforge.cilib.problem.Problem; > import net.sourceforge.cilib.problem.ProblemFactory; > > /** > - * <p> > - * This class represents a single simulation experiment. The experiment is > repeated based on the - * number of samples that the measurement suite > requires. In this implementation each experiment is - * run in its own > thread. Thus, each experiment is run in parallel for a given simulation. - > * </p> > - * <p> > - * The simulation executes a given algorithm on the given problem. > Factories are utilised so that - * the simulation can create as many > alogirthms and problems as it needs to run many experiments. - * </p> > - * <p> > - * The primary purpose of running simulations is to measure the > performance of the given algorithm - * on a given problem. For that reason, > a simulation accepts a measurement suite which it uses to - * record the > performace. > - * </p> > - * @author Edwin Peer > + * A Simulation is a complete simulation that runs as a separate thread. > */ > -public class Simulation extends Thread implements AlgorithmListener { > - private static final long serialVersionUID = 8987667794610802908L; > - private MeasurementSuite measurementSuite; > - private Algorithm[] algorithms; > - private Thread[] threads; > - private Vector<ProgressListener> progressListeners; > - private Hashtable<Algorithm, Double> progress; > - > - public Simulation getClone() { > - return null; > - } > +class Simulation extends Thread implements AlgorithmListener { > + private static final long serialVersionUID = -3733724215662398762L; > + > + private final Simulator simulator; > + private final AlgorithmFactory algorithmFactory; > + private final ProblemFactory problemFactory; > + > + private Algorithm algorithm; > > /** > - * Creates a new instance of Simulation given an algorithm factory, a > problem factory and a - * measurement suite. {@see > net.sourceforge.cilib.XMLObjectFactory} - * @param algorithmFactory The > algorithm factory. > - * @param problemFactory The problem factory. > - * @param measurementSuite The measurement suite. > + * Create a Simulation with the required dependencies. > + * @param simulator The controlling {@code Simulator}. > + * @param algorithmFactory The factory that creates {@code Algorithm} > instances. + * @param problemFactory The factory that creates {@code > Problem} instances. */ > - public Simulation(AlgorithmFactory algorithmFactory, ProblemFactory > problemFactory, MeasurementSuite measurementSuite) { - > - measurementSuite.initialise(); > - this.measurementSuite = measurementSuite; > - progressListeners = new Vector<ProgressListener>(); > - progress = new Hashtable<Algorithm, Double>(); > - > - algorithms = new Algorithm[measurementSuite.getSamples()]; > - threads = new Thread[measurementSuite.getSamples()]; > - for (int i = 0; i < measurementSuite.getSamples(); ++i) { > - algorithms[i] = algorithmFactory.newAlgorithm(); > - threads[i] = new Thread(algorithms[i]); > - algorithms[i].addAlgorithmListener(this); > - Problem problem = problemFactory.newProblem(); > - try { > - Class<? extends Object> current = problem.getClass(); > - // System.out.println(current.getName()); > - while (!current.getSuperclass().equals(Object.class)) { > - current = current.getSuperclass(); > - // System.out.println(current.getName()); > - } > - String type = current.getInterfaces()[0].getName(); > - // System.out.println("type: " + type); > - Class<?> [] parameters = new Class[1]; > - parameters[0] = Class.forName(type); > - // System.out.println("parameters: " + > parameters[0].getName()); - String setMethodName = "set" + > type.substring(type.lastIndexOf(".") + 1); - // > System.out.println("setMethodName: " + setMethodName); - > Method setProblemMethod = algorithms[i].getClass().getMethod(setMethodName, > parameters); - // System.out.println("setProblemMethod: " + > setProblemMethod.getName()); - > setProblemMethod.invoke(algorithms[i], new Object[] {problem}); - > } > - catch (Exception ex) { > - throw new > InitialisationException(algorithms[i].getClass().getName() + " does not > support problems of type " + problem.getClass().getName()); - } > - progress.put(algorithms[i], new Double(0)); > - } > - } > - > - public void initialise() { > - for (Algorithm algorithm : algorithms) > - algorithm.initialise(); > + public Simulation(Simulator simulator, AlgorithmFactory > algorithmFactory, ProblemFactory problemFactory) { + this.simulator > = simulator; > + this.algorithmFactory = algorithmFactory; > + this.problemFactory = problemFactory; > } > > /** > - * Executes all the experiments for this simulation. > + * Execute the simulation. > */ > + @Override > public void run() { > - for (int i = 0; i < measurementSuite.getSamples(); ++i) { > - threads[i].start(); > - } > - for (int i = 0; i < measurementSuite.getSamples(); ++i) { > - try { > - threads[i].join(); > - } > - catch (InterruptedException ex) { > - ex.printStackTrace(); > + algorithm = algorithmFactory.newAlgorithm(); > + algorithm.addAlgorithmListener(this); > + > + Problem problem = problemFactory.newProblem(); > + try { > + Class<? extends Object> current = problem.getClass(); > + > + while (!current.getSuperclass().equals(Object.class)) { > + current = current.getSuperclass(); > } > + > + String type = current.getInterfaces()[0].getName(); > + Class<?> [] parameters = new Class[1]; > + parameters[0] = Class.forName(type); > + String setMethodName = "set" + > type.substring(type.lastIndexOf(".") + 1); + Method > setProblemMethod = algorithm.getClass().getMethod(setMethodName, > parameters); + setProblemMethod.invoke(algorithm, new Object[] > {problem}); + } > + catch (Exception ex) { > + throw new > InitialisationException(algorithm.getClass().getName() + " does not support > problems of type " + problem.getClass().getName()); } > - measurementSuite.getOutputBuffer().close(); > - measurementSuite = null; > - algorithms = null; > - progress = null; > - progressListeners = null; > - threads = null; > + > + algorithm.initialise(); > + algorithm.run(); > } > > /** > - * Terminates all the experiments. > + * Terminate the current simulation. > */ > public void terminate() { > - for (int i = 0; i < measurementSuite.getSamples(); ++i) { > - algorithms[i].terminate(); > - } > + algorithm.terminate(); > } > > /** > - * Adds a listener for progress events. A progress is fired > periodically based on the resolution - * of the measurements. {@see > ProgressEvent} {@see ProgressListener} - * @param The event listener > + * {@inheritDoc} > */ > - public void addProgressListener(ProgressListener listener) { > - progressListeners.add(listener); > + @Override > + public void algorithmStarted(AlgorithmEvent e) { > } > > /** > - * Removes a listener for progress events. > - * @param The event listener > + * {@inheritDoc} > */ > - public void removeProgressListener(ProgressListener listener) { > - progressListeners.remove(listener); > + @Override > + public void algorithmFinished(AlgorithmEvent e) { > + this.simulator.simulationFinished(this); > } > > - private synchronized void notifyProgress() { > - double ave = 0; > - for (Double tmp : progress.values()) { > - ave += tmp.doubleValue(); > - } > - > - ave /= progress.size(); > - > - for (ProgressListener listener : progressListeners) { > - listener.handleProgressEvent(new ProgressEvent(ave)); > - } > + /** > + * {@inheritDoc} > + */ > + @Override > + public void algorithmTerminated(AlgorithmEvent e) { > } > > - public void algorithmStarted(AlgorithmEvent e) { > + /** > + * {@inheritDoc} > + */ > + @Override > + public void iterationCompleted(AlgorithmEvent e) { > + this.simulator.simulationIterationCompleted(this); > } > > - public void algorithmFinished(AlgorithmEvent e) { > - measurementSuite.measure(e.getSource()); > - progress.put(e.getSource(), new > Double(e.getSource().getPercentageComplete())); - notifyProgress(); > + /** > + * {@inheritDoc} > + */ > + @Override > + public AlgorithmListener getClone() { > + return this; > } > > - public void algorithmTerminated(AlgorithmEvent e) { > + /** > + * Obtain the {@code Algorithm} of the current {@code Simulation}. > + * @return The current {@code Algorithm}. > + */ > + public Algorithm getAlgorithm() { > + return algorithm; > } > > - public void iterationCompleted(AlgorithmEvent e) { > - if (e.getSource().getIterations() % > measurementSuite.getResolution() == 0) { - > measurementSuite.measure(e.getSource()); > - progress.put(e.getSource(), new > Double(e.getSource().getPercentageComplete())); - > notifyProgress(); > - } > - } > } > diff --git a/src/main/java/net/sourceforge/cilib/simulator/Simulation.java > b/src/main/java/net/sourceforge/cilib/simulator/Simulator.java similarity > index 52% > copy from src/main/java/net/sourceforge/cilib/simulator/Simulation.java > copy to src/main/java/net/sourceforge/cilib/simulator/Simulator.java > index 377dd5c..3fc3051 100644 > --- a/src/main/java/net/sourceforge/cilib/simulator/Simulation.java > +++ b/src/main/java/net/sourceforge/cilib/simulator/Simulator.java > @@ -21,27 +21,22 @@ > */ > package net.sourceforge.cilib.simulator; > > -import java.lang.reflect.Method; > import java.util.Hashtable; > import java.util.Vector; > > import net.sourceforge.cilib.algorithm.Algorithm; > -import net.sourceforge.cilib.algorithm.AlgorithmEvent; > import net.sourceforge.cilib.algorithm.AlgorithmFactory; > -import net.sourceforge.cilib.algorithm.AlgorithmListener; > -import net.sourceforge.cilib.algorithm.InitialisationException; > -import net.sourceforge.cilib.problem.Problem; > import net.sourceforge.cilib.problem.ProblemFactory; > > /** > * <p> > * This class represents a single simulation experiment. The experiment is > repeated based on the * number of samples that the measurement suite > requires. In this implementation each experiment is - * run in its own > thread. Thus, each experiment is run in parallel for a given simulation. + > * execute in its own thread. Thus, each experiment is execute in parallel > for a given simulation. * </p> > * <p> > * The simulation executes a given algorithm on the given problem. > Factories are utilised so that - * the simulation can create as many > alogirthms and problems as it needs to run many experiments. + * the > simulation can create as many alogirthms and problems as it needs to > execute many experiments. * </p> > * <p> > * The primary purpose of running simulations is to measure the > performance of the given algorithm @@ -50,79 +45,44 @@ import > net.sourceforge.cilib.problem.ProblemFactory; * </p> > * @author Edwin Peer > */ > -public class Simulation extends Thread implements AlgorithmListener { > +public class Simulator { > private static final long serialVersionUID = 8987667794610802908L; > + > private MeasurementSuite measurementSuite; > - private Algorithm[] algorithms; > - private Thread[] threads; > + private Simulation[] simulations; > private Vector<ProgressListener> progressListeners; > - private Hashtable<Algorithm, Double> progress; > - > - public Simulation getClone() { > - return null; > - } > + private Hashtable<Simulation, Double> progress; > > /** > - * Creates a new instance of Simulation given an algorithm factory, a > problem factory and a + * Creates a new instance of Simulator given an > algorithm factory, a problem factory and a * measurement suite. {@see > net.sourceforge.cilib.XMLObjectFactory} * @param algorithmFactory The > algorithm factory. > * @param problemFactory The problem factory. > * @param measurementSuite The measurement suite. > */ > - public Simulation(AlgorithmFactory algorithmFactory, ProblemFactory > problemFactory, MeasurementSuite measurementSuite) { - > + public Simulator(AlgorithmFactory algorithmFactory, ProblemFactory > problemFactory, MeasurementSuite measurementSuite) { > measurementSuite.initialise(); > this.measurementSuite = measurementSuite; > progressListeners = new Vector<ProgressListener>(); > - progress = new Hashtable<Algorithm, Double>(); > + progress = new Hashtable<Simulation, Double>(); > > - algorithms = new Algorithm[measurementSuite.getSamples()]; > - threads = new Thread[measurementSuite.getSamples()]; > + simulations = new Simulation[measurementSuite.getSamples()]; > for (int i = 0; i < measurementSuite.getSamples(); ++i) { > - algorithms[i] = algorithmFactory.newAlgorithm(); > - threads[i] = new Thread(algorithms[i]); > - algorithms[i].addAlgorithmListener(this); > - Problem problem = problemFactory.newProblem(); > - try { > - Class<? extends Object> current = problem.getClass(); > - // System.out.println(current.getName()); > - while (!current.getSuperclass().equals(Object.class)) { > - current = current.getSuperclass(); > - // System.out.println(current.getName()); > - } > - String type = current.getInterfaces()[0].getName(); > - // System.out.println("type: " + type); > - Class<?> [] parameters = new Class[1]; > - parameters[0] = Class.forName(type); > - // System.out.println("parameters: " + > parameters[0].getName()); - String setMethodName = "set" + > type.substring(type.lastIndexOf(".") + 1); - // > System.out.println("setMethodName: " + setMethodName); - > Method setProblemMethod = algorithms[i].getClass().getMethod(setMethodName, > parameters); - // System.out.println("setProblemMethod: " + > setProblemMethod.getName()); - > setProblemMethod.invoke(algorithms[i], new Object[] {problem}); - > } > - catch (Exception ex) { > - throw new > InitialisationException(algorithms[i].getClass().getName() + " does not > support problems of type " + problem.getClass().getName()); - } > - progress.put(algorithms[i], new Double(0)); > + simulations[i] = new Simulation(this, algorithmFactory, > problemFactory); + progress.put(simulations[i], 0.0); > } > } > > - public void initialise() { > - for (Algorithm algorithm : algorithms) > - algorithm.initialise(); > - } > - > /** > * Executes all the experiments for this simulation. > */ > - public void run() { > + public void execute() { > for (int i = 0; i < measurementSuite.getSamples(); ++i) { > - threads[i].start(); > + simulations[i].start(); > } > for (int i = 0; i < measurementSuite.getSamples(); ++i) { > try { > - threads[i].join(); > + simulations[i].join(); > } > catch (InterruptedException ex) { > ex.printStackTrace(); > @@ -130,10 +90,9 @@ public class Simulation extends Thread implements > AlgorithmListener { } > measurementSuite.getOutputBuffer().close(); > measurementSuite = null; > - algorithms = null; > + simulations = null; > progress = null; > progressListeners = null; > - threads = null; > } > > /** > @@ -141,14 +100,14 @@ public class Simulation extends Thread implements > AlgorithmListener { */ > public void terminate() { > for (int i = 0; i < measurementSuite.getSamples(); ++i) { > - algorithms[i].terminate(); > + simulations[i].terminate(); > } > } > > /** > * Adds a listener for progress events. A progress is fired > periodically based on the resolution * of the measurements. {@see > ProgressEvent} {@see ProgressListener} - * @param The event listener > + * @param listener The event listener > */ > public void addProgressListener(ProgressListener listener) { > progressListeners.add(listener); > @@ -156,7 +115,7 @@ public class Simulation extends Thread implements > AlgorithmListener { > > /** > * Removes a listener for progress events. > - * @param The event listener > + * @param listener The event listener > */ > public void removeProgressListener(ProgressListener listener) { > progressListeners.remove(listener); > @@ -175,22 +134,25 @@ public class Simulation extends Thread implements > AlgorithmListener { } > } > > - public void algorithmStarted(AlgorithmEvent e) { > - } > - > - public void algorithmFinished(AlgorithmEvent e) { > - measurementSuite.measure(e.getSource()); > - progress.put(e.getSource(), new > Double(e.getSource().getPercentageComplete())); + /** > + * Indicate that the provided {@code Simulation} has completed. > + * @param simulation The {@code simulation} which has completed. > + */ > + void simulationFinished(Simulation simulation) { > + measurementSuite.measure(simulation.getAlgorithm()); > + progress.put(simulation, new > Double(simulation.getAlgorithm().getPercentageComplete())); > notifyProgress(); > } > > - public void algorithmTerminated(AlgorithmEvent e) { > - } > - > - public void iterationCompleted(AlgorithmEvent e) { > - if (e.getSource().getIterations() % > measurementSuite.getResolution() == 0) { - > measurementSuite.measure(e.getSource()); > - progress.put(e.getSource(), new > Double(e.getSource().getPercentageComplete())); + /** > + * Indicate that the provided {@code Simulation} has completed an > iteration. + * @param simulation The {@code Simulation} that has > completed an iteration. + */ > + void simulationIterationCompleted(Simulation simulation) { > + Algorithm algorithm = simulation.getAlgorithm(); > + if (algorithm.getIterations() % measurementSuite.getResolution() > == 0) { + measurementSuite.measure(simulation.getAlgorithm()); > + progress.put(simulation, new > Double(algorithm.getPercentageComplete())); notifyProgress(); > } > } > diff --git a/src/test/java/net/sourceforge/cilib/xml/XMLFileTest.java > b/src/test/java/net/sourceforge/cilib/xml/XMLFileTest.java index > 9e1ab35..1cb0933 100644 > --- a/src/test/java/net/sourceforge/cilib/xml/XMLFileTest.java > +++ b/src/test/java/net/sourceforge/cilib/xml/XMLFileTest.java > @@ -30,7 +30,7 @@ import javax.xml.parsers.ParserConfigurationException; > import net.sourceforge.cilib.simulator.MeasurementSuite; > import net.sourceforge.cilib.simulator.ProgressListener; > import net.sourceforge.cilib.simulator.ProgressText; > -import net.sourceforge.cilib.simulator.Simulation; > +import net.sourceforge.cilib.simulator.Simulator; > import org.junit.Test; > import org.w3c.dom.Document; > import org.w3c.dom.Element; > @@ -79,7 +79,7 @@ public class XMLFileTest { > XMLProblemFactory problemFactory = new > XMLProblemFactory(doc, (Element) > current.getElementsByTagName("problem").item(0)); XMLObjectFactory > measurementsFactory = new XMLObjectFactory(doc, (Element) > current.getElementsByTagName("measurements").item(0)); MeasurementSuite > suite = (MeasurementSuite) measurementsFactory.newObject(); - > Simulation simulation = new Simulation(algorithmFactory, problemFactory, > suite); + Simulator simulation = new > Simulator(algorithmFactory, problemFactory, suite); if(progress != null) { > simulation.addProgressListener(progress); > } |