How do I spawn threads on different CPU cores? How do I spawn threads on different CPU cores? multithreading multithreading

How do I spawn threads on different CPU cores?


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.


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.


Although I agree with most of the answers here, I think it's worth it to add a new consideration: Speedstep technology.

When running a CPU intensive, single threaded job on a multi-core system, in my case a Xeon E5-2430 with 6 real cores (12 with HT) under windows server 2012, the job got spread out among all the 12 cores, using around 8.33% of each core and never triggering a speed increase. The CPU remained at 1.2 GHz.

When I set the thread affinity to a specific core, it used ~100% of that core, causing the CPU to max out at 2.5 GHz, more than doubling the performance.

This is the program I used, which just loops increasing a variable. When called with -a, it will set the affinity to core 1. The affinity part was based on this post.

using System;using System.Diagnostics;using System.Linq;using System.Runtime.InteropServices;using System.Threading;namespace Esquenta{    class Program    {        private static int numThreads = 1;        static bool affinity = false;        static void Main(string[] args)        {            if (args.Contains("-a"))            {                affinity = true;            }            if (args.Length < 1 || !int.TryParse(args[0], out numThreads))            {                numThreads = 1;            }            Console.WriteLine("numThreads:" + numThreads);            for (int j = 0; j < numThreads; j++)            {                var param = new ParameterizedThreadStart(EsquentaP);                var thread = new Thread(param);                thread.Start(j);            }        }        static void EsquentaP(object numero_obj)        {            int i = 0;            DateTime ultimo = DateTime.Now;            if(affinity)            {                Thread.BeginThreadAffinity();                CurrentThread.ProcessorAffinity = new IntPtr(1);            }            try            {                while (true)                {                    i++;                    if (i == int.MaxValue)                    {                        i = 0;                        var lps = int.MaxValue / (DateTime.Now - ultimo).TotalSeconds / 1000000;                        Console.WriteLine("Thread " + numero_obj + " " + lps.ToString("0.000") + " M loops/s");                        ultimo = DateTime.Now;                    }                }            }            finally            {                Thread.EndThreadAffinity();            }        }        [DllImport("kernel32.dll")]        public static extern int GetCurrentThreadId();        [DllImport("kernel32.dll")]        public static extern int GetCurrentProcessorNumber();        private static ProcessThread CurrentThread        {            get            {                int id = GetCurrentThreadId();                return Process.GetCurrentProcess().Threads.Cast<ProcessThread>().Single(x => x.Id == id);            }        }    }}

And the results:

results

Processor speed, as shown by Task manager, similar to what CPU-Z reports:

enter image description here