How do I spawn threads on different CPU cores?

后端 未结 10 2069
梦谈多话
梦谈多话 2020-11-28 20:43

Let\'s say I had a program in C# that did something computationally expensive, like encoding a list of WAV files into MP3s. Ordinarily I would encode the files one at a time

10条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-28 21:12

    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().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

提交回复
热议问题