在C ++中模拟CPU负载

时间:2013-01-09 08:48:21

标签: 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){}
}

我使用与此主题中给出的答案相同的方法编写此代码:Simulate steady CPU load and spikes

我的问题是:

  1. 我是否已将C#代码从其他帖子正确翻译到C ++?
  2. 此代码是否会在四核处理器上产生50%的平均CPU负载?
  3. 如何在合理的准确度下找出CPU的负载百分比? (任务经理是我唯一的选择吗?)
  4. 编辑:我问这个问题的原因是我希望最终能够在合理的容差范围内生成10,20,30,...,90%的CPU负载。该代码似乎适用于生成70%的负载&lt;但在任何低于70%的负载下(由任务管理器CPU负载读数测量)似乎非常不准确。

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

3 个答案:

答案 0 :(得分:6)

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

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

但是,关于问题2),您应该将最后while(1){}替换为阻止而不是旋转的内容(例如WaitForSingleObjectSleep)。否则整个程序将在四核上加载50%。由于主线程,您将在一个核心上100%加载,加上四个工作者的4x 50%。这显然会导致每个核心超过50%(并且会导致线程从一个核心反弹到另一个核心,导致令人讨厌的副作用)。

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

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

修改

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

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

    #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;
    }
    

答案 1 :(得分:1)

您可以使用Windows perf counter API来获取CPU负载。无论是整个系统还是整个系统。

答案 2 :(得分:1)

这是一个代码示例,它在Windows上将我的CPU加载到100%。

#include "windows.h"

DWORD WINAPI thread_function(void* data)
{
    float number = 1.5;
    while(true)
    {
        number*=number;
    }
    return 0;
}

void main()
{
    while (true)
    {
        CreateThread(NULL, 0, &thread_function, NULL, 0, NULL);
    }
}

在构建应用程序并运行它时,按Ctrl-C终止应用程序。