2011-04-07 56 views
4

是否可以凍結Windows任務管理器中顯示的CPU使用率?我希望將我的程序中的負載凍結爲20%,50%,70%等特定值。如何在給定的負載下運行CPU(%CPU利用率)?

(這是分析多少功率的PC與關於CPU使用率佔用。)

這可能嗎?

+1

你爲什麼要這麼做? – 2011-04-07 06:52:22

+0

我需要分析電腦消耗的CPU使用量。 – Raj 2011-04-07 07:00:54

+1

我不認爲這會像這樣工作。 – 2011-04-07 07:02:52

回答

7

我第一次嘗試幼稚將產卵2個線程的內核 - 在最高優先級的每個線程,然後,每個線程內,運行一個繁忙的環路,並做了一些工作。 (更多的線程比核心是「偷」我可以從其他線程在Windows中的所有時間:-)

使用某種API讀取CPU負載(也許WMI或性能計數器?),然後我會使每個線程從忙碌循環(每個循環的一定時間的休眠)產生,直到我得到反饋週期中的近似負載。

這個循環會自我調整:負載過高,睡眠更多。負載過低,睡眠不足。這不是一門精確的科學,但我認爲可以通過一些調整來獲得穩定的負載。

但是,我不知道,真的:-)

快樂編碼。


另外,考慮電源管理 - 有時它可以鎖定一個CPU在「最大%」。然後完全加載CPU,它將超出該限制。 (至少Windows 7具有內置功能來執行此操作,具體取決於CPU和芯片組 - 可能有許多第三方工具。)

情況變得相當混亂,而新的CPU會動態計時基於負載和溫度等。


這是我對「最初的」.NET 3.5方法的嘗試。確保包含System.Management參考。

任務管理器報告的CPU利用率徘徊在目標的幾個百分比內 - 平均值似乎非常接近 - 在我的系統上。 YMMV,但調整有一定的靈活性。

快樂編碼(再次)。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Management; 
using System.Threading; 
using System.Diagnostics; 

namespace CPULoad 
{ 
    class Program 
    { 
     // What to try to get :-) 
     static int TargetCpuUtilization = 50; 
     // An average window too large results in bad harmonics -- keep it small. 
     static int AverageWindow = 5; 
     // A somewhat large number gets better results here. 
     static int ThreadsPerCore = 8; 
     // WMI is *very slow* compared to a PerformanceCounter. 
     // It still works, but each cycle is *much* longer and it doesn't 
     // exhibit as good of characteristics in maintaining a stable load. 
     // (It also seems to run a few % higher). 
     static bool UseWMI = false; 
     // Not sure if this helps -- but just play about :-) 
     static bool UseQuestionableAverage = true; 

     static int CoreCount() { 
      var sys = new ManagementObject("Win32_ComputerSystem.Name=\"" + Environment.MachineName + "\""); 
      return int.Parse("" + sys["NumberOfLogicalProcessors"]); 
     } 

     static Func<int> GetWmiSampler() { 
      var searcher = new ManagementObjectSearcher(
       @"root\CIMV2", 
       "SELECT PercentProcessorTime FROM Win32_PerfFormattedData_PerfOS_Processor"); 
      return() => { 
       var allCores = searcher.Get().OfType<ManagementObject>().First(); 
       return int.Parse("" + allCores["PercentProcessorTime"]); 
      }; 
     } 

     static Func<int> GetCounterSampler() { 
      var cpuCounter = new PerformanceCounter { 
       CategoryName = "Processor", 
       CounterName = "% Processor Time", 
       InstanceName = "_Total", 
      }; 
      return() => { 
       return (int)cpuCounter.NextValue(); 
      }; 
     } 

     static Func<LinkedList<int>, int> StandardAverage() { 
      return (samples) => { 
       return (int)samples.Average(); 
      };  
     } 

     // Bias towards newest samples 
     static Func<LinkedList<int>, int> QuestionableAverage() { 
      return (samples) => { 
       var weight = 4.0; 
       var sum = 0.0; 
       var max = 0.0; 
       foreach (var sample in samples) { 
        sum += sample * weight; 
        max += weight; 
        weight = Math.Min(4, Math.Max(1, weight * 0.8)); 
       } 
       return (int)(sum/max); 
      }; 
     } 

     static void Main (string[] args) { 
      var threadCount = CoreCount() * ThreadsPerCore; 
      var threads = new List<Thread>(); 
      for (var i = 0; i < threadCount; i++) { 
       Console.WriteLine("Starting thread #" + i);     
       var thread = new Thread(() => { 
        Loader(
         UseWMI ? GetWmiSampler() : GetCounterSampler(), 
         UseQuestionableAverage ? QuestionableAverage() : StandardAverage()); 
       }); 
       thread.IsBackground = true; 
       thread.Priority = ThreadPriority.Highest; 
       thread.Start(); 
       threads.Add(thread); 
      } 
      Console.ReadKey(); 
      Console.WriteLine("Fin!"); 
     } 

     static void Loader (Func<int> nextSample, Func<LinkedList<int>, int> average) { 
      Random r = new Random(); 
      long cycleCount = 0; 
      int cycleLength = 10; 
      int sleepDuration = 15; 
      int temp = 0; 
      var samples = new LinkedList<int>(new[] { 50 }); 
      long totalSample = 0; 

      while (true) { 
       cycleCount++; 
       var busyLoops = cycleLength * 1000; 
       for (int i = 0; i < busyLoops; i++) { 
        // Do some work 
        temp = (int)(temp * Math.PI); 
       } 
       // Take a break 
       Thread.Sleep(sleepDuration); 

       { 
        // Add new sample 
        // This seems to work best when *after* the sleep/yield 
        var sample = nextSample(); 
        if (samples.Count >= AverageWindow) { 
         samples.RemoveLast(); 
        } 
        samples.AddFirst(sample); 
        totalSample += sample; 
       } 
       var avg = average(samples); 
       // should converge to 0 
       var conv = Math.Abs(TargetCpuUtilization - (int)(totalSample/cycleCount)); 

       Console.WriteLine(string.Format("avg:{0:d2} conv:{1:d2} sleep:{2:d2} cycle-length:{3}", 
        avg, conv, sleepDuration, cycleLength)); 
       // Manipulating both the sleep duration and work duration seems 
       // to have the best effect. We don't change both at the same 
       // time as that skews one with the other. 
       // Favor the cycle-length adjustment. 
       if (r.NextDouble() < 0.05) { 
        sleepDuration += (avg < TargetCpuUtilization) ? -1 : 1; 
        // Don't let sleep duration get unbounded upwards or it 
        // can cause badly-oscillating behavior. 
        sleepDuration = (int)Math.Min(24, Math.Max(0, sleepDuration)); 
       } else { 
        cycleLength += (avg < TargetCpuUtilization) ? 1 : -1; 
        cycleLength = (int)Math.Max(5, cycleLength); 
       } 
      } 
     } 
    } 
} 

雖然Windows是一個搶先式操作系統,代碼運行在Kernel Mode - 如驅動程序 - 由遠不如搶佔。雖然在C#AFAIK中不可行,但這應該產生一種比上述更嚴格的負載控制方法,但也有更好的複雜性(並且能夠崩潰整個系統:-)

Process.PriorityClass,但設置這對任何事情都是正常的,這樣對我來說就不會有一致的行爲。

0

我不知道你是否可以這樣做,但你可以通過Priority屬性更改正在執行的線程的線程優先級。你可以通過以下方式設置:

Thread.CurrentThread.Priority = ThreadPriority.Lowest; 

另外,我不認爲你真的想要限制它。如果機器處於閒置狀態,您希望它忙於處理任務,對吧? ThreadPriority可幫助將此信息傳遞給調度程序。

參考:How to restrict the CPU usage a C# program takes?

+0

優先級不會改變整體CPU使用率,只是線程獲得CPU時間的順序。 – tomfanning 2011-04-07 07:49:35