Repository: commons-math
Updated Branches:
  refs/heads/MATH_3_X 49b4bbd41 -> 1c4ebd5bd


MATH-1250

Methods to estimate concurrency performance.


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/895f50e6
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/895f50e6
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/895f50e6

Branch: refs/heads/MATH_3_X
Commit: 895f50e696f07942e6694f145f1d8e3d83c5ef84
Parents: 49b4bbd
Author: Gilles <er...@apache.org>
Authored: Sun Jul 19 00:02:45 2015 +0200
Committer: Gilles <er...@apache.org>
Committed: Sun Jul 19 20:37:27 2015 +0200

----------------------------------------------------------------------
 src/changes/changes.xml                         |  7 +++
 .../commons/math3/ml/neuralnet/Neuron.java      | 44 ++++++++++++++-
 .../neuralnet/sofm/KohonenTrainingTaskTest.java | 21 ++++++-
 .../sofm/TravellingSalesmanSolver.java          | 58 ++++++++++++++++----
 4 files changed, 113 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/895f50e6/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c5cdb11..3e6d4be 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -51,6 +51,13 @@ If the output is not quite correct, check for invisible 
trailing spaces!
   </properties>
   <body>
     <release version="3.6" date="XXXX-XX-XX" description="">
+      <action dev="erans" type="add" issue="MATH-1250">
+        "Neuron" class (package "o.a.c.m.ml.neuralnet"): added methods that 
can be used
+        to assess concurrency performance.
+      </action>
+      <action dev="erans" type="fix" issue="MATH-1248" due-to="Chris Popp">
+        Removed unnecessary allocations in "BigFraction" (package 
"o.a.c.m.fraction").
+      </action>
       <action dev="psteitz" type="fix" issue="MATH-1245">
         Fixed error in computing discrete distribution of D statistics for 
small-sample
         2-sample Kolmogorov-Smirnov tests. Error was causing incorrect 
p-values returned 

http://git-wip-us.apache.org/repos/asf/commons-math/blob/895f50e6/src/main/java/org/apache/commons/math3/ml/neuralnet/Neuron.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ml/neuralnet/Neuron.java 
b/src/main/java/org/apache/commons/math3/ml/neuralnet/Neuron.java
index 51c533f..3fd0c0a 100644
--- a/src/main/java/org/apache/commons/math3/ml/neuralnet/Neuron.java
+++ b/src/main/java/org/apache/commons/math3/ml/neuralnet/Neuron.java
@@ -20,8 +20,10 @@ package org.apache.commons.math3.ml.neuralnet;
 import java.io.Serializable;
 import java.io.ObjectInputStream;
 import java.util.concurrent.atomic.AtomicReference;
-import org.apache.commons.math3.util.Precision;
+import java.util.concurrent.atomic.AtomicLong;
+
 import org.apache.commons.math3.exception.DimensionMismatchException;
+import org.apache.commons.math3.util.Precision;
 
 
 /**
@@ -40,6 +42,10 @@ public class Neuron implements Serializable {
     private final int size;
     /** Neuron data. */
     private final AtomicReference<double[]> features;
+    /** Number of attempts to update a neuron. */
+    private final AtomicLong numberOfAttemptedUpdates = new AtomicLong(0);
+    /** Number of successful updates  of a neuron. */
+    private final AtomicLong numberOfSuccessfulUpdates = new AtomicLong(0);
 
     /**
      * Creates a neuron.
@@ -129,16 +135,48 @@ public class Neuron implements Serializable {
             return false;
         }
 
+        // Increment attempt counter.
+        numberOfAttemptedUpdates.incrementAndGet();
+
         if (features.compareAndSet(current, update.clone())) {
-            // The current thread could atomically update the state.
+            // The current thread could atomically update the state (attempt 
succeeded).
+            numberOfSuccessfulUpdates.incrementAndGet();
             return true;
         } else {
-            // Some other thread came first.
+            // Some other thread came first (attempt failed).
             return false;
         }
     }
 
     /**
+     * Retrieves the number of calls to the
+     * {@link #compareAndSetFeatures(double[],double[]) compareAndSetFeatures}
+     * method.
+     * Note that if the caller wants to use this method in combination with
+     * {@link #getNumberOfSuccessfulUpdates()}, additional synchronization
+     * may be required to ensure consistency.
+     *
+     * @return the number of update attempts.
+     */
+    public long getNumberOfAttemptedUpdates() {
+        return numberOfAttemptedUpdates.get();
+    }
+
+    /**
+     * Retrieves the number of successful calls to the
+     * {@link #compareAndSetFeatures(double[],double[]) compareAndSetFeatures}
+     * method.
+     * Note that if the caller wants to use this method in combination with
+     * {@link #getNumberOfAttemptedUpdates()}, additional synchronization
+     * may be required to ensure consistency.
+     *
+     * @return the number of successful updates.
+     */
+    public long getNumberOfSuccessfulUpdates() {
+        return numberOfSuccessfulUpdates.get();
+    }
+
+    /**
      * Checks whether the contents of both arrays is the same.
      *
      * @param current Current values.

http://git-wip-us.apache.org/repos/asf/commons-math/blob/895f50e6/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/KohonenTrainingTaskTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/KohonenTrainingTaskTest.java
 
b/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/KohonenTrainingTaskTest.java
index d3f5628..218a709 100644
--- 
a/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/KohonenTrainingTaskTest.java
+++ 
b/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/KohonenTrainingTaskTest.java
@@ -30,6 +30,7 @@ import java.util.concurrent.Future;
 
 import org.apache.commons.math3.Retry;
 import org.apache.commons.math3.RetryRunner;
+import org.apache.commons.math3.ml.neuralnet.sofm.KohonenTrainingTask;
 import org.apache.commons.math3.util.FastMath;
 import org.junit.Assert;
 import org.junit.Test;
@@ -65,7 +66,12 @@ public class KohonenTrainingTaskTest {
 
         final TravellingSalesmanSolver solver = new 
TravellingSalesmanSolver(squareOfCities, 2, seed);
         // printSummary("before.travel.seq.dat", solver);
-        solver.createSequentialTask(15000).run();
+        final Runnable task = solver.createSequentialTask(15000);
+        task.run();
+
+        // All update attempts must be successful in the absence of 
concurrency.
+        Assert.assertEquals(solver.getUpdateRatio(), 1, 0d);
+
         // printSummary("after.travel.seq.dat", solver);
         final City[] result = solver.getCityList();
         Assert.assertEquals(squareOfCities.length,
@@ -96,12 +102,16 @@ public class KohonenTrainingTaskTest {
             new City("i0", 1, 1),
         };
 
-        final TravellingSalesmanSolver solver = new 
TravellingSalesmanSolver(squareOfCities, 2);
+        // Seed that allows the unit test to always succeed.
+        final long seed = 534712311L;
+
+        final TravellingSalesmanSolver solver = new 
TravellingSalesmanSolver(squareOfCities, 2, seed);
         // printSummary("before.travel.par.dat", solver);
 
         // Parallel execution.
         final ExecutorService service = Executors.newCachedThreadPool();
-        final Runnable[] tasks = solver.createParallelTasks(3, 5000);
+        final int numProcs = Runtime.getRuntime().availableProcessors();
+        final Runnable[] tasks = solver.createParallelTasks(numProcs, 5000);
         final List<Future<?>> execOutput = new ArrayList<Future<?>>();
         // Run tasks.
         for (Runnable r : tasks) {
@@ -116,6 +126,11 @@ public class KohonenTrainingTaskTest {
         // Terminate all threads.
         service.shutdown();
 
+        if (numProcs > 1) {
+            // We expect that some update attempts will be concurrent.
+            Assert.assertTrue(solver.getUpdateRatio() < 1);
+        }
+
         // printSummary("after.travel.par.dat", solver);
         final City[] result = solver.getCityList();
         Assert.assertEquals(squareOfCities.length,

http://git-wip-us.apache.org/repos/asf/commons-math/blob/895f50e6/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/TravellingSalesmanSolver.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/TravellingSalesmanSolver.java
 
b/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/TravellingSalesmanSolver.java
index 369ea33..026d8bd 100644
--- 
a/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/TravellingSalesmanSolver.java
+++ 
b/src/test/java/org/apache/commons/math3/ml/neuralnet/sofm/TravellingSalesmanSolver.java
@@ -23,23 +23,30 @@ import java.util.Set;
 import java.util.HashSet;
 import java.util.Collection;
 import java.util.Iterator;
-import org.apache.commons.math3.ml.neuralnet.Neuron;
-import org.apache.commons.math3.ml.neuralnet.Network;
-import org.apache.commons.math3.ml.neuralnet.FeatureInitializer;
-import org.apache.commons.math3.ml.neuralnet.FeatureInitializerFactory;
+
+import org.apache.commons.math3.analysis.FunctionUtils;
+import org.apache.commons.math3.analysis.UnivariateFunction;
+import org.apache.commons.math3.analysis.function.Constant;
+import org.apache.commons.math3.analysis.function.HarmonicOscillator;
+import org.apache.commons.math3.distribution.RealDistribution;
+import org.apache.commons.math3.distribution.UniformRealDistribution;
+import org.apache.commons.math3.exception.MathUnsupportedOperationException;
 import org.apache.commons.math3.ml.distance.DistanceMeasure;
 import org.apache.commons.math3.ml.distance.EuclideanDistance;
+import org.apache.commons.math3.ml.neuralnet.FeatureInitializer;
+import org.apache.commons.math3.ml.neuralnet.FeatureInitializerFactory;
+import org.apache.commons.math3.ml.neuralnet.Network;
+import org.apache.commons.math3.ml.neuralnet.Neuron;
 import org.apache.commons.math3.ml.neuralnet.oned.NeuronString;
+import org.apache.commons.math3.ml.neuralnet.sofm.KohonenTrainingTask;
+import org.apache.commons.math3.ml.neuralnet.sofm.KohonenUpdateAction;
+import org.apache.commons.math3.ml.neuralnet.sofm.LearningFactorFunction;
+import 
org.apache.commons.math3.ml.neuralnet.sofm.LearningFactorFunctionFactory;
+import org.apache.commons.math3.ml.neuralnet.sofm.NeighbourhoodSizeFunction;
+import 
org.apache.commons.math3.ml.neuralnet.sofm.NeighbourhoodSizeFunctionFactory;
 import org.apache.commons.math3.random.RandomGenerator;
 import org.apache.commons.math3.random.Well44497b;
-import org.apache.commons.math3.exception.MathUnsupportedOperationException;
 import org.apache.commons.math3.util.FastMath;
-import org.apache.commons.math3.analysis.UnivariateFunction;
-import org.apache.commons.math3.analysis.FunctionUtils;
-import org.apache.commons.math3.analysis.function.HarmonicOscillator;
-import org.apache.commons.math3.analysis.function.Constant;
-import org.apache.commons.math3.distribution.RealDistribution;
-import org.apache.commons.math3.distribution.UniformRealDistribution;
 
 /**
  * Solves the "Travelling Salesman's Problem" (i.e. trying to find the
@@ -133,6 +140,35 @@ public class TravellingSalesmanSolver {
     }
 
     /**
+     * Measures the network's concurrent update performance.
+     *
+     * @return the ratio between the number of succesful network updates
+     * and the number of update attempts.
+     */
+    public double getUpdateRatio() {
+        return computeUpdateRatio(net);
+    }
+
+    /**
+     * Measures the network's concurrent update performance.
+     *
+     * @param net Network to be trained with the SOFM algorithm.
+     * @return the ratio between the number of successful network updates
+     * and the number of update attempts.
+     */
+    private static double computeUpdateRatio(Network net) {
+        long numAttempts = 0;
+        long numSuccesses = 0;
+
+        for (Neuron n : net) {
+            numAttempts += n.getNumberOfAttemptedUpdates();
+            numSuccesses += n.getNumberOfSuccessfulUpdates();
+        }
+
+        return (double) numSuccesses / (double) numAttempts;
+    }
+
+    /**
      * Creates an iterator that will present a series of city's coordinates in
      * a random order.
      *

Reply via email to