Parallel processing 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

作为练习,我正在尝试在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 := 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)
        }
    }