C 与线程并行合并排序/比Seq慢/多。合并排序。帮助

C 与线程并行合并排序/比Seq慢/多。合并排序。帮助,c,pthreads,parallel-processing,mutex,mergesort,C,Pthreads,Parallel Processing,Mutex,Mergesort,^这是我的并行合并排序的实现。基本上,我所做的是,对于每一次拆分,前半部分由线程处理,而后半部分是顺序的(即)假设我们有一个9个元素的数组,[0..4]由线程1处理,[0..1]由线程2处理,[5..6]由线程3处理(请查看源代码以获得澄清) 其他一切都保持不变,比如合并。但问题是,这比合并排序慢得多,甚至比普通冒泡排序慢!我的意思是对于25000 int的数组。我不确定瓶颈在哪里:是互斥锁吗?是合并吗 有没有办法加快速度?既然系统上的内核数量有限,为什么要创建比内核更多的线程 此外,还不清楚为

^这是我的并行合并排序的实现。基本上,我所做的是,对于每一次拆分,前半部分由线程处理,而后半部分是顺序的(即)假设我们有一个9个元素的数组,[0..4]由线程1处理,[0..1]由线程2处理,[5..6]由线程3处理(请查看源代码以获得澄清)

其他一切都保持不变,比如合并。但问题是,这比合并排序慢得多,甚至比普通冒泡排序慢!我的意思是对于25000 int的数组。我不确定瓶颈在哪里:是互斥锁吗?是合并吗


有没有办法加快速度?

既然系统上的内核数量有限,为什么要创建比内核更多的线程


此外,还不清楚为什么需要一个互斥体。从快速扫描中可以看出,程序不需要在本地函数之外共享线程[lthreadcnt]。只要使用一个局部变量,您就应该是黄金。

您正在创建大量线程,每个线程只做很少的工作。要对25000个整数进行排序,您需要创建大约12500个线程来生成其他线程并合并它们的结果,以及大约12500个线程,每个线程只对两个整数进行排序

创建所有这些线程的开销远远超过了并行处理带来的收益


为了避免这种情况,请确保每个线程都有合理的工作量要做。例如,如果一个线程发现它只需要排序您的并行性太细粒度,那么有太多的线程只做很小的工作。您可以定义阈值,以便按顺序对大小小于阈值的数组进行排序。小心繁殖线程的数量,一个很好的迹象是线程的数量通常不会比内核的数量大很多


由于您的大部分计算都在
merge
函数中,另一个建议是使用分治合并而不是简单的合并。其优点有两个:运行时间更短,并且很容易生成线程来运行并行合并。您可以在此处了解如何实现并行合并:。他们还有一篇关于并行合并排序的文章,可能会对您有所帮助:

对于堆栈溢出问题,您不应该使用一天内过期的粘贴箱,因为它会阻止其他人在下周学习如何解决您的问题(或明天回答您的问题)。您根本不应该使用粘贴箱。不要通过并行执行相同的位来实现递归样式的合并排序。当子列表的长度达到(比如)1000时,线程通信的开销开始接近合并所需的时间,所以只需进行快速排序即可(或者,不管怎样,只要看到相同的点)。另外,正如其他人所说,只需将合并排队到[核心数]线程或其他线程池实现即可。您可以将合并与回调同步。如果这样做,4/8核处理器上的“平铺合并排序”将排序1000000个整数,比单线程快速排序快6倍。这一点很好。我被这个封闭的想法吸引住了,因为我已经为此工作了5个小时。O.O,您确实强调了创建大量线程(约12500个)的重要性。因此,串行拆分而并行合并会更快?您可以使用递归限制进行并行拆分(对于2和4个核来说很好,对于6或8个核来说不太好),但是串行拆分可能会更有效。您也没有进行任何I/O操作,因此大量的线程无法提高任何效率。这可能远远超出了您想要的范围,但是如果您可以在缓存线边界上拆分阵列,那么您也可能在那里获得性能上的胜利,因为争用成本很高。由于较少线程查看大量数据,这一点就不那么重要了。