多處理器的線程依賴

來源:互聯網
上載者:User
 

多處理器的線程依賴

摘要

本文結合一個有趣的例子示範了如何設定CPU的線程依賴,並解釋了物理線程和邏輯線程的區別和聯絡。

Keywords

CPU, Thread, ProcessThread, C#

首先要搞清楚的是,Managed 程式碼中的線程(Thread)並不是真的線程(OS Thread)。它只是邏輯上我們劃定的線程。邏輯上的線程並不執行,實際執行的是物理線程或者叫OS線程。而通常來說,每一個邏輯線程都對應的關聯於某一條物理線程,這種關係一直維繫到該邏輯線程的生命週期結束。要設定線程的處理器依賴我們先要得到當前實際啟動並執行物理OS Thread或者叫物理線程,這時候需要使用Windows API – GetCurrentThreadId 。

    class KernalHelper
    {
        [DllImport("kernel32")]
       public static extern int GetCurrentThreadId(); 
    }

 

然後再通過當前的osThreadID找到對應的ProcessThread,並設定其ProcessorAffinity。

以下代碼示範了如何在一台雙核PC的資源管理員裡划出正弦曲線:

 private fields#region private fields
        private static int rounds = 0;
        private static int MAXROUND = 60;
        private static long[] sins = new long[MAXROUND];
        private static PerformanceCounter pc;
        private static bool tag = false;
        #endregion

        static void Main(string[] args)
        {
            Thread WatchThread = new Thread(() => GenerateSin(1));
            WatchThread.Start();
            Console.WriteLine("Press any key to break");
            Console.ReadKey();
            WatchThread.Abort();
        }


        public static void GenerateSin(int num)
        {
            //對當前物理線程設定處理器依賴
            int osThreadId = KernalHelper.GetCurrentThreadId();
            foreach (ProcessThread pt in Process.GetCurrentProcess().Threads)
            {
                if (osThreadId == pt.Id)
                {
                  pt.ProcessorAffinity = (IntPtr)num;
                }
            } 

            try
            {
                tag = true;
                //獲得處理器的使用率
                pc = new PerformanceCounter("Processor", "% Processor Time", "_Total");

                for (int a = 0; a < MAXROUND; a++)
                {
                    //六十個點的,振幅為5000000周期為60的正弦序列
                    sins[a] = (long)(5000000 * Math.Sin(Math.PI * a / (double)MAXROUND * 2f)) + 5000000;
                }


                long t1, t2;
                long TimeSlide;

                while (tag)
                {
                    t1 = pc.RawValue + sins[rounds % MAXROUND];
                    TimeSlide = Stopwatch.GetTimestamp() + Stopwatch.Frequency;
                    t2 = TimeSlide - Stopwatch.Frequency + sins[rounds % MAXROUND] * Stopwatch.Frequency / 10000000;
                    while (pc.RawValue < t1)
                    {
                        Thread.Sleep(10);
                    }
                    while (Stopwatch.GetTimestamp() < TimeSlide) ;
                    rounds++;
                }
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
            }
            finally
            {
                pc.Close();
            }
        }

 

效果:



 

關於更多控制CPU使用率的有趣思考請看<編程之美 - 微軟技術面試心得>

邏輯線程對CPU而言並不直接具有任務的性質,它只是一個CLR層面的資料結構,並不是OS層面實際的使用中的物件,邏輯線程與OS物理線程的依賴關係由CLR維護。這確實有一點點抽象,不過在託管的應用程式層面你基本上不需要關心你定義的線程和底層的線程是如何映射的。因為OS的線程調度能力比人工額外編碼控制要好得多,除非你確實是有非常特殊的任務需要做,或者需要硬體層面的記憶體映射,否則就不要更改進程和處理器的依賴關係以及託管線程和OS線程的依賴關係。我不知道為什麼.NET Framework中還提供了相應的方法和屬性協助程式員實現這樣的既不“優雅”也不“安全”的功能,這顯得和.NET一貫的作風有些不搭調。

預設情況下CLR並不保證每一個線程都始終運行在同一個處理器上,很可能在下一個時間片上線程會交由另一個處理器處理。為了避免這種情況,只能顯式的指定處理器依賴情況。不過一般來說,OS都會試圖保證所有UI線程都運行在發起它們的處理器上。所以還是覺得實際上除了這種趣味性的程式和某些極端測試,沒有必要對此進行人工幹涉。

Enjoy it~

黃季冬<fox23>

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.