diff --git a/src/Numerics/Compatibility.cs b/src/Numerics/Compatibility.cs index 0f605d90..4499bde4 100644 --- a/src/Numerics/Compatibility.cs +++ b/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> Create(int fromInclusive, int toExclusive) + { + var rangeSize = Math.Max(1, (toExclusive - fromInclusive) / Control.NumberOfParallelWorkerThreads); + return Create(fromInclusive, toExclusive, rangeSize); + } + + public static IEnumerable> 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> 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(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(IEnumerable source, ParallelOptions parallelOptions, Action 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( + IEnumerable source, + ParallelOptions parallelOptions, + Func localInit, + Func body, + Action 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> Create(int fromInclusive, int toExclusive) + { + var rangeSize = Math.Max(1, (toExclusive - fromInclusive) / Control.NumberOfParallelWorkerThreads); + return Create(fromInclusive, toExclusive, rangeSize); + } + + public static OrderablePartitioner> 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> 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(item, num2); + num += rangeSize; + } + } + } } #endif diff --git a/src/Numerics/Control.cs b/src/Numerics/Control.cs index edecd791..21bb583b 100644 --- a/src/Numerics/Control.cs +++ b/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 /// public static bool ThreadSafeRandomNumberGenerators { get; set; } - /// - /// Gets or sets a value indicating whether parallelization shall be disabled globally. - /// - public static bool DisableParallelization { get; set; } - /// /// Gets or sets the linear algebra provider. Consider to use UseNativeMKL or UseManaged instead. /// @@ -157,6 +152,11 @@ namespace MathNet.Numerics set { _numberOfThreads = Math.Max(1, Math.Min(1024, value)); } } + /// + /// Gets or sets the TaskScheduler used to schedule the worker tasks. + /// + public static TaskScheduler TaskScheduler { get; set; } + /// /// 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); } } - /// - /// Given the number elements, should the operation be parallelized. - /// - /// The number elements to check. - /// true if the operation should be parallelized; false otherwise. - public static bool ParallelizeOperation(int elements) - { - return !DisableParallelization && NumberOfParallelWorkerThreads >= 2 && elements >= ParallelizeElements; - } - /// /// Maximum number of columns to print in ToString methods by default. /// diff --git a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs b/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs index 75021366..7afcebea 100644 --- a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex.cs +++ b/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(); } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// diff --git a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs b/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs index 85966372..003054bf 100644 --- a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Complex32.cs +++ b/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(); } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// diff --git a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs b/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs index 8290e256..4d19b341 100644 --- a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Double.cs +++ b/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]; } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// diff --git a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs b/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs index 78a122f6..024cca70 100644 --- a/src/Numerics/Providers/LinearAlgebra/ManagedLinearAlgebraProvider.Single.cs +++ b/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]; } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// @@ -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]; } - } + }); } /// diff --git a/src/Numerics/Threading/CommonParallel.cs b/src/Numerics/Threading/CommonParallel.cs index fabb548b..6e93d465 100644 --- a/src/Numerics/Threading/CommonParallel.cs +++ b/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 /// @@ -46,6 +47,15 @@ namespace MathNet.Numerics.Threading /// public static class CommonParallel { + private static ParallelOptions CreateParallelOptions() + { + return new ParallelOptions + { + MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads, + TaskScheduler = Control.TaskScheduler, + }; + } + /// /// Executes a for loop in which iterations may run in parallel. /// @@ -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)); } /// @@ -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 } /// @@ -179,14 +150,8 @@ namespace MathNet.Numerics.Threading /// The selected value. public static T Aggregate(int fromInclusive, int toExclusive, Func select, Func 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[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(); var syncLock = new object(); - var maxThreads = Control.DisableParallelization ? 1 : Control.NumberOfParallelWorkerThreads; Parallel.ForEach( Partitioner.Create(fromInclusive, toExclusive), - new ParallelOptions {MaxDegreeOfParallelism = maxThreads}, + CreateParallelOptions(), () => new List(), (range, loop, localData) => { @@ -273,7 +201,6 @@ namespace MathNet.Numerics.Threading } }); return reduce(intermediateResults.ToArray()); -#endif } /// @@ -285,14 +212,8 @@ namespace MathNet.Numerics.Threading /// The selected value. public static TOut Aggregate(T[] array, Func select, Func 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[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(); 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(), (range, loop, localData) => { @@ -379,7 +263,6 @@ namespace MathNet.Numerics.Threading } }); return reduce(intermediateResults.ToArray()); -#endif } ///