public static IEnumerable <object[]> SingleData(object[] elements, object[] counts) { foreach (int element in elements) { foreach (object[] results in UnorderedSources.Ranges(element, counts.Cast <int>())) { yield return(new object[] { results[0], results[1], element }); } foreach (object[] results in Sources.Ranges(element, counts.Cast <int>())) { yield return(new object[] { results[0], results[1], element }); } } }
private static IEnumerable <LabeledOperation> UnorderedRangeSources() { // The difference between this and the existing sources is more control is needed over the range creation. // Specifically, start/count won't be known until the nesting level is resolved at runtime. yield return(Label("ParallelEnumerable.Range", (start, count, ignore) => ParallelEnumerable.Range(start, count))); yield return(Label("Enumerable.Range", (start, count, ignore) => Enumerable.Range(start, count).AsParallel())); yield return(Label("Array", (start, count, ignore) => UnorderedSources.GetRangeArray(start, count).AsParallel())); yield return(Label("Partitioner", (start, count, ignore) => Partitioner.Create(UnorderedSources.GetRangeArray(start, count)).AsParallel())); yield return(Label("List", (start, count, ignore) => UnorderedSources.GetRangeArray(start, count).ToList().AsParallel())); yield return(Label("ReadOnlyCollection", (start, count, ignore) => new ReadOnlyCollection <int>(UnorderedSources.GetRangeArray(start, count).ToList()).AsParallel())); }
/// <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); } } }
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); } } }