Parallel programming with .NET

Visual Studio 2010 has some interesting new features, one of which is parallel programming. This simple example, written in C# and F#, tests the difference between serial and parallel computations of Fibonacci numbers. The example uses the System.Threading.Tasks.Parallel.For method. Indeed, there is about a 4-fold improvement on my quad-core multiprocessor for long computations but not for short computations. There is a trade-off between the size of the computation versus the overhead to create, schedule, and synchronize threads.

C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    
    class Program
    {

        Int32 fib(Int32 x)
        {
            if (x <= 2)
                return 1;
            else
                return fib(x - 1) + fib(x - 2);
        }

        static void Main(string[] args)
        {
            DateTime current;
            Program p = new Program();
            Stopwatch sw = new Stopwatch();
            double s = 0;
            sw.Reset();
            current = DateTime.Now;
            Console.WriteLine(current);
            sw.Start();
            for (int i = 0; i < 40; ++i)
                p.fib(i);
            sw.Stop();
            s = sw.Elapsed.TotalMilliseconds;
            System.Console.WriteLine("Serial = " + s);
            current = DateTime.Now;
            Console.WriteLine(current);

            double l = 0;
            sw.Reset();
            sw.Start();
            Parallel.For(0, 40, j =>
                {
                    p.fib(j);
                });
            sw.Stop();
            l = sw.Elapsed.TotalMilliseconds;
            System.Console.WriteLine("Parallel = " + l);
            current = DateTime.Now;
            Console.WriteLine(current);

            sw.Reset();
            sw.Start();
            for (int i = 0; i < 10; ++i)
                p.fib(40);
            sw.Stop();
            s = sw.Elapsed.TotalMilliseconds;
            System.Console.WriteLine("Serial2 = " + s);
            current = DateTime.Now;
            Console.WriteLine(current);

            sw.Reset();
            sw.Start();
            Parallel.For(0, 10, j =>
            {
                p.fib(40);
            });
            sw.Stop();
            l = sw.Elapsed.TotalMilliseconds;
            System.Console.WriteLine("Parallel = " + l);
            current = DateTime.Now;
            Console.WriteLine(current);
        }
    }
}

Output:

3/27/2010 6:54:22 AM
Serial = 3243.8431
3/27/2010 6:54:25 AM
Parallel = 3094.8497
3/27/2010 6:54:28 AM
Serial2 = 20070.4749
3/27/2010 6:54:48 AM
Parallel = 6129.799
3/27/2010 6:54:54 AM

F#:

// Learn more about F# at http://fsharp.net

let rec fib x = if x <= 2 then 1 else fib(x-1) + fib(x-2)

let sw = System.Diagnostics.Stopwatch();
sw.Reset();
let c0 = System.DateTime.Now
System.Console.WriteLine(c0);
sw.Start();
for x in 0..40 do
    fib(x);
    done
sw.Stop();
let s = sw.ElapsedMilliseconds;
System.Console.WriteLine(s);
let c1 = System.DateTime.Now
System.Console.WriteLine(c1);

sw.Reset();
sw.Start();
Async.Parallel [ for x in 0..40 -> async { return fib(x) } ]  |> Async.RunSynchronously
sw.Stop();
let p = sw.ElapsedMilliseconds;
System.Console.WriteLine(p);
let c2 = System.DateTime.Now
System.Console.WriteLine(c2);

sw.Reset();
sw.Start();
for x in 0..10 do
    fib(40);
    done
sw.Stop();
let s2 = sw.ElapsedMilliseconds;
System.Console.WriteLine(s2);
let c3 = System.DateTime.Now
System.Console.WriteLine(c3);

sw.Reset();
sw.Start();
Async.Parallel [ for x in 0..10 -> async { return fib(40) } ]  |> Async.RunSynchronously
sw.Stop();
let p2 = sw.ElapsedMilliseconds;
System.Console.WriteLine(p2);
let c4 = System.DateTime.Now
System.Console.WriteLine(c4);

let y = 1


Output:

3/27/2010 7:01:39 AM
5450
3/27/2010 7:01:44 AM
2351
3/27/2010 7:01:47 AM
22893
3/27/2010 7:02:10 AM
6663
3/27/2010 7:02:16 AM

Posted in Tip