gpt4 book ai didi

c# - 如何在给定负载下运行 CPU(CPU 利用率百分比)?

转载 作者:太空狗 更新时间:2023-10-30 00:45:23 25 4
gpt4 key购买 nike

是否可以卡住 Windows 任务管理器中显示的 CPU 使用率?我希望将负载卡住为程序中的特定值,如 20%、50%、70% 等。

(这是为了分析 PC 在 CPU 使用率方面消耗了多少电量。)

这可能吗?

最佳答案

我的第一个天真的尝试是生成 2 个线程作为核心——每个线程都具有最高优先级,然后在每个线程内运行一个忙循环并做一些工作。 (多于核心的线程就是“窃取”我可以从 Windows 中的其他线程获得的所有时间:-)

使用某种 API 来读取 CPU 负载(也许是 WMI 或性能计数器?)然后我会让每个线程从繁忙的循环中“屈服”(每个循环休眠一定时间)直到我得到反馈周期中的近似负载。

这个循环会 self 调整:负载太高,睡得更多。负荷太低,睡得少。这不是一门精确的科学,但我认为通过一些调整可以获得稳定的负载。

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

快乐编码。


此外,请考虑电源管理——有时它可以将 CPU 锁定在“最大百分比”。然后完全加载 CPU,它将达到该极限。 (至少,Windows 7 具有执行此操作的内置功能,具体取决于 CPU 和芯片组——可能有许多第 3 方工具。)

对于基于负载和温度等动态计时的新型 CPU,情况变得相当困惑。


这是我对 .NET 3.5 的“天真”方法的尝试。确保包括 System.Management 引用。

在我的系统上,任务管理器报告的 CPU 利用率徘徊在目标的百分之几内——平均值似乎非常接近。 YMMV,但有一些调整的灵 active 。

快乐编码(再次)。

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 ,但将其设置为正常以外的任何值都会对我产生最不一致的行为。

关于c# - 如何在给定负载下运行 CPU(CPU 利用率百分比)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5577098/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com