The World’s Leading Microsoft .NET Magazine
   
 
The .NET Addict's Blog

My Top Tags

                                                           

My RSS Feeds








I heart FeedBurner

Latest Diggs - Programming

Computers Blogs - Blog Top Sites

Site Hits

Total: 4,908,483
since: 19 Jan 2005

Threading on Multiple Cores in the .NET Framework

posted Tue 26 Jun 07

Recently I've been doing a little bit of thinking about concurrency and multi-threading. Multi-threading is a fantastic tool, but it's also a really big gun with which to shoot your foot. In other words: It's a powerful tool and if it gets into the wrong (read: unprepared) hands, it can do a lot of damage. I've seen everything from multi-threading that immediately blocked, which caused the same problem it was originally intended to solve (GUI blocking while waiting for a task) to spinning off so many threads that the app spends all it's time context switching and virtually none of it's time doing work.

What I was curious about was: If I create a new System.Thread and start it, am I going to be running that thread on other cores or other processors? In short, I wanted to know if my multi-threaded apps can automatically take advantage of multi-core and multi-processor architecture without me having to do anything extra-special (or extra-painful, for that matter). Here's the code I wrote as a threading sample. It basically computes the outer edges of circles, and does it a truckload of times:

static void Main(string[] args)
{
    Console.WriteLine("About to compute a lot of circles on threads.");
    for (int threadCount = 0; threadCount < 2; threadCount++)
    {
        Thread t = new Thread(new ThreadStart(DoWork));
        t.Start();
    }
    Console.ReadLine();
}
static void DoWork()
{
    Console.WriteLine("[Thread " + Thread.CurrentThread.ManagedThreadId.ToString() + "] Start Work.");
    for (int count = 0; count < 100000; count++)
    {
        for (int angle = 0; angle < 360; angle++)
        {
            double x = Math.Cos(angle);
            double y = Math.Sin(angle);
        }
    }
    Console.WriteLine("[Thread " + Thread.CurrentThread.ManagedThreadId.ToString() + "] End Work.");
}

In the code sample, I'm using 2 threads, but you can tweak it for more threads. The revealing change is when you go from 2 threads to 1 thread. On my twin-processor Xeon machine, running the above code consumed 56% of my overall CPU. In the following task manager screenshot, you'll see that my second processor did all the work while my first processor did very little. When I upped the thread count from 1 to 2 (or more), both processors engaged and the app consumes nearly all of my CPU (as would be expected).

So, to me, what this clearly shows me is that by default, if you're writing multi-threaded code in your .NET applications, you will be able to take advantage of multi-core and multi-processor architecture without having to do anything in particular. Of course, saying that is the easy part - the hard part is partitioning your application into units of work that can be done in parallel in order to really take advantage of all this new hardware coming out.

In case you're curious, here's a screenshot of the task manager looking at the CPU levels. The first spike is where I ran it on 2 threads. The second plateau is where I ran it on 4 threads with 500,000 circle computations per thread.

tags:        

links: digg this    del.icio.us    technorati    reddit

AddThis Social Bookmark Button




1. Jon left...
Tue 26 Jun 07 1:14 pm :: http://crazytrain.wordpress.com

Wow, really cool post! Id love to hear more about this subject! Do you have a screenshot of what happened with the multiple threads?


2. Kevin Hoffman left...

Jon, the second screenshot can also be found on Flickr here: http://farm2.static.flickr.com/1188/632347133_77be94c306_o.png

Basically what you're looking at in that screenshot is 4 threads and 500,000 circles per thread. You can see that the CPU takes a breather every so often, but both cores are pushing hard on the tasks.


3. Kevin Hoffman left...

Jon, I also modified the original blog post to include the second screenshot.


4. James Gregurich left...
Tue 26 Jun 07 1:49 pm

great. this should make it feasible to mimic NSOperation/NSOperationQueue in managed code.


5. Chris Hanson left...
Tue 26 Jun 07 2:23 pm :: http://chanson.livejournal.com/

Is it actually surprising on Windows for multiple threads to be run on independent cores? I'd think that any modern operating system actually schedules in terms of threads rather than tasks, using any available CPU resources modulo some dynamic affinity calculation. That's certainly what Mach (and therefore Mac OS X) does.


6. Kevin Hoffman left...

Actually, it was surprising to me because in a managed application, the CLR host is the parent process. When your application fires up, you get an AppDomain and everything done within the application is done within that AppDomain (unless you're specifically requesting additional AppDomains).

I was actually pretty shocked, I fully expected that each AppDomain would get core affinity and that managed threads within that AppDomain would be isolated to a single core. I'm quite pleased that the result was otherwise.


7. Victor Moran left...
Wed 20 Feb 08 3:38 pm

Actually at the OS level, processes still rule. The creation of a thread resource calls out to WinAPI at the process level. AppDomains are an abstraction and aren't recognized by Windows (hence don't get context switched or assigned affinity) - only the process in which the AppDomain lives does, hence threads are not limited to the AppDomains in which they originated (but are confined to the process in which the AppDomain resides).


Tag Related Posts

Smart, Deep Property Notifications in CLINQ v2.0

Tue 07 Oct 08 1:15 P GMT-05
tags:          

Microsoft's Lofty Direction

Sun 05 Oct 08 2:30 P GMT-05

MobileMe vs. Live Mesh Throwdown - Round 1

Wed 16 Jul 08 10:33 A GMT-05

One Framework to Rule them All

Mon 25 Feb 08 6:49 P GMT-05

My Little Pony .NET Unleashed 2007

Fri 30 Mar 07 1:59 P GMT-05

Authorness

Thu 15 Mar 07 1:44 P GMT-05

Localizing a WPF Application

Tue 22 Aug 06 11:39 A GMT-05
tags:            

Is Windows Workflow Foundation Too Complex?

Fri 18 Aug 06 12:15 P GMT-05

Lambda Lambda Lambda

Sun 21 May 06 1:01 A GMT-05

The Adventures of LINQ (Not Zelda)

Fri 19 May 06 11:21 P GMT-05
tags: