It doesn't seem to do squat for the following test program. Is this because I'm testing with a small list?
static void Main(string[] args)
{
List<int> list = 0.UpTo(4);
Test(list.AsParallel());
Test(list);
}
private static void Test(IEnumerable<int> input)
{
var timer = new Stopwatch();
timer.Start();
var size = input.Count();
if (input.Where(IsOdd).Count() != size / 2)
throw new Exception("Failed to count the odds");
timer.Stop();
Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
}
private static bool IsOdd(int n)
{
Thread.Sleep(1000);
return n%2 == 1;
}
Both versions take 4 seconds to run.
AsParallel(IEnumerable) Enables parallelization of a query. AsParallel<TSource>(Partitioner<TSource>) Enables parallelization of a query, as sourced by a custom partitioner that is responsible for splitting the input sequence into partitions.
If you specify Default as a parameter to the WithExecutionMode extension method, PLINQ will execute the query in parallel if an improvement in performance is evident in executing the query in parallel. If not, PLINQ would execute the query just like a LINQ query.
Task Parallel Library cares about the static type of the sequence. It should be IParallelEnumerable<T>
for the operations to be handled by the TPL. You are casting the collection back to IEnumerable<T>
when you call Test
. Therefore, the compiler will resolve .Where
call on the sequence to System.Linq.Enumerable.Where
extension method instead of the parallel version provided by the TPL.
(Updating for .NET4 since this question ranks pretty high in a Google search for AsParallel())
Just a few changes will allow your example to work as I imagine you expected.
Change List<int> list = 0.UpTo(4);
to var list = Enumerable.Range(0, 4);
Your example would work if you added a function overload with a signature that takes a ParallelQuery...
private static void Test(ParallelQuery<int> input)
{
var timer = new Stopwatch();
timer.Start();
int size = input.Count();
if (input.Where(IsOdd).Count() != size / 2)
{
throw new Exception("Failed to count the odds");
}
timer.Stop();
Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
}
Alternatively, you could use LINQ syntax....
private static void Test(ParallelQuery<int> list)
{
var timer = Stopwatch.StartNew();
if ((from n in list.AsParallel()
where IsOdd(n)
select n).Count() != (list.Count() / 2))
{
throw new Exception("Failed to count the odds");
}
Console.WriteLine("Tested " + list.Count() + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
}
Hope this helps someone!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With