是否可以冻结Windows任务管理器中显示的CPU使用率?我希望将我的程序中的负载冻结为20%,50%,70%等特定值。如何在给定的负载下运行CPU(%CPU利用率)?
(这是分析多少功率的PC与关于CPU使用率占用。)
这可能吗?
是否可以冻结Windows任务管理器中显示的CPU使用率?我希望将我的程序中的负载冻结为20%,50%,70%等特定值。如何在给定的负载下运行CPU(%CPU利用率)?
(这是分析多少功率的PC与关于CPU使用率占用。)
这可能吗?
我第一次尝试幼稚将产卵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
,但设置这对任何事情都是正常的,这样对我来说就不会有一致的行为。
我不知道你是否可以这样做,但你可以通过Priority属性更改正在执行的线程的线程优先级。你可以通过以下方式设置:
Thread.CurrentThread.Priority = ThreadPriority.Lowest;
另外,我不认为你真的想要限制它。如果机器处于闲置状态,您希望它忙于处理任务,对吧? ThreadPriority可帮助将此信息传递给调度程序。
优先级不会改变整体CPU使用率,只是线程获得CPU时间的顺序。 – tomfanning 2011-04-07 07:49:35
你为什么要这么做? – 2011-04-07 06:52:22
我需要分析电脑消耗的CPU使用量。 – Raj 2011-04-07 07:00:54
我不认为这会像这样工作。 – 2011-04-07 07:02:52