所以我前几天做了一些关于并发性的思考,我想知道为每个元素保护带有单个互斥锁的阵列是否更快,或者整个阵列使用一个互斥锁来保护它是否更快其中的所有数据。从逻辑上讲,我认为一个程序可以使用invidual互斥锁更快地执行,这样每个线程只需要" checkout"他们需要的元素,听起来像是可以实现更好的并发性。如果只有一个能够一次执行等待互斥锁,那么肯定会有很多等待。为了测试这个理论,我创建了一组像this这样的测试。在这两个函数中,所做的就是锁定互斥锁并将随机值写入数组中的随机位置,唯一的区别是每个元素在第一个函数中都有自己的互斥锁,然后所有元素在第二个中共享一个互斥锁。我将运行次数保持为25,以便在每次测试结束时获得良好的平均值。
我用它跑了:
NUM_ELEMENTS = 10;
NUM_THREADS = 5;
results
NUM_ELEMENTS = 100;
NUM_THREADS = 5;
results
NUM_ELEMENTS = 10;
NUM_THREADS = 10;
results
NUM_ELEMENTS = 100;
NUM_THREADS = 10;
results
NUM_ELEMENTS = 10;
NUM_THREADS = 15;
results
NUM_ELEMENTS = 100;
NUM_THREADS = 15;
results
对于在数组中使用10个元素的集合,下面是2种不同方法的平均值图表。 here
对于在数组中使用100个元素的集合,下面是两种不同方法的平均值图表。 here
为了记录,这一切都是在MingW完成的,因为我没有工作的linux盒子(因为原因),除了-c ++ 11之外没有其他标志。正如你所看到的,我的原始理论是完全错误的。显然,如果整个数组值共享一个互斥量用于写入,则它比具有自己锁定的每个值快得多。这似乎完全违反直觉。所以我向你们提出了一个聪明的人的问题,这个系统或其他地方正在发生的事情导致了这个难题。请纠正我的想法!
编辑:刚刚注意到图表没有正确导入,所以你不知道发生了什么。固定 编辑:根据@nanda的建议,除了使用4个线程的线程池之外,我还实现了2个类似的测试,它们处理与其他线程相同数量的随机分配给测试向量。 Here是更新的测试,here是输出文件。在奇思妙想中,我还将原来的2个测试使用的线程数减少到4个(我的cpu上的核心数),以及如输出所示,这两种方法现在平均时间非常相似。这样可以得出@nanda的推理是正确的结论,即大量的可运行线程(或者比你的内核多得多的线程)导致系统必须排队进程线程,导致大量的延迟但也是一时兴起,我添加了一个"控制"可以这么说,这只是一个异步循环,它对数组进行了相同数量的随机访问。它比并行方法快得多。另外,正如您可能注意到的那样,执行与原始两种方法相同数量的访问的线程池方法比原始的两种方法完成得快得多。所以这是我的两个新问题。与异步方法相比,为什么世界上并发方法的速度非常慢。另外,为什么并发的线程池方法比原始方法快一点?