- 一个完全由CPU限制的非常大的任务(即,超过几个CPU周期),以及
- 一台具有四个物理核心和总共8个逻辑核心的CPU,
在这种情况下,8、16和28个线程是否比4个线程效果更好?我知道,对于具有四个物理核心的机器而言,四个线程的上下文切换和开销都会比8、16或28个线程少。然而,具体的时序如下:
Threads Time Taken (in seconds)
4 78.82
8 48.58
16 51.35
28 52.10
下面的原始问题部分提到了用于测试获取时间的代码。CPU规格也在底部给出。
超线程通过复制处理器的某些部分(存储架构状态的部分),但不复制主要执行资源来工作。这使得超线程处理器在主机操作系统中可以看作是一个常规的“物理”处理器和一个额外的“逻辑”处理器。
?
今天在SO上有人提出了这个问题,它测试了多个线程同时执行相同任务的性能。以下是相关代码:private static void Main(string[] args)
{
int threadCount;
if (args == null || args.Length < 1 || !int.TryParse(args[0], out threadCount))
threadCount = Environment.ProcessorCount;
int load;
if (args == null || args.Length < 2 || !int.TryParse(args[1], out load))
load = 1;
Console.WriteLine("ThreadCount:{0} Load:{1}", threadCount, load);
List<Thread> threads = new List<Thread>();
for (int i = 0; i < threadCount; i++)
{
int i1 = i;
threads.Add(new Thread(() => DoWork(i1, threadCount, load)));
}
var timer = Stopwatch.StartNew();
foreach (var thread in threads) thread.Start();
foreach (var thread in threads) thread.Join();
timer.Stop();
Console.WriteLine("Time:{0} seconds", timer.ElapsedMilliseconds/1000.0);
}
static void DoWork(int seed, int threadCount, int load)
{
var mtx = new double[3,3];
for (var i = 0; i < ((10000000 * load)/threadCount); i++)
{
mtx = new double[3,3];
for (int k = 0; k < 3; k++)
for (int l = 0; l < 3; l++)
mtx[k, l] = Math.Sin(j + (k*3) + l + seed);
}
}
(我删掉了一些括号,以便将代码放在一页上以便快速阅读。)
我在我的机器上运行了这段代码来复制问题。我的机器有四个物理核心和八个逻辑核心。上面的代码中的方法
DoWork()
完全受限于CPU。我觉得超线程可能会带来30%的加速(因为这里有与物理核心数量相同的受限于CPU的线程(即4个))。但实际上它几乎达到了64%的性能提升。当我用四个线程运行这段代码时,大约需要82秒,而当我用8、16和28个线程运行这段代码时,在所有情况下都在大约50秒内完成。总结时间如下:
Threads Time Taken (in seconds)
4 78.82
8 48.58
16 51.35
28 52.10
我可以看到,使用四个线程时,CPU使用率约为50%。难道不应该是100%吗?毕竟,我的处理器只有四个物理核心。而当使用8和16个线程时,CPU使用率约为100%。
我正在努力理解为什么一个完全依赖于CPU的进程在启用超线程后会表现得更好。
为了完整起见,
- 我有Intel Core i7-4770 CPU @ 3.40 GHz, 3401 MHz, 4个内核,8个逻辑处理器。
- 我在发布模式下运行了代码。
- 我知道时间测量的方法不好。这只会给出最慢线程的时间。我将代码原样从其他问题中拿来。