如何运行的CPU在给定的负载(%的CPU利用率)?利用率、负载、CPU

2023-09-04 11:54:27 作者:孑然

是否可以冻结显示在Windows任务管理器的CPU使用率?我想从我的程序冻结负荷为特定值像20%,50%,70%等。

Is it possible to freeze CPU usage that is shown in in Windows Task Manager? I wish to freeze the load as specific values like 20%, 50%, 70% etc. from my program.

(这是分析多大的权力将PC与消费有关的CPU使用。)

(This is to analyse how much power the PC is consuming with regard to CPU usage.)

这可能吗?

推荐答案

我的第一天真的尝试将产卵2个线程的内核 - 每个线程的优先级最高,然后,每个线程内运行一个繁忙的循环和做了一些工作。 (更多线程不是内核是偷所有的时间,我可以从其他线程获得在Windows中: - )

My first naive attempt would be to spawn 2x threads as cores -- each thread in the highest priority and then, within each thread, run a busy-loop and do some work. (More threads than cores is to "steal" all the time I can get from other threads in windows :-)

使用某种形式的API来读取CPU的负载(也许是WMI或性能计数器?)我会那么做,从繁忙的环路(睡了一定的时间每​​个环路)的每个线程'产量',直到我得到的近似​​的负载反馈循环。

Using some kind of API to read the CPU load (perhaps WMI or performance counters?) and I would then make each thread 'yield' from the busy loop (sleep for a certain amount of time each loop) until I get the approximate load in the feedback cycle.

这个周期会自我调整:负载过高,多睡觉。过低的负载,睡眠时间少。这不是一门精确的科学,但我认为有一些调整一个稳定的负载可以得到。

This cycle would be self-adjusting: too high load, sleep more. Too low load, sleep less. It's not an exact science, but I think that with some tweaking a stable load can be obtained.

不过,我也没办法,真正做到: - )

But, I have no idea, really :-)

快乐编码。

另外,还要考虑电源管理 - 有时也可以在最大%锁定CPU。然后完全加载的CPU,它会最大输出在该限制。 (Windows 7中,至少有一个内置的功能,要做到这一点,取决于CPU和芯片组 - 有可能许多第三方工具)

Also, consider power management -- sometimes it can lock a CPU at a "max %". Then fully load the CPU and it will max out at that limit. (Windows 7, at least, has a built-in feature to do this, depending upon CPU and chip-set -- there are likely many 3rd party tools.)

情况变得相当混乱与新CPU的主频动态根据负载和温度等。

The situation becomes rather confusing with newer CPUs that dynamically clocked based on load and temperature, etc.

下面是我尝试了天真的方式为.NET 3.5。确保包括 System.Management 引用。

Here is my attempt at the "naive" approach for .NET 3.5. Make sure to include the System.Management reference.

报告的任务管理器的CPU利用率徘徊在目标的百分之几 - 平均似乎pretty的织补接近 - 在我的系统。因人而异,但有一定的灵活性调整

The CPU utilization as reported by the Task Manager hovers within a few percent of the target -- average seems pretty darn close -- on my system. YMMV, but there is some flexibility for adjustment.

快乐编码(再次)。

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是preemptive操作系统,code的运行在的内核模式 - 如司机 - 是远不如pempted $ P $。而在C#AFAIK不可行的,这应该得到比上述更严格的负载控制的方法,但也有一个好一点的更复杂(和崩溃对整个系统的能力: - )

While Windows is a preemptive operating system, code which runs in Kernel Mode -- such as drivers -- is preempted by far less. While not doable in C# AFAIK, this should yield a method of stricter load control than the above, but also has a good bit more complexity (and the ability to crash the entire system :-)

进程。的priorityClass ,但是这个设置并不正常,以免产生一致的行为给我。

There is Process.PriorityClass, but setting this to anything but normal yielded lest consistent behavior for me.