5

我目前正在使用 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){}
}

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

我的问题是:

  1. 我是否已将另一篇文章中的 C# 代码正确翻译为 C++?
  2. 这段代码会在四核处理器上产生 50% 的平均 CPU 负载吗?
  3. 我怎样才能在合理的准确度内找出 CPU 的负载百分比?(任务管理器是我唯一的选择吗?)

编辑:我问这个问题的原因是我希望最终能够在合理的公差范围内产生 10、20、30、...、90% 的 CPU 负载。此代码似乎可以很好地生成负载 70%<,但在任何低于 70% 的负载下似乎都非常不准确(由任务管理器 CPU 负载读数测量)。

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

4

3 回答 3

8

乍一看,这看起来不像是漂亮但正确的 C++ 或 C(确定它的简单方法是编译它)。缺少包含 ( <windows.h>,<process.h><time.h>) 但否则它编译得很好。

请注意,clockandSleep并不是非常准确,Sleep也不是非常可靠。不过,平均而言,线程函数应该按预期工作(给予或接受几个百分比的变化)。

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

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

另请注意,以这种方式模拟负载可能会起作用,但不是 100% 可靠。
可能存在难以预测的影响(内存、执行单元)。例如,假设您在这个循环中使用了 100% 的 CPU 整数执行单元(合理的假设),但它的浮点或 SSE 单元为零。现代 CPU 可能会在真实或逻辑内核之间共享资源,您可能无法准确预测得到的效果。或者,另一个线程可能是内存受限或有严重的页面错误,因此占用 CPU 时间不会像您想象的那样影响它(实际上可能会给它足够的时间来使预取工作更好)。或者,它可能会阻止 AGP 传输。或者,还有一些你说不出来的东西。

编辑:

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

  • 用于clock_t返回的值clock(从技术上讲,这比使用非特殊typedef的整数“更正确”。顺便说一句,这可能是原始代码无法按预期工作的原因,因为clock_t它是 Win32 下的有符号整数。条件inif()总是评估true,所以工作人员几乎一直在睡觉,不消耗 CPU。
  • 旋转时代码更少,数学更简单。计算未来 50 个滴答声的唤醒时间并旋转直到达到该时间。
  • 用于getchar在最后阻止程序。这不会消耗 CPU 时间,它允许您按 结束程序Enter。线程没有像通常那样正确结束,但在这种简单的情况下,让操作系统在进程退出时终止它们可能是可以的。
  • 与原始代码一样,这假定clockSleep使用相同的刻度。这无疑是一个大胆的假设,但在您在原始代码中使用的 Win32 下它是正确的(两个“滴答”都是毫秒)。C++ 没有类似的东西Sleep(没有boost::thread, 或 C++11 std::thread),所以如果打算使用非 Windows 可移植性,无论如何你都必须重新考虑。
  • 与原始代码一样,它依赖于不精确且不可靠的函数 (clock和)。在我的系统上等于而不使用. 尽管如此,该程序“几乎完美”地运行,导致我的机器上的负载为 50% +/- 0.5%。SleepSleep(50)Sleep(63)timeBeginPeriod
  • 与原始代码一样,这没有考虑线程优先级。具有高于正常优先级的进程将完全不会被此限制代码所打动,因为这就是 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;
    }
    
于 2013-01-09T10:48:46.690 回答
2

这是一个代码示例,它在 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 以终止应用程序。

于 2014-03-27T11:32:39.440 回答
1

您可以使用 Windows性能计数器 API来获取 CPU 负载。适用于整个系统或您的流程。

于 2013-01-09T08:57:24.927 回答