Parallel processing Go中并行快速排序中的死锁
作为练习,我正在尝试在Go中实现一个并行版本的快速排序。这就是我到目前为止所做的:Parallel processing Go中并行快速排序中的死锁,parallel-processing,go,deadlock,quicksort,Parallel Processing,Go,Deadlock,Quicksort,作为练习,我正在尝试在Go中实现一个并行版本的快速排序。这就是我到目前为止所做的: func quicksort(nums []int, ch chan int, level int, threads int) { level *= 2; if len(nums) == 1 { ch<- nums[0]; close(ch); return } less := make([]int, 0) greater := make([]int,0) pivot := num
func quicksort(nums []int, ch chan int, level int, threads int) {
level *= 2;
if len(nums) == 1 { ch<- nums[0]; close(ch); return }
less := make([]int, 0)
greater := make([]int,0)
pivot := nums[0]
nums = nums[1:]
for _,i := range nums{
switch{
case i <= pivot:
less = append(less,i)
case i > pivot:
greater = append(greater,i)
}
}
ch1 := make(chan int, len(less))
ch2 := make(chan int, len(greater))
if(level <= threads){
go quicksort(less, ch1, level, threads)
go quicksort(greater,ch2, level, threads)
}else{
quicksort(less,ch1, level, threads)
quicksort(greater,ch2, level, threads)
}
for i := range ch1{
ch<-i;
}
ch<-pivot
for i := range ch2{
ch<-i;
}
close(ch)
return
}
func快速排序(nums[]int,ch chan int,level int,threads int){
级别*=2;
如果len(nums)=1{ch代码有一个问题,并且至少有一个潜在的错误使用情况:
缺少一个基本情况。考虑如果<代码> QuaskSuth被要求对空切片排序,将会发生什么。
当第一次调用quicksort
时,比如在main()
中,如果没有在单独的goroutine中生成分类器,则运行顶级排序的主线程可能会阻止尝试写回通道(取决于顶级通道本身是否已缓冲)
例如:
func main() {
x := []int{3, 1, 4, 1, 5, 9, 2, 6}
ch := make(chan int)
quicksort(x, ch, 0, 0) // buggy!
for v := range(ch) {
fmt.Println(v)
}
}
这是一个错误,因为它要求主线程进行排序,但它将不可避免地在快速排序的这一部分阻塞:它无法与自身通信
for i := range ch1{
ch<-i;
}
现在我们避免了这个死锁问题。是你吗,莱纳斯???;-)嗯,是的:)。我不确定我是否就是你要找的莱纳斯。如果你提供完整的程序和恐慌,调试起来会更容易。你能把你的程序放上去吗?这样,就更容易发现错误。我把这个放在play.golang.org上--不确定我是否可以正确地说,但我没有死锁,我得到了“恐慌:运行时错误:索引超出范围”。我还注意到pivot在通道上被发送了两次。它在中小于(因为它小于或等于自身),所以递归调用将通过ch1,然后是ch,但随后它也被显式发送(ch谢谢!启动sort as go例程成功了:)。不过我确实有一个新问题,因为(即使在将GOMAXPROCS设置为我的内核数之后)我的并行版本比顺序版本花费的时间多150%…在我看来,这是一个相当好的并行化问题,go例程应该很轻…即使N=100000,并行速度也要慢得多…@Linus Goroutines相对于操作系统线程来说是便宜的。go的并发原语更适合粗粒度的pa集合主义。你在解决方案中选择的设计在我看来像是细粒度的并行。我建议你问一个关于快速排序性能的新问题。请包括基准测试!
func main() {
x := []int{3, 1, 4, 1, 5, 9, 2, 6}
ch := make(chan int)
go quicksort(x, ch, 0, 0)
for v := range(ch) {
fmt.Println(v)
}
}