views:

3787

answers:

8

Let's say I had a program in C# that did something computationally expensive, like encoding a list of WAV files into MP3's. Ordinarily I would encode the files one at a time, but let's say I wanted the program to figure out how many CPU cores I had and spin up an encoding thread on each core. So, when I run the program on a quad core CPU, the program figures out it's a quad core CPU, figures out there's four cores to work with, then spawns four threads for the encoding, each of which is running on its own separate CPU. How would I do this?

And would this be any different if the cores were spread out across multiple physical CPU's? As in, if I had a machine with two quad core CPU's on it, are there any special considerations or are the eight cores across the two dies considered equal in Windows?

A: 

Where each thread goes is generally handled by the OS itself...so generate 4 threads on a 4 core system and the OS will decide which cores to run each on, which will usually be 1 thread on each core.

Adam Haile
+19  A: 

Don't bother doing that.

Instead use the Thread Pool. The thread pool is a mechanism (actually a class) of the framework that you can query for a new thread.

When you ask for a new thread it will either give you a new one or enqueue the work until a thread get freed. In that way the framework is in charge on deciding wether it should create more threads or not depending on the number of present CPUs.

Edit: In addition, as it has been already mentioned, the OS is in charge of distributing the threads among the different CPUs.

Jorge Córdoba
What if you haven't got .NET?
Crashworks
This is a .NET related question. Why would you not have .NET?
Dave Van den Eynde
A: 

It is the operating system's job to split threads across different cores, and it will do so when automatically when your threads are using a lot of CPU time. Don't worry about that. As for finding out how many cores your user has, try Environment.ProcessorCount in C#.

wvdschel
+2  A: 

You shouldn't have to worry about doing this yourself. I have multithreaded .NET apps running on dual-quad machines, and no matter how the threads are started, whether via the ThreadPool or manually, I see a nice even distribution of work across all cores.

Eric Z Beard
+1  A: 

One of the reasons you should not (as has been said) try to allocated this sort of stuff yourself, is that you just don't have enough information to do it properly, particularly into the future with NUMA, etc.

If you have a thread read-to-run, and there's a core idle, the kernel will run your thread, don't worry.

Will Dean
+1  A: 

In the case of managed threads, the complexity of doing this is a degree greater than that of native threads. This is because CLR threads are not directly tied to a native OS thread. In other words, the CLR can switch a managed thread from native thread to native thread as it sees fit. The function Thread.BeginThreadAffinity is provided to place a managed thread in lock-step with a native OS thread. At that point, you could experiment with using native API's to give the underlying native thread processor affinity. As everyone suggests here, this isn't a very good idea. In fact there is documentation suggesting that threads can receive less processing time if they are restricted to a single processor or core.

You can also explore the System.Diagnostics.Process class. There you can find a function to enumerate a process' threads as a collection of ProcessThread objects. This class has methods to set ProcessorAffinity or even set a preferred processor -- not sure what that is.

Disclaimer: I've experienced a similar problem where I thought the CPU(s) were under utilized and researched a lot of this stuff; however, based on all that I read, it appeared that is wasn't a very good idea, as evidenced by the comments posted here as well. However, it's still interesting and a learning experience to experiment.

Peter Meyer
+3  A: 

It is not necessarily as simple as using the thread pool.

By default, the thread pool allocates multiple threads for each CPU. Since every thread which gets involved in the work you are doing has a cost (task switching overhead, use of the CPU's very limited L1, L2 and maybe L3 cache, etc...), the optimal number of threads to use is <= the number of available CPU's - unless each thread is requesting services from other machines - such as a highly scalable web service. In some cases, particularly those which involve more hard disk reading and writing than CPU activity, you can actually be better off with 1 thread than multiple threads.

For most applications, and certainly for WAV and MP3 encoding, you should limit the number of worker threads to the number of available CPU's. Here is some C# code to find the number of CPU's:

int processors = 1;
string processorsStr = System.Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS");
if (processorsStr != null)
    processors = int.Parse(processorsStr);

Unfortunately, it is not as simple as limiting yourself to the number of CPU's. You also have to take into account the performance of the hard disk controller(s) and disk(s).

The only way you can really find the optimal number of threads is trial an error. This is particularly true when you are using hard disks, web services and such. With hard disks, you might be better off not using all four processers on you quad processor CPU. On the other hand, with some web services, you might be better off making 10 or even 100 requests per CPU.

Joe Erickson
A: 

i7 840QM IS 8 Threads on 4 Cores according to INTEL/other sources, so how goes that work? It is not that 1 CORE=1 THREAD, or is only capable of one action? In the ATI-GPU many threads are computed via a single core on graphics cards, aren't they? Multi-Threading?

lucky7