web-dev-qa-db-ja.com

安定したCPU負荷とスパイクをシミュレートする

C#で一定期間100%未満の安定したCPU負荷を生成するにはどうすればよいですか?また、一定期間後に負荷量を変更できるようにしたいと思います。非常に短時間で使用量の急増を生成することをどのように推奨しますか?

42
kjv

まず、CPU使用率は常に特定の期間の平均であることを理解する必要があります。いつでも、CPUは機能しているか機能していないかのどちらかです。 CPUが40%動作することはありません。

ただし、CPUを0.4秒間動作させ、0.6秒間スリープさせることで、たとえば1秒間に40%の負荷をシミュレートできます。これにより、その1秒間の平均使用率は40%になります。

1秒未満に短縮すると、たとえば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();
        }
    }
}

TickCount プロパティよりも正確であるため、ここでは stopwatch を使用していますが、同様にそれを使用し、減算を使用して、十分に長く実行されたかどうかを確認できます。 。

覚えておくべき2つのこと:

  • マルチコアシステムでは、コアごとに1つのスレッドを生成する必要があります。それ以外の場合は、CPU /コアが1つだけ実行され、おおよそ「パーセンテージ/コア数」の使用率が示されます。
  • Thread.Sleepはあまり正確ではありません。正確にミリ秒までの時間を保証することは決してないので、結果にいくつかの変動が見られます

2番目の質問に答えるには、一定時間後に使用率を変更することについて、このメソッドを1つ以上のスレッド(コアの数に応じて)で実行し、使用率を変更する場合は、それらのスレッドを停止して新しいスレッドを生成することをお勧めします新しいパーセンテージ値で。そうすれば、実行中のスレッドのpercentageを変更するためにスレッド通信を実装する必要はありません。

57
Isak Savo

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();
        }
   }
16
Guido Zanon

均一なストレスの場合:IsakSavoの答えを少し調整します

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();
}
5
fartwhif

cpuUsageIncreaseby変数を設定する必要があるたびに。例:

1- 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);
                }
            }
        }
1