From 94af0578c844045a26ed090006fcb80888fbb940 Mon Sep 17 00:00:00 2001 From: Marcus Cuda Date: Thu, 20 Aug 2009 23:02:05 +0800 Subject: [PATCH] Parellel: found problem with tests, they were only testing the list version - added set versions fixed bug when no tasks were ran Signed-off-by: Marcus Cuda --- src/Numerics/Threading/Parallel.cs | 23 ++-- .../ThreadingTests/ParallelForEachTests.cs | 120 +++++++++++++++++- 2 files changed, 129 insertions(+), 14 deletions(-) diff --git a/src/Numerics/Threading/Parallel.cs b/src/Numerics/Threading/Parallel.cs index fff725e7..5d04a9ed 100644 --- a/src/Numerics/Threading/Parallel.cs +++ b/src/Numerics/Threading/Parallel.cs @@ -123,14 +123,6 @@ namespace MathNet.Numerics.Threading throw new ArgumentNullException("body"); } - // source is a IList, call For instead. - if (source is IList) - { - var list = (IList)source; - For(0, list.Count, i => body(list[i])); - return; - } - // fast forward execution in case parallelization is disabled if (Control.DisableParallelization || ThreadQueue.ThreadCount <= 1 @@ -144,6 +136,14 @@ namespace MathNet.Numerics.Threading return; } + // source is a IList, call For instead. + if (source is IList) + { + var list = (IList)source; + For(0, list.Count, i => body(list[i])); + return; + } + var enumerator = source.GetEnumerator(); var maxBlockSize = Control.InitialThreadBlockSize; var scalingFactor = Control.BlockScalingFactor; @@ -175,8 +175,11 @@ namespace MathNet.Numerics.Threading maxBlockSize = Math.Min(Control.MaximumBlockSize, maxBlockSize * scalingFactor); } - WaitForTasksToComplete(tasks.ToArray()); - CollectExceptionsAndDisposeTasks(tasks); + if (tasks.Count > 0) + { + WaitForTasksToComplete(tasks.ToArray()); + CollectExceptionsAndDisposeTasks(tasks); + } } /// diff --git a/src/UnitTests/ThreadingTests/ParallelForEachTests.cs b/src/UnitTests/ThreadingTests/ParallelForEachTests.cs index cb00ed0c..c327e77a 100644 --- a/src/UnitTests/ThreadingTests/ParallelForEachTests.cs +++ b/src/UnitTests/ThreadingTests/ParallelForEachTests.cs @@ -39,7 +39,7 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests { [Test, ApartmentState(ApartmentState.MTA)] [Column( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] - public void ParallelForEachInvokesEveryItemOnceMTAOnePerCore(int count) + public void ParallelForEachInvokesEveryItemInListOnceMTAOnePerCore(int count) { // ensure One-Per-Core ThreadQueue.Start(Environment.ProcessorCount); @@ -67,7 +67,7 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests [Test, ApartmentState(ApartmentState.STA)] [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] - public void ParallelForEachInvokesEveryItemOnceSTAOnePerCore(int count) + public void ParallelForEachInvokesEveryItemInListOnceSTAOnePerCore(int count) { // ensure One-Per-Core ThreadQueue.Start(Environment.ProcessorCount); @@ -95,7 +95,7 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests [Test, ApartmentState(ApartmentState.MTA)] [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] - public void ParallelForEachInvokesEveryItemOnceMTATwoPerCore(int count) + public void ParallelForEachInvokesEveryItemInListOnceMTATwoPerCore(int count) { // ensure Two-Per-Core ThreadQueue.Start(2 * Environment.ProcessorCount); @@ -123,7 +123,7 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests [Test, ApartmentState(ApartmentState.STA)] [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] - public void ParallelForEachInvokesEveryItemOnceSTATwoPerCore(int count) + public void ParallelForEachInvokesEveryItemInListOnceSTATwoPerCore(int count) { // ensure Two-Per-Core ThreadQueue.Start(2 * Environment.ProcessorCount); @@ -149,6 +149,118 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests } } + [Test, ApartmentState(ApartmentState.MTA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInSetOnceMTAOnePerCore(int count) + { + // ensure One-Per-Core + ThreadQueue.Start(Environment.ProcessorCount); + + var items = new double[count]; + var pairs = new HashSet>(); + for (var i = 0; i < items.Length; i++) + { + pairs.Add(new KeyValuePair(i, i)); + } + Parallel.ForEach(pairs, pair => items[pair.Key] = pair.Value); + + Parallel.ForEach(pairs, + pair => + { + items[pair.Key] = pair.Value + 1000; + } + ); + + for (int i = 0; i < items.Length; i++) + { + Assert.AreEqual(1000 + i, items[i], i.ToString()); + } + } + + [Test, ApartmentState(ApartmentState.STA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInSetOnceSTAOnePerCore(int count) + { + // ensure One-Per-Core + ThreadQueue.Start(Environment.ProcessorCount); + + var items = new double[count]; + var pairs = new HashSet>(); + for (var i = 0; i < items.Length; i++) + { + pairs.Add(new KeyValuePair(i, i)); + } + Parallel.ForEach(pairs, pair => items[pair.Key] = pair.Value); + + Parallel.ForEach(pairs, + pair => + { + items[pair.Key] = pair.Value + 1000; + } + ); + + for (int i = 0; i < items.Length; i++) + { + Assert.AreEqual(1000 + i, items[i], i.ToString()); + } + } + + [Test, ApartmentState(ApartmentState.MTA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInSetOnceMTATwoPerCore(int count) + { + // ensure Two-Per-Core + ThreadQueue.Start(2 * Environment.ProcessorCount); + + var items = new double[count]; + var pairs = new HashSet>(); + for (var i = 0; i < items.Length; i++) + { + pairs.Add(new KeyValuePair(i, i)); + } + Parallel.ForEach(pairs, pair => items[pair.Key] = pair.Value); + + Parallel.ForEach(pairs, + pair => + { + items[pair.Key] = pair.Value + 1000; + } + ); + + for (int i = 0; i < items.Length; i++) + { + Assert.AreEqual(1000 + i, items[i], i.ToString()); + } + } + + [Test, ApartmentState(ApartmentState.STA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInSetOnceSTATwoPerCore(int count) + { + // ensure Two-Per-Core + ThreadQueue.Start(2 * Environment.ProcessorCount); + + var items = new double[count]; + var pairs = new HashSet>(); + for (var i = 0; i < items.Length; i++) + { + pairs.Add(new KeyValuePair(i, i)); + } + Parallel.ForEach(pairs, pair => items[pair.Key] = pair.Value); + + Parallel.ForEach(pairs, + pair => + { + items[pair.Key] = pair.Value + 1000; + } + ); + + for (int i = 0; i < items.Length; i++) + { + Assert.AreEqual(1000 + i, items[i], i.ToString()); + } + } + [Test, ApartmentState(ApartmentState.MTA)] public void DoesNotGetConfusedByMultipleStartShutdown() {