【问题标题】:Simulate steady CPU load and spikes模拟稳定的 CPU 负载和峰值
【发布时间】:2011-01-31 15:43:02
【问题描述】:

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

【问题讨论】:

    标签: c# cpu-usage


    【解决方案1】:

    首先,您必须了解 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

    【讨论】:

      【解决方案2】:

      除了 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();
              }
         }
      

      【讨论】:

      • 我使用了你的功能,它几乎可以工作。 8 个内核中有 7 个处于所需水平,然后我将“for (int i = 0;i
      【解决方案3】:

      对于统一的强调: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();
      }
      

      【讨论】:

        【解决方案4】:

        每次你必须设置 cpuUsageIncreaseby 变量。 例如:

        1- Cpu % 增加 > cpuUsageIncreaseby % 一分钟。 2- 降到 0% 20 秒。 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);
                        }
                    }
                }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-14
          相关资源
          最近更新 更多