TheDeveloperBlog.com

Home | Contact Us

C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML

C# AsParallel Example

This C# tutorial shows how to use the AsParallel extension method from System.Linq. It provides a benchmark of AsParallel on array data.

AsParallel. Query expressions can be run in parallel.

With the AsParallel extension method, we enable parallel threads to improve performance. We show a method that becomes twice as fast on a dual-core machine when AsParallel is used.

Threads

Note: AsParallel can make certain queries much faster, and other queries much slower.

Note 2: Performance depends on the target machine and the characteristics of the query and your data source.

Example. We introduce two methods. SumDefault sums all the elements in the array with the Sum method alone. SumAsParallel first calls AsParallel on the array. It then calls Sum on the result of AsParallel. The two methods have the same result.

Sum

C# program that uses AsParallel

using System;
using System.Diagnostics;
using System.Linq;

class Program
{
    static int SumDefault(int[] array)
    {
	/*
	 *
	 * Sum all numbers in the array.
	 *
	 * */
	return array.Sum();
    }

    static int SumAsParallel(int[] array)
    {
	/*
	 *
	 * Enable parallelization and then sum.
	 *
	 * */
	return array.AsParallel().Sum();
    }

    static void Main()
    {
	// Generate array.
	int[] array = Enumerable.Range(0, short.MaxValue).ToArray();

	// Test methods.
	Console.WriteLine(SumAsParallel(array));
	Console.WriteLine(SumDefault(array));

	const int m = 10000;
	var s1 = Stopwatch.StartNew();
	for (int i = 0; i < m; i++)
	{
	    SumDefault(array);
	}
	s1.Stop();
	var s2 = Stopwatch.StartNew();
	for (int i = 0; i < m; i++)
	{
	    SumAsParallel(array);
	}
	s2.Stop();
	Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
	    m).ToString("0.00 ns"));
	Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
	    m).ToString("0.00 ns"));
	Console.Read();
    }
}

Result for 32767 elements

536821761
536821761
232450.53 ns
118515.85 ns

Performance result. We can see that AsParallel makes the query twice as fast. This is the result on a dual-core machine under light load. If you have only one processor core, the results should be close.

Also: If you have more than two processor cores, the AsParallel call may increase performance even more.

Discussion. AsParallel will not have great results on all kinds of queries. For small collections, AsParallel will be slower because of the extra method call. For example, I changed the array to only have two elements with Enumerable.Range(0, 2).

Enumerable.Range

Result: With two elements, AsParallel makes the query run over 200 times slower instead of two times faster.

Result with two elements

1
1
   48.84 ns
10914.27 ns

Example 2. Next, we show a program that you must never run. It uses a static field in a Func implementation. It uses this Func in a parallel query (created by AsParallel()). The program is supposed to count the even numbers in the int array.

FuncInt Array

However: The AsParallel call causes multiple threads to access the static field. The threads use IsEvenCounter, a non-thread-safe method.

Static Field

So: The results are unpredictable. In the array with 500 even numbers, this program will count 478, 500, or 517 even numbers.

Odd, Even

If you remove the AsParallel() call from the statement, the result is always 500. This program proves that AsParallel is actually creating multiple threads. And this exposes an error in the program design.

C# program that shows AsParallel problem

using System;
using System.Linq;

class Program
{
    static int _counter;
    static bool IsEvenCounter(int value)
    {
	// ... Return whether counter field is even.
	return Program._counter++ % 2 == 0;
    }

    static void Main()
    {
	Func<int, bool> func = Program.IsEvenCounter;
	int[] array = Enumerable.Range(0, 1000).ToArray();

	// ... Use parallel query ten times on the array.
	// ... Write number of results matched by Func.
	for (int i = 0; i < 10; i++)
	{
	    var result = array.AsParallel().Where(func);
	    Console.WriteLine(result.Count());
	}
    }
}

Output

517
514
500
509
500
478
500
508
500
501

Summary. It is tempting to think that AsParallel makes queries twice as fast if you call it on a computer with a dual-core processor. This is true on certain, long-running queries, but it makes small and fast queries more than 200 times slower.

Note: If you have a query that is computationally intensive, AsParallel might be helpful.

Tip: If you really need better performance an imperative method implementation, with for, might be even better.

For


Related Links

Adjectives Ado Ai Android Angular Antonyms Apache Articles Asp Autocad Automata Aws Azure Basic Binary Bitcoin Blockchain C Cassandra Change Coa Computer Control Cpp Create Creating C-Sharp Cyber Daa Data Dbms Deletion Devops Difference Discrete Es6 Ethical Examples Features Firebase Flutter Fs Git Go Hbase History Hive Hiveql How Html Idioms Insertion Installing Ios Java Joomla Js Kafka Kali Laravel Logical Machine Matlab Matrix Mongodb Mysql One Opencv Oracle Ordering Os Pandas Php Pig Pl Postgresql Powershell Prepositions Program Python React Ruby Scala Selecting Selenium Sentence Seo Sharepoint Software Spellings Spotting Spring Sql Sqlite Sqoop Svn Swift Synonyms Talend Testng Types Uml Unity Vbnet Verbal Webdriver What Wpf