Browse Source

Merge pull request #197 from tibel/taskscheduler

Simplify CommonParallel
provider
Christoph Ruegg 13 years ago
parent
commit
5d3ef8c1ed
  1. 167
      src/Numerics/Compatibility.cs
  2. 24
      src/Numerics/Control.cs
  3. 144
      src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs
  4. 144
      src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs
  5. 126
      src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs
  6. 126
      src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs
  7. 179
      src/Numerics/Threading/CommonParallel.cs

167
src/Numerics/Compatibility.cs

@ -2,6 +2,10 @@
namespace MathNet.Numerics
{
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class SerializableAttribute : Attribute
@ -12,6 +16,126 @@ namespace MathNet.Numerics
public class SpecialNameAttribute : Attribute
{
}
internal static class Partitioner
{
public static IEnumerable<Tuple<int, int>> Create(int fromInclusive, int toExclusive)
{
var rangeSize = Math.Max(1, (toExclusive - fromInclusive) / Control.NumberOfParallelWorkerThreads);
return Create(fromInclusive, toExclusive, rangeSize);
}
public static IEnumerable<Tuple<int, int>> Create(int fromInclusive, int toExclusive, int rangeSize)
{
if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive");
if (rangeSize <= 0) throw new ArgumentOutOfRangeException("rangeSize");
return CreateRanges(fromInclusive, toExclusive, rangeSize);
}
private static IEnumerable<Tuple<int, int>> CreateRanges(int fromInclusive, int toExclusive, int rangeSize)
{
bool flag = false;
int num = fromInclusive;
while (num < toExclusive && !flag)
{
int item = num;
int num2;
try
{
num2 = checked(num + rangeSize);
}
catch (OverflowException)
{
num2 = toExclusive;
flag = true;
}
if (num2 > toExclusive)
{
num2 = toExclusive;
}
yield return new Tuple<int, int>(item, num2);
num += rangeSize;
}
}
}
internal class ParallelOptions
{
public TaskScheduler TaskScheduler { get; set; }
public int MaxDegreeOfParallelism { get; set; }
public CancellationToken CancellationToken { get; set; }
public ParallelOptions()
{
TaskScheduler = TaskScheduler.Default;
MaxDegreeOfParallelism = -1;
CancellationToken = CancellationToken.None;
}
}
internal class ParallelLoopState
{
}
internal static class Parallel
{
public static void ForEach<TSource>(IEnumerable<TSource> source, ParallelOptions parallelOptions, Action<TSource> body)
{
var chunks = source.ToArray();
var tasks = new Task[chunks.Length];
for (var i = 0; i < tasks.Length; i++)
{
var chunk = chunks[i];
tasks[i] = Task.Factory.StartNew(() => body(chunk), parallelOptions.CancellationToken, TaskCreationOptions.None, parallelOptions.TaskScheduler);
}
Task.WaitAll(tasks, parallelOptions.CancellationToken);
}
public static void Invoke(ParallelOptions parallelOptions, params Action[] actions)
{
var tasks = new Task[actions.Length];
for (var i = 0; i < tasks.Length; i++)
{
var action = actions[i];
if (action == null)
{
throw new ArgumentException(String.Format(Properties.Resources.ArgumentItemNull, "actions"), "actions");
}
tasks[i] = Task.Factory.StartNew(action, parallelOptions.CancellationToken, TaskCreationOptions.None, parallelOptions.TaskScheduler);
}
Task.WaitAll(tasks, parallelOptions.CancellationToken);
}
public static void ForEach<TSource, TLocal>(
IEnumerable<TSource> source,
ParallelOptions parallelOptions,
Func<TLocal> localInit,
Func<TSource, ParallelLoopState, TLocal, TLocal> body,
Action<TLocal> localFinally)
{
var chunks = source.ToArray();
var tasks = new Task[chunks.Length];
var loopState = new ParallelLoopState();
for (var i = 0; i < tasks.Length; i++)
{
var chunk = chunks[i];
tasks[i] = Task.Factory.StartNew(() =>
{
var local = localInit();
local = body(chunk, loopState, local);
localFinally(local);
}, parallelOptions.CancellationToken, TaskCreationOptions.None, parallelOptions.TaskScheduler);
}
Task.WaitAll(tasks, parallelOptions.CancellationToken);
}
}
}
#endif
@ -37,6 +161,7 @@ namespace MathNet.Numerics
namespace MathNet.Numerics
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
internal static class ObjectComparer
@ -130,5 +255,47 @@ namespace MathNet.Numerics
}
}
}
internal static class Partitioner
{
public static OrderablePartitioner<Tuple<int, int>> Create(int fromInclusive, int toExclusive)
{
var rangeSize = Math.Max(1, (toExclusive - fromInclusive) / Control.NumberOfParallelWorkerThreads);
return Create(fromInclusive, toExclusive, rangeSize);
}
public static OrderablePartitioner<Tuple<int, int>> Create(int fromInclusive, int toExclusive, int rangeSize)
{
if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive");
if (rangeSize <= 0) throw new ArgumentOutOfRangeException("rangeSize");
return System.Collections.Concurrent.Partitioner.Create(CreateRanges(fromInclusive, toExclusive, rangeSize));
}
private static IEnumerable<Tuple<int, int>> CreateRanges(int fromInclusive, int toExclusive, int rangeSize)
{
bool flag = false;
int num = fromInclusive;
while (num < toExclusive && !flag)
{
int item = num;
int num2;
try
{
num2 = checked(num + rangeSize);
}
catch (OverflowException)
{
num2 = toExclusive;
flag = true;
}
if (num2 > toExclusive)
{
num2 = toExclusive;
}
yield return new Tuple<int, int>(item, num2);
num += rangeSize;
}
}
}
}
#endif

24
src/Numerics/Control.cs

@ -30,6 +30,7 @@
using MathNet.Numerics.Providers.LinearAlgebra;
using System;
using System.Threading.Tasks;
namespace MathNet.Numerics
{
@ -61,10 +62,10 @@ namespace MathNet.Numerics
// Parallelization & Threading
_numberOfThreads = Environment.ProcessorCount;
DisableParallelization = _numberOfThreads < 2;
_blockSize = 512;
_parallelizeOrder = 64;
_parallelizeElements = 300;
TaskScheduler = TaskScheduler.Default;
// Linear Algebra Provider
LinearAlgebraProvider = new ManagedLinearAlgebraProvider();
@ -93,7 +94,6 @@ namespace MathNet.Numerics
public static void UseSingleThread()
{
_numberOfThreads = 1;
DisableParallelization = true;
ThreadSafeRandomNumberGenerators = false;
}
@ -125,11 +125,6 @@ namespace MathNet.Numerics
/// </value>
public static bool ThreadSafeRandomNumberGenerators { get; set; }
/// <summary>
/// Gets or sets a value indicating whether parallelization shall be disabled globally.
/// </summary>
public static bool DisableParallelization { get; set; }
/// <summary>
/// Gets or sets the linear algebra provider. Consider to use UseNativeMKL or UseManaged instead.
/// </summary>
@ -157,6 +152,11 @@ namespace MathNet.Numerics
set { _numberOfThreads = Math.Max(1, Math.Min(1024, value)); }
}
/// <summary>
/// Gets or sets the TaskScheduler used to schedule the worker tasks.
/// </summary>
public static TaskScheduler TaskScheduler { get; set; }
/// <summary>
/// Gets or sets the the block size to use for
/// the native linear algebra provider.
@ -190,16 +190,6 @@ namespace MathNet.Numerics
set { _parallelizeElements = Math.Max(3, value); }
}
/// <summary>
/// Given the number elements, should the operation be parallelized.
/// </summary>
/// <param name="elements">The number elements to check.</param>
/// <returns><c>true</c> if the operation should be parallelized; <c>false</c> otherwise.</returns>
public static bool ParallelizeOperation(int elements)
{
return !DisableParallelization && NumberOfParallelWorkerThreads >= 2 && elements >= ParallelizeElements;
}
/// <summary>
/// Maximum number of columns to print in ToString methods by default.
/// </summary>

144
src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs

@ -82,43 +82,23 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
else if (alpha.IsOne())
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + x[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = y[index] + x[index];
result[i] = y[i] + x[i];
}
}
});
}
else
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + (alpha*x[i]);
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = y[index] + (alpha*x[index]);
result[i] = y[i] + (alpha*x[i]);
}
}
});
}
}
@ -146,23 +126,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
else
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = alpha*x[i];
}
});
}
else
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = alpha*x[index];
result[i] = alpha*x[i];
}
}
});
}
}
@ -178,23 +148,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentNullException("x");
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i].Conjugate();
}
});
}
else
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index].Conjugate();
result[i] = x[i].Conjugate();
}
}
});
}
/// <summary>
@ -262,23 +222,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] + y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index] + y[index];
result[i] = x[i] + y[i];
}
}
});
}
/// <summary>
@ -313,23 +263,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] - y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index] - y[index];
result[i] = x[i] - y[i];
}
}
});
}
/// <summary>
@ -364,23 +304,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]*y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index]*y[index];
result[i] = x[i] * y[i];
}
}
});
}
/// <summary>
@ -415,23 +345,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]/y[i];
}
});
}
else
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index]/y[index];
result[i] = x[i] / y[i];
}
}
});
}
/// <summary>

144
src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs

@ -78,43 +78,23 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
else if (alpha.IsOne())
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + x[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = y[index] + x[index];
result[i] = y[i] + x[i];
}
}
});
}
else
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + (alpha*x[i]);
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = y[index] + (alpha*x[index]);
result[i] = y[i] + (alpha * x[i]);
}
}
});
}
}
@ -143,23 +123,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
else
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = alpha*x[i];
}
});
}
else
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = alpha*x[index];
result[i] = alpha * x[i];
}
}
});
}
}
@ -175,23 +145,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentNullException("x");
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i].Conjugate();
}
});
}
else
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index].Conjugate();
result[i] = x[i].Conjugate();
}
}
});
}
/// <summary>
@ -260,23 +220,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] + y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index] + y[index];
result[i] = x[i] + y[i];
}
}
});
}
/// <summary>
@ -311,23 +261,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] - y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index] - y[index];
result[i] = x[i] - y[i];
}
}
});
}
/// <summary>
@ -362,23 +302,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]*y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index]*y[index];
result[i] = x[i] * y[i];
}
}
});
}
/// <summary>
@ -413,23 +343,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]/y[i];
}
});
}
else
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index]/y[index];
result[i] = x[i] / y[i];
}
}
});
}
/// <summary>

126
src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs

@ -76,43 +76,23 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
else if (alpha == 1.0)
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + x[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = y[index] + x[index];
result[i] = y[i] + x[i];
}
}
});
}
else
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + (alpha*x[i]);
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = y[index] + (alpha*x[index]);
result[i] = y[i] + (alpha * x[i]);
}
}
});
}
}
@ -140,23 +120,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
else
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = alpha*x[i];
}
});
}
else
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = alpha*x[index];
result[i] = alpha * x[i];
}
}
});
}
}
@ -244,23 +214,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] + y[i];
}
});
}
else
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index] + y[index];
result[i] = x[i] + y[i];
}
}
});
}
/// <summary>
@ -295,23 +255,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] - y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index] - y[index];
result[i] = x[i] - y[i];
}
}
});
}
/// <summary>
@ -346,23 +296,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]*y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index]*y[index];
result[i] = x[i] * y[i];
}
}
});
}
/// <summary>
@ -397,23 +337,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]/y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index]/y[index];
result[i] = x[i] / y[i];
}
}
});
}
/// <summary>

126
src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs

@ -76,43 +76,23 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
else if (alpha == 1.0)
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + x[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = y[index] + x[index];
result[i] = y[i] + x[i];
}
}
});
}
else
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = y[i] + (alpha*x[i]);
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = y[index] + (alpha*x[index]);
result[i] = y[i] + (alpha * x[i]);
}
}
});
}
}
@ -140,23 +120,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
}
else
{
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = alpha*x[i];
}
});
}
else
CommonParallel.For(0, x.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = alpha*x[index];
result[i] = alpha * x[i];
}
}
});
}
}
@ -244,23 +214,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] + y[i];
}
});
}
else
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index] + y[index];
result[i] = x[i] + y[i];
}
}
});
}
/// <summary>
@ -295,23 +255,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i] - y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index] - y[index];
result[i] = x[i] - y[i];
}
}
});
}
/// <summary>
@ -346,23 +296,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]*y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index]*y[index];
result[i] = x[i] * y[i];
}
}
});
}
/// <summary>
@ -397,23 +337,13 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (Control.ParallelizeOperation(x.Length))
{
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (int i = a; i < b; i++)
{
result[i] = x[i]/y[i];
}
});
}
else
CommonParallel.For(0, y.Length, 4096, (a, b) =>
{
for (var index = 0; index < x.Length; index++)
for (int i = a; i < b; i++)
{
result[index] = x[index]/y[index];
result[i] = x[i] / y[i];
}
}
});
}
/// <summary>

179
src/Numerics/Threading/CommonParallel.cs

@ -31,14 +31,15 @@
namespace MathNet.Numerics.Threading
{
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
#if (PORTABLE || NET35)
using System.Linq;
using Properties;
#else
#if NET35
using Partitioner = MathNet.Numerics.Partitioner;
#endif
#if !PORTABLE
using System.Collections.Concurrent;
using System.Collections.Generic;
#endif
/// <summary>
@ -46,6 +47,15 @@ namespace MathNet.Numerics.Threading
/// </summary>
public static class CommonParallel
{
private static ParallelOptions CreateParallelOptions()
{
return new ParallelOptions
{
MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads,
TaskScheduler = Control.TaskScheduler,
};
}
/// <summary>
/// Executes a for loop in which iterations may run in parallel.
/// </summary>
@ -79,39 +89,18 @@ namespace MathNet.Numerics.Threading
return;
}
var maxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads;
// Special case: not worth to parallelize, inline
if (Control.DisableParallelization || maxDegreeOfParallelism < 2 || (rangeSize*2) > length)
if (Control.NumberOfParallelWorkerThreads < 2 || (rangeSize * 2) > length)
{
body(fromInclusive, toExclusive);
return;
}
#if (PORTABLE || NET35)
var tasks = new Task[Math.Min(maxDegreeOfParallelism, length/rangeSize)];
rangeSize = (toExclusive - fromInclusive)/tasks.Length;
// partition the jobs into separate sets for each but the last worked thread
for (var i = 0; i < tasks.Length - 1; i++)
{
var start = fromInclusive + (i*rangeSize);
var stop = fromInclusive + ((i + 1)*rangeSize);
tasks[i] = Task.Factory.StartNew(() => body(start, stop));
}
// add another set for last worker thread
tasks[tasks.Length - 1] =
Task.Factory.StartNew(() => body(fromInclusive + ((tasks.Length - 1)*rangeSize), toExclusive));
Task.WaitAll(tasks);
#else
// Common case
Parallel.ForEach(
Partitioner.Create(fromInclusive, toExclusive, rangeSize),
new ParallelOptions {MaxDegreeOfParallelism = maxDegreeOfParallelism},
(range, loopState) => body(range.Item1, range.Item2));
#endif
CreateParallelOptions(),
range => body(range.Item1, range.Item2));
}
/// <summary>
@ -136,7 +125,7 @@ namespace MathNet.Numerics.Threading
}
// Special case: straight execution without parallelism
if (Control.DisableParallelization || Control.NumberOfParallelWorkerThreads < 2)
if (Control.NumberOfParallelWorkerThreads < 2)
{
for (int i = 0; i < actions.Length; i++)
{
@ -146,27 +135,9 @@ namespace MathNet.Numerics.Threading
}
// Common case
#if (PORTABLE || NET35)
var tasks = new Task[actions.Length];
for (var i = 0; i < tasks.Length; i++)
{
Action action = actions[i];
if (action == null)
{
throw new ArgumentException(String.Format(Resources.ArgumentItemNull, "actions"), "actions");
}
tasks[i] = Task.Factory.StartNew(action);
}
Task.WaitAll(tasks);
#else
Parallel.Invoke(
new ParallelOptions
{
MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads
},
CreateParallelOptions(),
actions);
#endif
}
/// <summary>
@ -179,14 +150,8 @@ namespace MathNet.Numerics.Threading
/// <returns>The selected value.</returns>
public static T Aggregate<T>(int fromInclusive, int toExclusive, Func<int, T> select, Func<T[], T> reduce)
{
if (select == null)
{
throw new ArgumentNullException("select");
}
if (reduce == null)
{
throw new ArgumentNullException("reduce");
}
if (select == null) throw new ArgumentNullException("select");
if (reduce == null) throw new ArgumentNullException("reduce");
// Special case: no action
if (fromInclusive >= toExclusive)
@ -201,7 +166,7 @@ namespace MathNet.Numerics.Threading
}
// Special case: straight execution without parallelism
if (Control.DisableParallelization || Control.NumberOfParallelWorkerThreads < 2)
if (Control.NumberOfParallelWorkerThreads < 2)
{
var mapped = new T[toExclusive - fromInclusive];
for (int k = 0; k < mapped.Length; k++)
@ -211,49 +176,12 @@ namespace MathNet.Numerics.Threading
return reduce(mapped);
}
#if (PORTABLE || NET35)
var tasks = new Task<T>[Control.NumberOfParallelWorkerThreads];
var size = (toExclusive - fromInclusive) / tasks.Length;
// partition the jobs into separate sets for each but the last worked thread
for (var i = 0; i < tasks.Length - 1; i++)
{
var start = fromInclusive + (i * size);
var stop = fromInclusive + ((i + 1) * size);
tasks[i] = Task.Factory.StartNew(() =>
{
var mapped = new T[stop - start];
for (int k = 0; k < mapped.Length; k++)
{
mapped[k] = select(k + start);
}
return reduce(mapped);
});
}
// add another set for last worker thread
tasks[tasks.Length - 1] = Task.Factory.StartNew(() =>
{
var start = fromInclusive + ((tasks.Length - 1) * size);
var mapped = new T[toExclusive - start];
for (int k = 0; k < mapped.Length; k++)
{
mapped[k] = select(k + start);
}
return reduce(mapped);
});
return Task.Factory
.ContinueWhenAll(tasks, tsk => reduce(tsk.Select(t => t.Result).ToArray()))
.Result;
#else
// Common case
var intermediateResults = new List<T>();
var syncLock = new object();
var maxThreads = Control.DisableParallelization ? 1 : Control.NumberOfParallelWorkerThreads;
Parallel.ForEach(
Partitioner.Create(fromInclusive, toExclusive),
new ParallelOptions {MaxDegreeOfParallelism = maxThreads},
CreateParallelOptions(),
() => new List<T>(),
(range, loop, localData) =>
{
@ -273,7 +201,6 @@ namespace MathNet.Numerics.Threading
}
});
return reduce(intermediateResults.ToArray());
#endif
}
/// <summary>
@ -285,14 +212,8 @@ namespace MathNet.Numerics.Threading
/// <returns>The selected value.</returns>
public static TOut Aggregate<T, TOut>(T[] array, Func<int, T, TOut> select, Func<TOut[], TOut> reduce)
{
if (select == null)
{
throw new ArgumentNullException("select");
}
if (reduce == null)
{
throw new ArgumentNullException("reduce");
}
if (select == null) throw new ArgumentNullException("select");
if (reduce == null) throw new ArgumentNullException("reduce");
// Special case: no action
if (array == null || array.Length == 0)
@ -307,7 +228,7 @@ namespace MathNet.Numerics.Threading
}
// Special case: straight execution without parallelism
if (Control.DisableParallelization || Control.NumberOfParallelWorkerThreads < 2)
if (Control.NumberOfParallelWorkerThreads < 2)
{
var mapped = new TOut[array.Length];
for (int k = 0; k < mapped.Length; k++)
@ -317,49 +238,12 @@ namespace MathNet.Numerics.Threading
return reduce(mapped);
}
#if (PORTABLE || NET35)
var tasks = new Task<TOut>[Control.NumberOfParallelWorkerThreads];
var size = array.Length / tasks.Length;
// partition the jobs into separate sets for each but the last worked thread
for (var i = 0; i < tasks.Length - 1; i++)
{
var start = (i * size);
var stop = ((i + 1) * size);
tasks[i] = Task.Factory.StartNew(() =>
{
var mapped = new TOut[stop - start];
for (int k = 0; k < mapped.Length; k++)
{
mapped[k] = select(k + start, array[k + start]);
}
return reduce(mapped);
});
}
// add another set for last worker thread
tasks[tasks.Length - 1] = Task.Factory.StartNew(() =>
{
var start = ((tasks.Length - 1) * size);
var mapped = new TOut[array.Length - start];
for (int k = 0; k < mapped.Length; k++)
{
mapped[k] = select(k + start, array[k + start]);
}
return reduce(mapped);
});
return Task.Factory
.ContinueWhenAll(tasks, tsk => reduce(tsk.Select(t => t.Result).ToArray()))
.Result;
#else
// Common case
var intermediateResults = new List<TOut>();
var syncLock = new object();
var maxThreads = Control.DisableParallelization ? 1 : Control.NumberOfParallelWorkerThreads;
Parallel.ForEach(
Partitioner.Create(0, array.Length),
new ParallelOptions {MaxDegreeOfParallelism = maxThreads},
CreateParallelOptions(),
() => new List<TOut>(),
(range, loop, localData) =>
{
@ -379,7 +263,6 @@ namespace MathNet.Numerics.Threading
}
});
return reduce(intermediateResults.ToArray());
#endif
}
/// <summary>

Loading…
Cancel
Save