我有一个简单的程序,它启动 n 个线程并在每个线程上创建一些负载。 如果我只启动一个线程,一个核心将获得大约 100% 的负载。 如果我启动一个有 16 个线程的进程(这意味着每个内核一个线程),我只能得到大约 80% 的负载。 如果我用 2 个线程启动 8 个进程(这仍然意味着每个内核一个线程),我得到大约 99% 的负载。 我没有在此示例中使用任何锁定。
这种行为的原因是什么? 我知道如果有 100 个线程在工作,负载就会下降,因为操作系统必须进行大量调度。 但在这种情况下,线程数与核心数一样多。
情况更糟(至少对我而言)。 如果我在我的循环中添加一个简单的 thread.sleep(0),一个进程和 16 个线程的负载增加到 95%。
谁能回答这个问题,或提供有关此特定主题的更多信息的链接?
//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/