我正在编写一个测试程序来启动两个线程,如下所示。
当我使用Process.ProcessorAffinity绑定来限制仅使用1个CPU时,该程序需要执行45.8683742秒的时间,而CPU 2几乎不需要时间在此处使用操作系统内核程序。
当我使用Process.ProcessorAffinity绑定来限制仅使用2个CPU时,该程序需要执行67.733864秒,而CPU 1,2则几乎不需要时间在这里使用操作系统内核程序。
当我使用Process.ProcessorAffinity绑定来限制仅使用3个CPU时,该程序将执行116.8519694秒,而它们所占用的CPU 1,2,3将使用更多时间的操作系统内核程序。
当我使用Process.ProcessorAffinity绑定来限制仅使用8个CPU时,该程序将花费132.9382714秒来执行,并且它们所占用的所有CPU都将花费更多的时间来使用操作系统内核程序。
我不知道发生了什么,有人可以帮忙解释一下吗?
class Program
{
private static long counter = 0;
public static void Main()
{
//Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)7;
Thread thread1 = new Thread(MyMethod);
Thread thread2 = new Thread(MyMethod);
thread1.Start();
thread2.Start();
Stopwatch sw = new Stopwatch();
sw.Start();
thread1.Join();
thread2.Join();
sw.Stop();
Console.WriteLine($"Sum is {counter}");
Console.WriteLine($"Total is {sw.Elapsed.TotalSeconds} Sec");
Console.WriteLine("Press any key for continuing...");
Console.ReadKey();
}
private static void MyMethod()
{
for (int index = 0; index < int.MaxValue; index++)
{ Interlocked.Increment(ref counter); }
}
}
答案 0 :(得分:2)
根据您的评论,您试图通过该计数器强制出现竞争状态。这里的问题是每个CPU都有一层层的缓存。
虽然CPU和运行时不能保证没有没有竞争条件,但至少最好不要主动导致。几乎没有什么东西可以使它们快到3层缓存中的任何一层都不同步。
例如,如果核心1更改了其第1层缓存中的counter值,则该更改将被有效地传播到第3层缓存-然后传播到每个核心的第1层缓存中。
由于操作为counter = counter + 1
,因此仍然存在争用条件的空间。虽然您假设该操作将完全受CPU限制,但刷新缓存实际上会强制将其限制为内存。