From bef57e21df3e37c6d22f1f4eff1fd604d4998bf2 Mon Sep 17 00:00:00 2001 From: Marcus Cuda Date: Tue, 1 Sep 2009 18:37:00 +0800 Subject: [PATCH] added some of the missing parallel tests Signed-off-by: Marcus Cuda --- src/Numerics/Threading/Parallel.cs | 1 + .../ThreadingTests/ParallelForEachTests.cs | 274 +++++++++++++++++- .../ThreadingTests/ParallelForTests.cs | 173 +++++++++++ 3 files changed, 442 insertions(+), 6 deletions(-) diff --git a/src/Numerics/Threading/Parallel.cs b/src/Numerics/Threading/Parallel.cs index 1d710c90..44bc4a43 100644 --- a/src/Numerics/Threading/Parallel.cs +++ b/src/Numerics/Threading/Parallel.cs @@ -160,6 +160,7 @@ namespace MathNet.Numerics.Threading { localresult = body(i, localresult); } + localFinally(localresult); return; } diff --git a/src/UnitTests/ThreadingTests/ParallelForEachTests.cs b/src/UnitTests/ThreadingTests/ParallelForEachTests.cs index c327e77a..e3016716 100644 --- a/src/UnitTests/ThreadingTests/ParallelForEachTests.cs +++ b/src/UnitTests/ThreadingTests/ParallelForEachTests.cs @@ -38,7 +38,7 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests public class ParallelForEachTests { [Test, ApartmentState(ApartmentState.MTA)] - [Column( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] public void ParallelForEachInvokesEveryItemInListOnceMTAOnePerCore(int count) { // ensure One-Per-Core @@ -50,7 +50,7 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests { pairs.Add(new KeyValuePair(i, i)); } - Parallel.ForEach(pairs, pair => items[pair.Key] = pair.Value ); + Parallel.ForEach(pairs, pair => items[pair.Key] = pair.Value); Parallel.ForEach(pairs, pair => @@ -61,7 +61,7 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests for (int i = 0; i < items.Length; i++) { - Assert.AreEqual(1000+i, items[i], i.ToString()); + Assert.AreEqual(1000 + i, items[i], i.ToString()); } } @@ -126,8 +126,8 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests public void ParallelForEachInvokesEveryItemInListOnceSTATwoPerCore(int count) { // ensure Two-Per-Core - ThreadQueue.Start(2 * Environment.ProcessorCount); - + ThreadQueue.Start(2 * Environment.ProcessorCount); + var items = new double[count]; var pairs = new List>(); for (var i = 0; i < items.Length; i++) @@ -310,7 +310,7 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests { var countSharedBetweenClosures = 0; var values = new int[10]; - + Assert.DoesNotThrow( () => Parallel.ForEach(values, @@ -336,5 +336,267 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests Assert.AreEqual(1000, countSharedBetweenClosures); } + + [Test, ApartmentState(ApartmentState.MTA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInListOnceMTAOnePerCoreWithIntialAndFinally(int count) + { + // ensure One-Per-Core + ThreadQueue.Start(Environment.ProcessorCount); + + var pairs = new List>(); + for (var i = 0; i < count; i++) + { + pairs.Add(new KeyValuePair(i, 2)); + } + + var sum = 0.0; + var sync = new object(); + + Parallel.ForEach( + pairs, () => 0.0, (pair, localData) => localData += pair.Value, + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.STA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInListOnceSTAOnePerCoreWithIntialAndFinally(int count) + { + // ensure One-Per-Core + ThreadQueue.Start(Environment.ProcessorCount); + + var pairs = new List>(); + for (var i = 0; i < count; i++) + { + pairs.Add(new KeyValuePair(i, 2)); + } + + var sum = 0.0; + var sync = new object(); + + Parallel.ForEach( + pairs, () => 0.0, (pair, localData) => localData += pair.Value, + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.MTA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInListOnceMTATwoPerCoreWithIntialAndFinally(int count) + { + ThreadQueue.Start(2 * Environment.ProcessorCount); + + var pairs = new List>(); + for (var i = 0; i < count; i++) + { + pairs.Add(new KeyValuePair(i, 2)); + } + + var sum = 0.0; + var sync = new object(); + + Parallel.ForEach( + pairs, () => 0.0, (pair, localData) => localData += pair.Value, + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.STA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInListOnceSTATwoPerCoreWithIntialAndFinally(int count) + { + ThreadQueue.Start(2 * Environment.ProcessorCount); + + var pairs = new List>(); + for (var i = 0; i < count; i++) + { + pairs.Add(new KeyValuePair(i, 2)); + } + + var sum = 0.0; + var sync = new object(); + + Parallel.ForEach( + pairs, () => 0.0, (pair, localData) => localData += pair.Value, + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.MTA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInSetOnceMTAOnePerCoreWithIntialAndFinally(int count) + { + // ensure One-Per-Core + ThreadQueue.Start(Environment.ProcessorCount); + + var pairs = new HashSet>(); + for (var i = 0; i < count; i++) + { + pairs.Add(new KeyValuePair(i, 2)); + } + + var sum = 0.0; + var sync = new object(); + + Parallel.ForEach( + pairs, () => 0.0, (pair, localData) => localData += pair.Value, + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.STA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInSetOnceSTAOnePerCoreWithIntialAndFinally(int count) + { + // ensure One-Per-Core + ThreadQueue.Start(Environment.ProcessorCount); + + var pairs = new HashSet>(); + for (var i = 0; i < count; i++) + { + pairs.Add(new KeyValuePair(i, 2)); + } + + var sum = 0.0; + var sync = new object(); + + Parallel.ForEach( + pairs, () => 0.0, (pair, localData) => localData += pair.Value, + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.MTA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInSetOnceMTATwoPerCoreWithIntialAndFinally(int count) + { + ThreadQueue.Start(2 * Environment.ProcessorCount); + + var pairs = new HashSet>(); + for (var i = 0; i < count; i++) + { + pairs.Add(new KeyValuePair(i, 2)); + } + + var sum = 0.0; + var sync = new object(); + + Parallel.ForEach( + pairs, () => 0.0, (pair, localData) => localData += pair.Value, + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.STA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1001)] + public void ParallelForEachInvokesEveryItemInSetOnceSTATwoPerCoreWithIntialAndFinally(int count) + { + ThreadQueue.Start(2 * Environment.ProcessorCount); + + var pairs = new HashSet>(); + for (var i = 0; i < count; i++) + { + pairs.Add(new KeyValuePair(i, 2)); + } + + var sum = 0.0; + var sync = new object(); + + Parallel.ForEach( + pairs, () => 0.0, (pair, localData) => localData += pair.Value, + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test] + public void DoesDetectAndResolveRecursiveParallelizationWithIntialAndFinally() + { + var countSharedBetweenClosures = 0; + var values = new int[10]; + + Assert.DoesNotThrow( + () => + Parallel.ForEach(values, + j => Interlocked.Increment(ref countSharedBetweenClosures))); + + Assert.AreEqual(10, countSharedBetweenClosures); + countSharedBetweenClosures = 0; + + Parallel.ForEach(values, + i => + Parallel.ForEach(values, + j => Interlocked.Increment(ref countSharedBetweenClosures))); + + Assert.AreEqual(100, countSharedBetweenClosures); + countSharedBetweenClosures = 0; + + Parallel.ForEach(values, + i => + Parallel.ForEach(values, + j => + Parallel.ForEach(values, () => 0.0, + (iterator, localData) => Interlocked.Increment(ref countSharedBetweenClosures), + localResult => { return; } + ))); + + Assert.AreEqual(1000, countSharedBetweenClosures); + } } } \ No newline at end of file diff --git a/src/UnitTests/ThreadingTests/ParallelForTests.cs b/src/UnitTests/ThreadingTests/ParallelForTests.cs index 6865ae85..34f3a513 100644 --- a/src/UnitTests/ThreadingTests/ParallelForTests.cs +++ b/src/UnitTests/ThreadingTests/ParallelForTests.cs @@ -187,5 +187,178 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests Assert.AreEqual(1000, countSharedBetweenClosures); } + [Test, ApartmentState(ApartmentState.MTA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 101)] + public void ParallelForInvokesEveryItemOnceMTAOnePerCoreWithIntialAndFinally(int count) + { + var items = new double[count]; + + // ensure One-Per-Core + ThreadQueue.Start(Environment.ProcessorCount); + + var sum = 0.0; + for(var i = 0; i < items.Length; i++) + { + items[i] = 2; + } + var sync = new object(); + Parallel.For( + 0, + count, + () => 0.0, + (i, localData) =>localData += items[i], + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.STA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 101)] + public void ParallelForInvokesEveryItemOnceSTAOnePerCoreWithIntialAndFinally(int count) + { + var items = new double[count]; + + // ensure One-Per-Core + ThreadQueue.Start(Environment.ProcessorCount); + + var sum = 0.0; + for (var i = 0; i < items.Length; i++) + { + items[i] = 2; + } + var sync = new object(); + Parallel.For( + 0, + count, + () => 0.0, + (i, localData) => localData += items[i], + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.MTA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 101)] + public void ParallelForInvokesEveryItemOnceMTATwoPerCoreWithIntialAndFinally(int count) + { + var items = new double[count]; + + ThreadQueue.Start(2 * Environment.ProcessorCount); + + var sum = 0.0; + for (var i = 0; i < items.Length; i++) + { + items[i] = 2; + } + var sync = new object(); + Parallel.For( + 0, + count, + () => 0.0, + (i, localData) => localData += items[i], + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.STA)] + [Column(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 101)] + public void ParallelForInvokesEveryItemOnceSTATwoPerCoreWithIntialAndFinally(int count) + { + var items = new double[count]; + + ThreadQueue.Start(2 * Environment.ProcessorCount); + + var sum = 0.0; + for (var i = 0; i < items.Length; i++) + { + items[i] = 2; + } + var sync = new object(); + Parallel.For( + 0, + count, + () => 0.0, + (i, localData) => localData += items[i], + localResult => + { + lock (sync) + { + sum += localResult; + } + } + ); + Assert.AreEqual(count * 2, sum); + } + + [Test, ApartmentState(ApartmentState.MTA)] + public void DoesDetectAndResolveRecursiveParallelizationWithIntialAndFinally() + { + int countSharedBetweenClosures = 0; + + Assert.DoesNotThrow( + () => + Parallel.For( + 0, + 10, + () => 0.0, + (j, localData) => Interlocked.Increment(ref countSharedBetweenClosures), + localResult => { return; } + )); + + Assert.AreEqual(10, countSharedBetweenClosures); + countSharedBetweenClosures = 0; + + Parallel.For( + 0, + 10, + i => + Parallel.For( + 0, + 10, + () => 0.0, + (j, localData) => Interlocked.Increment(ref countSharedBetweenClosures), + localResult => { return; } + )); + + Assert.AreEqual(100, countSharedBetweenClosures); + countSharedBetweenClosures = 0; + + Parallel.For( + 0, + 10, + i => + Parallel.For( + 0, + 10, + j => + Parallel.For( + 0, + 10, + () => 0.0, + (k, localData) => Interlocked.Increment(ref countSharedBetweenClosures), + localResult => { return; } + ))); + + Assert.AreEqual(1000, countSharedBetweenClosures); + } } } \ No newline at end of file