模拟稳定的CPU负载和突发性峰值

42

如何在C#中生成稳定的CPU负载,在一定时间内低于100%?我还希望能够在一定时间后更改负载量。您建议如何在非常短的时间内生成使用峰值?

4个回答

59

首先,您必须理解CPU使用率始终是一定时间内的平均值。在任何给定的时间,CPU要么在工作,要么不在工作。CPU永远不会有40%的工作负载。

但是,我们可以通过让CPU工作0.4秒然后睡眠0.6秒来模拟一秒钟内的40%负载。这将在那一秒钟内给出40%的平均利用率。

如果将其缩小到小于一秒的时间段,比如100毫秒的块,应该会得到更稳定的利用率。

以下方法将接受所需利用率作为参数,然后将单个CPU /核心利用到该程度:

public static void ConsumeCPU(int percentage)
{
    if (percentage < 0 || percentage > 100)
        throw new ArgumentException("percentage");
    Stopwatch watch = new Stopwatch();
    watch.Start();            
    while (true)
    {
        // Make the loop go on for "percentage" milliseconds then sleep the 
        // remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms
        if (watch.ElapsedMilliseconds > percentage)
        {
            Thread.Sleep(100 - percentage);
            watch.Reset();
            watch.Start();
        }
    }
}

我在这里使用Stopwatch,因为它比TickCount属性更准确,但您也可以使用后者并使用减法来检查运行时间是否足够长。

需要注意两点:

  • 在多核系统上,您将不得不为每个核心生成一个线程。否则,您将只看到一个CPU/核心被占用,给出大约“百分比/核数”的利用率。
  • Thread.Sleep不太准确。它永远无法确保精确到毫秒的时间,因此您将看到结果有一些变化。

为了回答您的第二个问题,关于在一定时间后更改利用率,我建议您在一个或多个线程上运行此方法(取决于核心数),然后当您想要更改利用率时,只需停止这些线程并使用新的百分比值生成新的线程即可。这样,您就不必实现线程通信来更改正在运行的线程的percentage


18

在回答Isak的问题之后,我在这里提供了一个简单的多核实现:

 public static void CPUKill(object cpuUsage)
    {
        Parallel.For(0, 1, new Action<int>((int i) =>
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            while (true)
            {
                if (watch.ElapsedMilliseconds > (int)cpuUsage)
                {
                    Thread.Sleep(100 - (int)cpuUsage);
                    watch.Reset();
                    watch.Start();
                }
            }
        }));

    }

    static void Main(string[] args)
    {
        int cpuUsage = 50;
        int time = 10000;
        List<Thread> threads = new List<Thread>();
        for (int i = 0; i < Environment.ProcessorCount; i++)
        {
            Thread t = new Thread(new ParameterizedThreadStart(CPUKill));
            t.Start(cpuUsage);
            threads.Add(t);
        }
        Thread.Sleep(time);
        foreach (var t in threads)
        {
            t.Abort();
        }
   }

2
我使用了你的函数,它几乎可以工作。8个核心中有7个达到了期望的水平,然后我将 "for (int i = 0; i < Environment.ProcessorCount; i++)" 更改为 "for (int i = 0; i < Environment.ProcessorCount + 1; i++)",现在它可以工作了... - ElMaquinista

5

为了实现均匀的负载压力:以Isak Savo的回答为基础,稍作调整。这个问题很有趣。实际上,有些工作负载在瓦数使用、热量输出、通道饱和度等方面远远超过了它,也许使用循环作为工作负载是不佳且几乎不切实际的。

int percentage = 80;
for (int i = 0; i < Environment.ProcessorCount; i++)
{
    (new Thread(() =>
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        while (true)
        {
            // Make the loop go on for "percentage" milliseconds then sleep the 
            // remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms
            if (watch.ElapsedMilliseconds > percentage)
            {
                Thread.Sleep(100 - percentage);
                watch.Reset();
                watch.Start();
            }
        }
    })).Start();
}

1
每次您都需要设置cpuUsageIncreaseby变量。 例如: 1- Cpu%增加了> cpuUsageIncreaseby%一分钟。 2- 在20秒内降至0%。 3- 转到步骤1。
     private void test()
        {
            int cpuUsageIncreaseby = 10;
            while (true)
            {
                for (int i = 0; i < 4; i++)
                {
                    //Console.WriteLine("am running ");
                    //DateTime start = DateTime.Now;
                    int cpuUsage = cpuUsageIncreaseby;
                    int time = 60000; // duration for cpu must increase for process...
                    List<Thread> threads = new List<Thread>();
                    for (int j = 0; j < Environment.ProcessorCount; j++)
                    {
                        Thread t = new Thread(new ParameterizedThreadStart(CPUKill));
                        t.Start(cpuUsage);
                        threads.Add(t);
                    }
                    Thread.Sleep(time);
                    foreach (var t in threads)
                    {
                        t.Abort();
                    }

                    //DateTime end = DateTime.Now;
                    //TimeSpan span = end.Subtract(start);
                    //Console.WriteLine("Time Difference (seconds): " + span.Seconds);

                    //Console.WriteLine("10 sec wait... for another.");
                    cpuUsageIncreaseby = cpuUsageIncreaseby + 10;
                    System.Threading.Thread.Sleep(20000);
                }
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接