【自定义CPU占用率】

题目:写一个程序,让用户来决定Windows任务管理器(Task Manager)的CPU占用率。程序越精简越好,计算机语言不限。例如,可以实现下面三种情况:

1. CPU的占用率固定在50%,为一条直线;

2. CPU的占用率为一条直线,但是具体占用率由命令行参数决定(参数范围1~ 100);

3. CPU的占用率状态是一个正弦曲线。

控制CPU占用率,不仅仅是出于好玩而已。以前的某些程序,特别是某些老游戏,在新的机器上运行速度太快,必须先给CPU降速,才能顺利运行那些程序,有个共享软件CPUKiller,就是专门弄这个的。

控制CPU占用率,因为要调用Windows的API,要考虑到多核、超线程的情况,要考虑到不同版本的Windows的计时相关的API的精度不同,使问题变得相当复杂,若再考虑其它程序的CPU占用率,则该问题则变得很烦人。(taskmgr调用了一个未公开的API)。

对CPU核数的判断,书上是调用GetProcessorInfo,其实可以直接调用GetSystemInfo,SYSTEM_INFO结构的dwNumberOfProcessors成员就是核数。不知道超线程对这两种方法有什么影响。

如果不考虑其它程序的CPU占用情况,可以在每个核上开一个线程,运行指定的函数,实现每个核的CPU占用率相同。

要让CPU的占用率,呈函数 y = calc(t) (0 <= y <= 1, t为时间,单位为ms )分布,只要取间隔很短的一系列点,认为在某个间隔内,y值近似不变。

设间隔值为GAP,显然在指定t值附近的GAP这段时间内,

CPU占用时间为:busy = GAP * calc(t),

CPU空闲时间为:idle = GAP – busy

因此,很容易写出下面这个通用函数:

void solve(Func *calc)
{
double tb = 0;
while(1) {
unsigned ta = get_time();
double r = calc(tb);
if (r < 0 || r > 1) r = 1;
DWORD busy = r * GAP;
while(get_time() - ta < busy) {}
Sleep(GAP - busy);
tb += GAP;
}

}


如果CPU占用率曲线不是周期性变化,就要对每个t值都要计算一次,否则,可以只计算第一个周期内的各个t值,其它周期的直接取缓存计算结果。

以CPU占用率为正弦曲线为例,显然:y = 0.5 * (1 + sin(a * t + b))

其周期T = 2 * PI / a (PI = 3.1415927),可以指定T值为60s即60000ms,则

可以确定a值为 2 * PI / T, 若在这60000ms内我们计算200次(c = 200),则GAP值为 T / c = 300ms.也就是说,只要确定了周期和计算次数,其它几个参数也都确定下来。

完整代码如下:

#include<windows.h>
#include<cstdio>
#include<cmath>

const int PERIOD = 60 * 1000; // 60,000 ms
const int COUNT = 200;

const double PI = 3.1415926535898;
const double GAP = ( double)PERIOD / COUNT;
const double FACTOR = 2 * PI / PERIOD;

typedef double Func( double);
inline DWORD get_time() { return GetTickCount(); }

double calc2( double x) { return (1 + sin(FACTOR * x)) / 2;}

double calc3( double)
{
static double cache[COUNT];
static int count = 0;
static bool first = true;
if (first) {
double x = 0.0;
for (int i = 0; i < COUNT; ++i, x += GAP)
cache[i] = (1.0 + sin(FACTOR * x)) / 2.0;
first = false;
}

if (count >= COUNT) count = 0;
return cache[count++];
}


double calc4( double) { return 0.8;}

void solve(Func *calc)
{
double tb = 0;
while(1) {
unsigned ta = get_time();
double r = calc(tb);
if (r < 0 || r > 1) r = 1;
DWORD busy = r * GAP;
while(get_time() - ta < busy) {}
Sleep(GAP - busy);
tb += GAP;
}

}



void run()
{
Func *func[] = { calc2, calc3, calc4 };
Func *calc = func[1];
const int MAX_CPUS = 32;
HANDLE handle[MAX_CPUS];
DWORD thread_id[MAX_CPUS];
SYSTEM_INFO info;
GetSystemInfo(&info);
const int num = info.dwNumberOfProcessors;
for (int i = 0; i < num; ++i) {
if ( (handle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,
(VOID*)calc, 0, &thread_id[i])) != NULL)
SetThreadAffinityMask(handle[i], i + 1);
}

WaitForSingleObject(handle[0],INFINITE);
}



int main()
{
run();
}



稍微优化下:

#include<cstdio>
#include<cmath>
#include<windows.h>

const int PERIOD = 60 * 1000; // 60,000 ms
const int COUNT = 300;

const double GAP_LINEAR = 100;

const double PI = 3.1415926535898;
const double GAP = ( double)PERIOD / COUNT;
const double FACTOR = 2 * PI / PERIOD;


typedef double Func( double);
inline DWORD get_time() { return GetTickCount(); }

double calc_sin( double x) { return (1 + sin(FACTOR * x)) / 2;}

static double Ratio = 0.7;

void set_ratio()
{
double ret = 0.0;
printf("Ratio:([0,1]) ");
scanf("%lf", &ret);
if (ret < 0.0 || ret > 1.0) ret = 0.5;
Ratio = ret;
}


void solve_nonperiod(Func *calc)
{
double tb = 0;
while(1) {
unsigned ta = get_time();
double r = calc(tb);
if (r < 0 || r > 1) r = 1;
DWORD busy = r * GAP;
while(get_time() - ta < busy) {}
Sleep(GAP - busy);
//tb += GAP;
tb += get_time() - ta;
}

}


void solve_period(Func *calc)
{
double x = 0.0;
double cache[COUNT];
for (int i = 0; i < COUNT; ++i, x += GAP)
cache[i] = calc(x);
int count = 0;
while(1) {
unsigned ta = get_time();
if (count >= COUNT) count = 0;
double r = cache[count++];
DWORD busy = r * GAP;
while(get_time() - ta < busy) {}
Sleep(GAP - busy);
}

}


void solve_linear(Func*)
{
const unsigned BUSY = Ratio * GAP_LINEAR;
const unsigned IDLE = (1 - Ratio) * GAP_LINEAR;
while(1) {
unsigned ta = get_time();
while(get_time() - ta < BUSY) {}
Sleep(IDLE);
}

}



void run(unsigned index = 0, double ratio = -1.0)
{
typedef void Solve(Func *calc);
Func *func[] = { calc_sin};
Func *calc = func[0];
Solve *solve_func[] = { solve_linear, solve_period, solve_nonperiod };
if (index >= sizeof(solve_func) / sizeof(solve_func[0])) index = 0;
Solve *solve = solve_func[index];
if (solve == solve_linear) {
if (ratio >= 0 && ratio <= 1) Ratio = ratio;
else set_ratio();
}

const int MAX_CPUS = 32;
HANDLE handle[MAX_CPUS];
DWORD thread_id[MAX_CPUS];
SYSTEM_INFO info;
GetSystemInfo(&info);
const int num = info.dwNumberOfProcessors;
for (int i = 0; i < num; ++i) {
if ((handle[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)solve,
(VOID*)calc, 0, &thread_id[i])) != NULL)
SetThreadAffinityMask(handle[i], i + 1);
}

WaitForSingleObject(handle[0],INFINITE);
}



int main()
{
run(0, 0.5);
//run(0);
//run(1);
//run(1);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用 Windows 自带的命令行工具“wmic”来实现自定义占用 CPU使用率的批处理。具体操作如下: 1. 打开命令行工具,输入“wmic cpu get loadpercentage”查看当前 CPU使用率。 2. 输入“wmic path Win32_PerfFormattedData_PerfOS_Processor where Name='_Total' get PercentProcessorTime”查看当前系统总体 CPU 使用率。 3. 输入“wmic path Win32_PerfFormattedData_PerfOS_Processor where Name='_Total' set PerformanceLimit=50”将 CPU使用率限制在 50%。 4. 输入“wmic path Win32_PerfFormattedData_PerfOS_Processor where Name='_Total' set PerformanceLimit=100”将 CPU使用率恢复到 100%。 注意:以上命令需要以管理员身份运行,否则可能会出现权限不足的错误。另外,使用这种方法限制 CPU 使用率可能会影响系统的性能,谨慎使用。 ### 回答2: 您好!如果您需要一个批处理脚本能够自定义占用CPU使用率,您可以尝试以下的方法: 1. 使用Windows的powercfg命令:您可以创建一个批处理脚本来调整电源计划中的CPU最大使用率。例如,您可以使用以下命令将CPU的最大使用设置为50%: ``` powercfg -setacvalueindex scheme_current sub_processor processor_throttle 50 ``` 然后您可以将这个命令添加到批处理脚本中,并根据需要进行自定义。 2. 使用第三方工具:有一些第三方工具可以帮助您精确控制CPU使用率。例如,您可以使用"Process Lasso"这样的工具来设置特定进程的CPU使用率。您可以创建一个批处理脚本,在其中使用命令行来调用这些工具,并根据需要进行自定义。 无论您选择使用哪种方法,记得在使用之前请充分了解和测试这些设置,以确保安全和稳定性。希望以上信息能对您有所帮助! ### 回答3: 您好,关于您所需的批处理程序可以自定义占用 CPU 使用率的问题,以下是一个简单的示例代码: ```batch @echo off set /p usage_rate=请输入希望的 CPU 使用率(1-100之间): :LOOP echo 正在占用 CPU 资源,请稍候... for /l %%i in (1, 1, %usage_rate%) do ( echo off ) goto LOOP ``` 以上批处理程序会要求用户输入希望的 CPU 使用率,然后利用一个循环来进行 CPU 使用率的占用。这里使用了 `for /l` 命令来模拟占用 CPU 资源,请确保输入的值在 1 到 100 之间。 注意:由于批处理语言限制,这种方式并不能真正精确地达到指定的 CPU 使用率,而只是在循环中占用了指定的比例的 CPU 资源。实际 CPU 使用率还会受到其他因素的影响。 希望以上回答能满足您的需求,如有任何问题,请随时与我联系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值