在C++中模拟CPU负载

use*_*631 4 c++ cpu cpu-usage

我目前正在使用C++在Windows中编写应用程序,我想模拟CPU负载.

我有以下代码:

void task1(void *param) { 

unsigned elapsed =0;
unsigned t0;

while(1){

    if ((t0=clock())>=50+elapsed){//if time elapsed is 50ms

        elapsed=t0;
        Sleep(50);
    }
  }
}

int main(){

int ThreadNr;

for(int i=0; i < 4;i++){//for each core (i.e. 4 cores)
    _beginthread( task1, 0, &ThreadNr );//create a new thread and run the "task1" function
}

while(1){}
}
Run Code Online (Sandbox Code Playgroud)

我使用与此线程中给出的答案相同的方法编写此代码:模拟稳定的CPU负载和峰值

我的问题是:

  1. 我是否已将C#代码从其他帖子正确翻译到C++?
  2. 这个代码会在四核处理器上产生50%的平均CPU负载吗?
  3. 如何在合理的精度下找出CPU的负载百分比?(任务经理是我唯一的选择吗?)

编辑:我问这个问题的原因是我希望最终能够在合理的容差范围内生成10,20,30,...,90%的CPU负载.此代码似乎适用于生成负载70%<但在低于70%的任何负载(通过任务管理器CPU负载读数测量)时似乎非常不准确.

任何人都有任何关于我如何生成所述负载的想法,但仍然能够在不同的计算机上使用我的程序(即使用不同的CPU)?

Dam*_*mon 6

乍一看,这看起来不是非常漂亮但正确的C++或C(一种简单的方法可以确保编译它).包含缺失(<windows.h>,<process.h><time.h>),但否则编译正常.

请注意,clock并且Sleep不是非常准确,Sleep也不是非常可靠.平均而言,线程函数应该按预期工作(给出或采取百分之几的变化).

但是,关于问题2)你应该用while(1){}阻塞而不是旋转的东西替换最后一个(例如,WaitForSingleObject或者Sleep如果你愿意).否则整个程序将不会在四核上加载50%.由于主线程,您将在一个核心上100%加载,加上四个工作者的4倍50%.这显然会达到每个核心超过50%(并且会导致线程从一个核心反弹到另一个核心,导致令人讨厌的副作用).

使用任务管理器或类似的实用程序来验证您是否获得所需的负载是一个不错的选择(因为它是最简单的解决方案,它也是最好的解决方案).

另外请注意,以这种方式模拟负载可能会起作用,但不是100%可靠.
可能存在难以预测的效果(内存,执行单元).例如,假设您使用此循环(合理假设)使用100%的CPU整数执行单元,但它的浮点或SSE单位为零.现代CPU可能在实际或逻辑核心之间共享资源,您可能无法准确预测您获得的效果.或者,另一个线程可能是内存绑定或具有重大页面错误,因此占用CPU时间几乎不会像您想象的那样影响它(实际上可能给它足够的时间来使预取工作更好).或者,它可能会阻止AGP转移.或者,你无法分辨的其他事情.

编辑:

改进版本,更短的代码,修复了一些问题,也可以按预期工作:

  • 用途clock_t为返回的值clock(这在技术上是"更正确"比使用不是特别typedef"d整数.Incidentially,这可能是由于这个原因,为什么原来的代码不会像预期的那样,因为clock_t在Win32下的整数.条件if()总是在评估true,所以工人几乎一直在睡觉,不消耗CPU.
  • 旋转时代码更少,数学更简单.计算将来50个小时的唤醒时间并旋转直到达到该时间.
  • 用于getchar在最后阻止程序.这不会消耗CPU时间,它允许您通过按下结束程序Enter.线程没有像通常那样正常结束,但在这个简单的情况下,让进程退出时让操作系统终止它们可能是可以的.
  • 与原始代码一样,这假定clockSleep使用相同的刻度.这无疑是一个大胆的假设,但它在原始代码中使用的Win32下都是正确的(两个"滴答"都是毫秒).C++没有Sleep(没有boost::thread或C++ 11 std::thread),所以如果打算使用非Windows可移植性,那么无论如何都必须重新思考.
  • 与原始代码一样,它依赖于不精确且不可靠的功能(clockSleep).在没有使用的情况下Sleep(50)等于Sleep(63)我的系统timeBeginPeriod.尽管如此,该程序"几乎完美"工作,导致我的机器负载增加50%+/ - 0.5%.
  • 与原始代码一样,这不考虑线程优先级.具有高于普通优先级的进程将完全不受此限制代码的影响,因为这是Windows调度程序的工作方式.

    #include <windows.h>
    #include <process.h>
    #include <time.h>
    #include <stdio.h>
    
    
    void task1(void *)
    {
        while(1)
        {
            clock_t wakeup = clock() + 50;
            while(clock() < wakeup) {}
            Sleep(50);
        }
    }
    
    int main(int, char**)
    {
        int ThreadNr;
        for(int i=0; i < 4; i++) _beginthread( task1, 0, &ThreadNr );
    
        (void) getchar();
        return 0;
    }
    
    Run Code Online (Sandbox Code Playgroud)