How to start the CPU at a given load (% of CPU usage)?

Can I freeze the CPU usage shown in the Windows task manager? I want to freeze the load in the form of certain values, such as 20%, 50%, 70%, etc. From my program.

(This is necessary to analyze how much power the PC consumes regarding CPU usage.)

Is it possible?

+4
source share
2 answers

My first naive attempt was to spawn 2 threads as a kernel - each thread with the highest priority, and then start a busy cycle in each thread and do some work. (More threads than cores, "steal" all the time that I can get from other threads in windows :-)

Using some kind of API to read the CPU load (maybe WMI or performance counters?), And then I will make each β€œyield” thread out of the busy cycle (sleep for a certain period of time for each cycle) until I get an approximate load in the cycle feedback.

This cycle will self-adjust: too high a load, more sleep. Too low load, less sleep. This is not an exact science, but I think that with some tuning you can get a stable load.

But I have no idea, really :-)

Happy coding.


Also, consider power management - sometimes it can block the CPU with a maximum value of%. Then fully load the CPU, and it will be maximum at this limit. (Windows 7, at least, has a built-in feature for this, depending on the processor and chip set - probably many third-party tools.)

The situation is becoming rather confused with new processors that dynamically synchronize depending on load and temperature, etc.


Here is my attempt at a β€œnaive” approach to .NET 3.5. Be sure to include the System.Management link.

Using the processor reported by the task manager is within a few percent of the target β€” the average value seems pretty black on my system. YMMV, but there is some flexibility in customization.

Happy coding (again).

 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); } } } } } 

While Windows is a preventative operating system, code that runs in kernel mode β€” for example, drivers β€” is crowded out much less. Although this is not feasible in C # AFAIK, this should give a method of more stringent load adjustment than higher, but it also has a big cue ball of complexity (and the ability to break the whole system :-)

There is a Process.PriorityClass , but setting this to anything other than the usual one gave me consistent behavior.

+7
source

I do not know if you can do this, but you can change the priority of the thread of the executable thread through the Priority property. You must install this:

 Thread.CurrentThread.Priority = ThreadPriority.Lowest; 

Also, I don't think you really want to close it. If the car is otherwise idle, you want it to take up the task, right? ThreadPriority helps inform the scheduler about this.

Link: How to limit CPU usage to a C # program?

0
source

Source: https://habr.com/ru/post/1347048/


All Articles