Browse Source

threading: minor refactoring, control, fast-forward execution

Signed-off-by: Christoph Ruegg <git@cdrnet.ch>
pull/2/head
Christoph Ruegg 17 years ago
parent
commit
c412fce9e6
  1. 22
      src/Numerics/Control.cs
  2. 2
      src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs
  3. 2
      src/Numerics/Threading/AggregateException.cs
  4. 66
      src/Numerics/Threading/Parallel.cs
  5. 2
      src/Numerics/Threading/Task.cs
  6. 16
      src/Numerics/Threading/ThreadQueue.cs
  7. 3
      src/UnitTests/ThreadingTests/ParallelTest.cs

22
src/Numerics/Control.cs

@ -28,12 +28,12 @@
namespace MathNet.Numerics namespace MathNet.Numerics
{ {
using System; using Threading;
/// <summary> /// <summary>
/// Sets parameters for the library. /// Sets parameters for the library.
/// </summary> /// </summary>
public static partial class Control public static class Control
{ {
/// <summary> /// <summary>
/// Initializes static members of the Control class. /// Initializes static members of the Control class.
@ -42,6 +42,7 @@ namespace MathNet.Numerics
{ {
CheckDistributionParameters = true; CheckDistributionParameters = true;
ThreadSafeRandomNumberGenerators = true; ThreadSafeRandomNumberGenerators = true;
DisableParallelization = false;
} }
/// <summary> /// <summary>
@ -59,5 +60,20 @@ namespace MathNet.Numerics
/// <c>true</c> to use thread safe random number generators ; otherwise, <c>false</c>. /// <c>true</c> to use thread safe random number generators ; otherwise, <c>false</c>.
/// </value> /// </value>
public static bool ThreadSafeRandomNumberGenerators { get; set; } public static bool ThreadSafeRandomNumberGenerators { get; set; }
/// <summary>
/// Gets or sets a value indicating how many parallel worker threads shall be used
/// when parallelization is applicable.
/// </summary>
public static int NumberOfParallelWorkerThreads
{
get { return ThreadQueue.ThreadCount; }
set { ThreadQueue.Start(value); }
}
/// <summary>
/// Gets or sets a value indicating whether parallelization shall be disabled globally.
/// </summary>
public static bool DisableParallelization { get; set; }
} }
} }

2
src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs

@ -70,7 +70,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
Complex[] b = new Complex[m]; Complex[] b = new Complex[m];
Complex[] a = new Complex[m]; Complex[] a = new Complex[m];
Parallel.Invoke( Parallel.Run(
() => () =>
{ {
// Build and transform padded sequence b_k = exp(I*Pi*k^2/N) // Build and transform padded sequence b_k = exp(I*Pi*k^2/N)

2
src/Numerics/Threading/AggregateException.cs

@ -63,4 +63,4 @@ namespace MathNet.Numerics.Threading
get { return new ReadOnlyCollection<Exception>(_exceptions); } get { return new ReadOnlyCollection<Exception>(_exceptions); }
} }
} }
} }

66
src/Numerics/Threading/Parallel.cs

@ -53,15 +53,33 @@ namespace MathNet.Numerics.Threading
throw new ArgumentNullException("body"); throw new ArgumentNullException("body");
} }
var actions = new Action[ThreadQueue.ThreadCount]; // fast forward execution if it's only one or none items
var count = toExclusive - fromInclusive; var count = toExclusive - fromInclusive;
var size = count / actions.Length; if (count <= 1)
{
if (count == 1)
{
body(fromInclusive);
}
if (count < 1) return;
}
// fast forward execution in case parallelization is disabled
// (cdrnet, 200908): should we fast forward on STA threads as well?
if (Control.DisableParallelization || ThreadQueue.ThreadCount <= 1)
{ {
for (int i = fromInclusive; i < toExclusive; i++)
{
body(i);
}
return; return;
} }
var actions = new Action[ThreadQueue.ThreadCount];
var size = count / actions.Length;
// partition the jobs into separate sets for each but the last worked thread // partition the jobs into separate sets for each but the last worked thread
for (var i = 0; i < actions.Length - 1; i++) for (var i = 0; i < actions.Length - 1; i++)
{ {
@ -71,7 +89,7 @@ namespace MathNet.Numerics.Threading
actions[i] = actions[i] =
() => () =>
{ {
for (var j = start; j < stop; j++) for (int j = start; j < stop; j++)
{ {
body(j); body(j);
} }
@ -82,7 +100,7 @@ namespace MathNet.Numerics.Threading
actions[actions.Length - 1] = actions[actions.Length - 1] =
() => () =>
{ {
for (var i = fromInclusive + ((actions.Length - 1) * size); i < toExclusive; i++) for (int i = fromInclusive + ((actions.Length - 1) * size); i < toExclusive; i++)
{ {
body(i); body(i);
} }
@ -98,13 +116,47 @@ namespace MathNet.Numerics.Threading
/// <exception cref="ArgumentNullException">The <paramref name="actions"/> argument is null.</exception> /// <exception cref="ArgumentNullException">The <paramref name="actions"/> argument is null.</exception>
/// <exception cref="ArgumentException">The actions array contains a null element.</exception> /// <exception cref="ArgumentException">The actions array contains a null element.</exception>
/// <exception cref="AggregateException">An action threw an exception.</exception> /// <exception cref="AggregateException">An action threw an exception.</exception>
internal static void Invoke(params Action[] actions) internal static void Run(params Action[] actions)
{ {
if (actions == null) if (actions == null)
{ {
throw new ArgumentNullException("actions"); throw new ArgumentNullException("actions");
} }
// fast forward execution if it's only one or none items
if (actions.Length <= 1)
{
if (actions.Length == 1)
{
actions[0]();
}
return;
}
// fast forward execution in case parallelization is disabled
// (cdrnet, 200908): should we fast forward on STA threads as well?
if (Control.DisableParallelization || ThreadQueue.ThreadCount <= 1)
{
for (int i = 0; i < actions.Length; i++)
{
actions[i]();
}
return;
}
Invoke(actions);
}
/// <summary>
/// Executes each of the provided actions inside a discrete, asynchronous task.
/// </summary>
/// <param name="actions">An array of actions to execute.</param>
/// <exception cref="ArgumentException">The actions array contains a null element.</exception>
/// <exception cref="AggregateException">An action threw an exception.</exception>
private static void Invoke(params Action[] actions)
{
// create a job for each action // create a job for each action
var tasks = new Task[actions.Length]; var tasks = new Task[actions.Length];
for (int i = 0; i < tasks.Length; i++) for (int i = 0; i < tasks.Length; i++)
@ -155,4 +207,4 @@ namespace MathNet.Numerics.Threading
} }
} }
} }
} }

2
src/Numerics/Threading/Task.cs

@ -84,4 +84,4 @@ namespace MathNet.Numerics.Threading
} }
} }
} }
} }

16
src/Numerics/Threading/ThreadQueue.cs

@ -82,7 +82,6 @@ namespace MathNet.Numerics.Threading
/// </summary> /// </summary>
static ThreadQueue() static ThreadQueue()
{ {
// TODO: Control.ThreadCount instead of Environment.ProcessorCount
Start(Environment.ProcessorCount); Start(Environment.ProcessorCount);
} }
@ -154,12 +153,14 @@ namespace MathNet.Numerics.Threading
} }
} }
// ...and run it if (task == null)
if (task != null)
{ {
task.Compute(); continue;
task.Set();
} }
// ...and run it
task.Compute();
task.Set();
} }
} }
@ -169,6 +170,9 @@ namespace MathNet.Numerics.Threading
/// <param name="numberOfThreads">Number of worker threads.</param> /// <param name="numberOfThreads">Number of worker threads.</param>
internal static void Start(int numberOfThreads) internal static void Start(int numberOfThreads)
{ {
// instead of throwing an out of range exception, simply normalize
numberOfThreads = Math.Max(1, Math.Min(1024, numberOfThreads));
lock (_stateSync) lock (_stateSync)
{ {
if (_threads != null) if (_threads != null)
@ -242,4 +246,4 @@ namespace MathNet.Numerics.Threading
} }
} }
} }
} }

3
src/UnitTests/ThreadingTests/ParallelTest.cs

@ -117,11 +117,12 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests
ThreadQueue.Start(2); ThreadQueue.Start(2);
Assert.AreEqual(2, ThreadQueue.ThreadCount); Assert.AreEqual(2, ThreadQueue.ThreadCount);
ThreadQueue.Start(2); Control.NumberOfParallelWorkerThreads = 2;
Assert.AreEqual(2, ThreadQueue.ThreadCount); Assert.AreEqual(2, ThreadQueue.ThreadCount);
ThreadQueue.Start(4); ThreadQueue.Start(4);
Assert.AreEqual(4, ThreadQueue.ThreadCount); Assert.AreEqual(4, ThreadQueue.ThreadCount);
Assert.AreEqual(4, Control.NumberOfParallelWorkerThreads);
ThreadQueue.Shutdown(); ThreadQueue.Shutdown();
ThreadQueue.Start(); ThreadQueue.Start();

Loading…
Cancel
Save