[英]Why does multithreading give a worse performance here?
我通过bitarray设置枚举每秒都为false。
现在我想通过分割它分成两个线程。对于一些奇怪的原因,不过,每个线程来完成工作的半量需要更多的64%的时间的时间加快这,我不知道为什么?
这可能是由于某种CPU缓存效应? 我该怎么做呢?
我以前用lambda表达式尝试了8个线程,但它总是大约1400毫秒,但是在单线程中我常常得到850毫秒。 此外,当我让一个线程完成所有工作时,我花了830毫秒。 我只是不明白,有人知道这里的原因吗?
码:
class Program
{
static int count = 0x10000000;
static int half = count / 2;
static BitArray bitArray = new BitArray(count);
static unsafe void Main(string[] args)
{
Stopwatch sw = Stopwatch.StartNew();
#if SINGLE
for (int i = 0; i < bitArray.Count; i += 2)
bitArray.Set(i, true);
#else
Thread thread1 = new Thread(Thread1);
Thread thread2 = new Thread(Thread2);
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
#endif
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.ReadLine();
}
static void Thread1()
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < half; i += 2)
bitArray.Set(i, true);
sw.Stop();
Console.WriteLine("Thread1: {0}", sw.ElapsedMilliseconds);
}
static void Thread2()
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = half; i < count; i += 2)
bitArray.Set(i, true);
sw.Stop();
Console.WriteLine("Thread2: {0}", sw.ElapsedMilliseconds);
}
}
BitArray不是一个线程安全的类。 你不应该这样使用它。 事实上,除了正确性之外,这很可能是缓慢的原因。 原因如下:
如果你查看BitArray的源代码,它包含一个int version
字段,它在每次操作时都会更新,特别是你调用的Set()
。
这意味着每个线程不断更新相同的内存位置,这是一个巨大的性能杀手,因为所有内核在访问此位置时都必须进行通信和同步。 在这种情况下,多线程解决方案的性能比单核解决方案更差,这是完全合理的。
因为线程并不像看起来那么容易。
首先,正如文档所述 ,BitArrays不是线程安全的。 这意味着当多个线程同时使用时,它们可能并且将会出现不可预测的行为。
至于性能损失,可能是由于你的两个线程导致的总线流量增加,试图同时修改相同的内存位置,不断地使彼此的缓存无效。
即使您认为您的线程没有修改相同的位置,也可能不是这样。 例如,BitArray有一个Count
属性。 每次将位设置为1时,线程很可能会修改一个计数器变量,即支持Count
属性。 由于竞争条件和陈旧值,这种并发修改是危险的,并且可能会增加总线流量,如前所述。
问题是CPU内核的工作频率为2-3GHz,而RAM和内存总线的工作频率为1Ghz。 ram速度慢得多,RAM访问需要大约100个CPU周期。 如果打破CPU的缓存机制,很明显性能会下降。
编辑:更不用说线程创建和加入涉及很大的开销。 如果你的工作是830ms一次性。 您不太可能通过多线程获得重大改进。 您还应该尝试去除线程中的Stopwatches,因为它们也是开销。
我修改了您的代码,以便测试运行10次并报告结果。 使用您的代码,我看到单线程与多线程测试的相似时序(每个线程大约需要1200毫秒)。
但是,正如其他人所说的那样,不能保证从多个线程使用单个BitArray不会导致线程之间发生争用。
通过为每个线程提供自己的BitArray而不是使用共享的静态BitArray,可以最简单地证明这一点。 通过这种方法,我通常会看到每个线程大约需要450毫秒,尽管偶尔会看到更长的时间:
Thread2: 415
Thread1: 420
447
Thread2: 414
Thread1: 420
496
Thread1: 1185
Thread2: 1198
1249
Thread1: 417
Thread2: 421
455
Thread1: 420
Thread2: 415
455
Thread2: 413
Thread1: 417
491
Thread2: 413
Thread1: 417
508
Thread2: 417
Thread1: 441
526
Thread1: 420
Thread2: 415
465
Thread1: 940
Thread2: 1005
1087
最终我认为这表明:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.