c# - 为什么 8 个 2 个线程的进程比 16 个线程的 1 个进程产生更多的负载?

标签 c# multithreading

我有一个简单的程序,它启动 n 个线程并在每个线程上创建一些负载。 如果我只启动一个线程,一个核心将获得大约 100% 的负载。 如果我启动一个有 16 个线程的进程(这意味着每个内核一个线程),我只能得到大约 80% 的负载。 如果我用 2 个线程启动 8 个进程(这仍然意味着每个内核一个线程),我得到大约 99% 的负载。 我没有在此示例中使用任何锁定。

这种行为的原因是什么? 我知道如果有 100 个线程在工作,负载就会下降,因为操作系统必须进行大量调度。 但在这种情况下,线程数与核心数一样多。

情况更糟(至少对我而言)。 如果我在我的循环中添加一个简单的 thread.sleep(0),一个进程和 16 个线程的负载增加到 95%。

谁能回答这个问题,或提供有关此特定主题的更多信息的链接?

One Process 16 threads

Eight Process 2 threads

One Process 16 threads with thread.sleep(0)

//Sample application which reads the number of threads to be started from Console.ReadLine
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Enter the number of threads to be started");
            int numberOfThreadsToStart;

            string input = Console.ReadLine();

            int.TryParse(input, out numberOfThreadsToStart);
            if(numberOfThreadsToStart < 1)
            {
                Console.WriteLine("No valid number of threads entered. Exit now");
                Thread.Sleep(1500);
                return;
            }

            List<Thread> threadList = new List<Thread>();
            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < numberOfThreadsToStart; i++)
            {
                Thread workerThread = new Thread(MakeSomeLoad);
                workerThread.Start();
                threadList.Add(workerThread);
            }

            while (true)
            {
                Console.WriteLine("I'm spinning... ");
                Thread.Sleep(2000);
            }
        }

        static void MakeSomeLoad()
        {
            for (int i = 0; i < 100000000; i++)
            {

                for (int j = 0; j < i; j++)
                {
                    //uncomment the following line to increase the load
                    //Thread.Sleep(0);
                    StringBuilder sb = new StringBuilder();
                    sb.Append("hello world" + j);
                }
            }
        }
    }

最佳答案

您的测试看起来 GC 非常繁重。如果您在一个进程中有 16 个线程,则 GC 将在该进程中运行更多,并且由于客户端 GC 不是并行的,这会导致较低的负载。即每个 GC 线程有 16 个垃圾生成线程。

另一方面,如果您运行 8 个进程,每个进程有两个线程,则只有两个线程为每个 GC 线程产生垃圾,并且 GC 可以在这些进程之间并行工作。

如果您编写的测试产生的垃圾较少,并且直接使用更多的 CPU,您可能会得到不同的结果。

(请注意,这只是推测,我没有运行您的测试,而且由于我只有双核 CPU,无论如何结果都会与您不同)

关于c# - 为什么 8 个 2 个线程的进程比 16 个线程的 1 个进程产生更多的负载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9330348/

相关文章:

c# - 如何用空格替换 ""“

.NET 减少了重复运行时的并行线程

c# - WCF - 如何获得一些 channel 标识符?

c# - 从结构数组中删除 double

asp.net - “System Idle Process”在高线程应用程序上吃掉CPU

java - Spring中实例DAI与Singleton Bean的交互

java - 在android中安排多个异步任务

c++ - 通过 Python 控制台对 PythonQt 库进行非锁定调用

c# - 为具有 List 对象属性的模型生成创建 View

c# - 在 C# 的代码隐藏中编写 SQLdatasource 以使用代码隐藏值