private static IEnumerable <Labeled <Action <ParVerifier, ParallelQuery <int> > > > HardQueries() { yield return(Labeled.Label <Action <ParVerifier, ParallelQuery <int> > >("Select+Where+TakeWhile+ToArray", (verifier, query) => query.Select(x => verifier.Verify(x)).Where(x => true).TakeWhile((x, i) => true).ToArray())); yield return(Labeled.Label <Action <ParVerifier, ParallelQuery <int> > >("Select+Where+TakeWhile+foreach", (verifier, query) => query.Select(x => verifier.Verify(x)).Where(x => true).TakeWhile((x, i) => true).Enumerate())); yield return(Labeled.Label <Action <ParVerifier, ParallelQuery <int> > >("Where+Select+ElementAt", (verifier, query) => query.Where(x => true).Select(x => verifier.Verify(x)).ElementAt(8))); yield return(Labeled.Label <Action <ParVerifier, ParallelQuery <int> > >("Where+Select+foreach", (verifier, query) => query.Where(x => true).Select(x => verifier.Verify(x)).Enumerate())); }
/// <summary> /// Get a a combination of partitioned data sources, degree of parallelism, expected resulting dop, /// query to execute on the data source, and mode of execution. /// </summary> /// <param name="dop">A set of the desired degrees of parallelism to be employed.</param> /// <returns>Entries for test data. /// The first element is the Labeled{ParallelQuery{int}} data source, /// the second is the desired dop, /// the third is the expected resulting dop, /// the fourth is the query to execute on the data source, /// and the fifth is the execution mode.</returns> public static IEnumerable <object[]> WithExecutionModeQueryData(int[] dops) { foreach (int dop in dops) { // Use data sources that have a fixed set of elements in each partition (no load balancing between the partitions). // PLINQ will assign a Task to each partition, and no other task will process that partition. As a result, we can // verify that we get a known number of tasks doing the processing. (This doesn't guarantee that such tasks are // running in parallel, but it's "good enough". If PLINQ's implementation is ever changed to proactively exit // tasks and spawn replicas to continue the processing, ala Parallel.For*, this test will need to be updated.) int count = 3 * dop; // 3 chosen arbitrarily as a small value; any positive value will do var partitionedRanges = new Labeled <ParallelQuery <int> >[] { Labeled.Label("ParallelEnumerable.Range", ParallelEnumerable.Range(0, count)), Labeled.Label("Partitioner.Create", Partitioner.Create(UnorderedSources.GetRangeArray(0, count), loadBalance: false).AsParallel()) }; // For each source and mode, get both unordered and ordered queries that should easily parallelize for all execution modes foreach (ParallelExecutionMode mode in new[] { ParallelExecutionMode.Default, ParallelExecutionMode.ForceParallelism }) { foreach (Labeled <ParallelQuery <int> > source in partitionedRanges) { foreach (var query in EasyUnorderedQueries(count)) { yield return new object[] { source, dop, dop, query, mode } } ; foreach (var query in EasyOrderedQueries(count)) { yield return new object[] { source.Order(), dop, dop, query, mode } } ; } } // For each source, get queries that are difficult to parallelize and thus only do so with ForceParallelism. foreach (Labeled <ParallelQuery <int> > source in partitionedRanges) { foreach (var query in HardQueries(count)) { yield return(new object[] { source, dop, dop, query, ParallelExecutionMode.ForceParallelism }); // should parallelize, thus expected DOP of > 1 yield return(new object[] { source, dop, 1, query, ParallelExecutionMode.Default }); // won't parallelize, thus expected DOP of 1 } } } }
public static IEnumerable <object[]> AggregateExceptionData(int[] counts) { foreach (object[] results in UnorderedSources.Ranges(counts.Cast <int>())) { Labeled <ParallelQuery <int> > query = (Labeled <ParallelQuery <int> >)results[0]; if (query.ToString().StartsWith("Partitioner")) { yield return(new object[] { Labeled.Label(query.ToString(), Partitioner.Create(UnorderedSources.GetRangeArray(0, (int)results[1]), false).AsParallel()), results[1] }); } else if (query.ToString().StartsWith("Enumerable.Range")) { yield return(new object[] { Labeled.Label(query.ToString(), new StrictPartitioner <int>(Partitioner.Create(Enumerable.Range(0, (int)results[1]), EnumerablePartitionerOptions.None), (int)results[1]).AsParallel()), results[1] }); } else { yield return(results); } } }
private static IEnumerable <Labeled <ParallelQuery <int> > > LabeledRanges(int start, int count) { yield return(Labeled.Label("ParallelEnumerable.Range", ParallelEnumerable.Range(start, count))); yield return(Labeled.Label("Enumerable.Range", Enumerable.Range(start, count).AsParallel())); int[] rangeArray = GetRangeArray(start, count); yield return(Labeled.Label("Array", rangeArray.AsParallel())); if (count < AdditionalTypeLimit + 1) { yield return(Labeled.Label("Partitioner", Partitioner.Create(rangeArray).AsParallel())); IList <int> rangeList = rangeArray.ToList(); yield return(Labeled.Label("List", rangeList.AsParallel())); yield return(Labeled.Label("ReadOnlyCollection", new ReadOnlyCollection <int>(rangeList).AsParallel())); } }
public static IEnumerable <object[]> NotLoadBalancedDegreeData(object[] counts, object[] degrees) { foreach (object[] results in DegreeData(counts, degrees)) { Labeled <ParallelQuery <int> > query = (Labeled <ParallelQuery <int> >)results[0]; if (query.ToString().StartsWith("Partitioner")) { yield return(new object[] { Labeled.Label(query.ToString(), Partitioner.Create(UnorderedSources.GetRangeArray(0, (int)results[1]), false).AsParallel()), results[1], results[2] }); } else if (query.ToString().StartsWith("Enumerable.Range")) { yield return(new object[] { Labeled.Label(query.ToString(), new StrictPartitioner <int>(Partitioner.Create(Enumerable.Range(0, (int)results[1]), EnumerablePartitionerOptions.NoBuffering), (int)results[1]).AsParallel()), results[1], results[2] }); } else { yield return(results); } } }
private static IEnumerable <Labeled <Action <UsedTaskTracker, ParallelQuery <int> > > > EasyOrderedQueries(int count) { yield return(Labeled.Label <Action <UsedTaskTracker, ParallelQuery <int> > >("Where+Select+Concat(AsOrdered+Where)+ToList", (verifier, query) => query.Where(x => true).Select(x => verifier.AddCurrent(x)).Concat(Enumerable.Range(0, count).AsParallel().AsOrdered().Where(x => true)).ToList())); }
private static IEnumerable <Labeled <Action <ParVerifier, ParallelQuery <int> > > > EasyOrderedQueries() { yield return(Labeled.Label <Action <ParVerifier, ParallelQuery <int> > >("Where+Select+Concat(AsOrdered+Where)+ToList", (verifier, query) => query.Where(x => true).Select(x => verifier.Verify(x)).Concat(Enumerable.Range(0, 1000).AsParallel().AsOrdered().Where(x => true)).ToList())); }
// Return an enumerable which throws on first MoveNext. // Useful for testing promptness of cancellation. public static IEnumerable <object[]> ThrowOnFirstEnumeration() { yield return(new object[] { Labeled.Label("ThrowOnFirstEnumeration", Enumerables <int> .ThrowOnEnumeration().AsParallel()), 8 }); }