回 帖 发 新 帖 刷新版面

主题:多线程用于快速排序

请问一个多线程用于快速排序的问题。以下是并行化后的简单例子(FORTRAN)。为什么并行化后用时反而比串行长?有什么好的建议吗?

program quicksortopenmp
implicit integer (a-z)
dimension iitem1(30)
s1=1
t1=30
DATA IITEM1/0, 10, 20, 30, 40, 50, 60, 100, 200, 500,&
            600, 610, 210, 225, 200, 100, 111, 210, 225, 255,&
            1, 7, 3, 5, 11, 23, 29, 18, 9, 14/
call quicksort(iitem1,s1,t1)
print *,'iitem1',iitem1
end program quicksortopenmp
    
recursive subroutine quicksort(iitem, s, t)
implicit integer (a-z)
dimension iitem(30)
integer s, t 
integer  k  
if(s.lt.t) then
call quickpass(iitem, s, t, k)
!$OMP PARALLEL SECTIONS
!$OMP section
call quicksort(iitem, s, k - 1)
!$OMP section
call quicksort(iitem, k + 1, t)
!$OMP END PARALLEL SECTIONS
endif
end subroutine

subroutine quickpass(iitem, s, t, k)
implicit integer (a-z)
dimension iitem(30)
integer s, t 
integer  k  
integer pivot 
integer i, j 
         pivot = iitem(s) 
         i = s
         j = t
    do while(i.lt.j)
        do while(i.lt.j.and.iitem(j).ge.pivot)
        j = j - 1
        enddo
      iitem(i) = iitem(j)
            do while(i.lt.j.and.iitem(i).le.pivot)
            i = i + 1
            enddo
          iitem(j) = iitem(i)
        enddo
                iitem(i) = pivot
                k = i
end subroutine

回复列表 (共3个回复)

沙发

快速排序我不熟悉, 就并行代码说两句吧
1. 你要排序的数据不多, 开启线程和关闭线程的开销恐怕都多于代码的运作.
2. 不知道你openmp的环境变量怎么取的, 有没有开嵌套并行? 或者开了嵌套并行到几级? 因为你用的是递归函数, 自己调用自己又会开启2个线程. 线程开得多并不离, 况且开关线程是有代价的.

板凳

对,问题也许就在递归函数,如果处理大量数据,会产生大量线程,导致每个线程只处理一些低级工作(如两个数据的交换等),反而非常耗时。

我只开了两个线程( OMP_NESTED=TRUE OMP_NUM_THREADS=2),因为只有两个并行区,即使这样也已产生问题。

以下是不采用递归函数的快速排序,各位高手看看能否并行化以节约大量时间用于处理大量数据?

      program sortstack
      INTEGER nndim
      INTEGER indx(30)    
      INTEGER Rij(30)
      INTEGER wksp(30)
    
      DATA Rij/0, 10, 20, 30, 40, 50, 60, 100, 200, 500,&
            600, 610, 210, 225, 200, 100, 111, 210, 225, 255,&
            1, 7, 3, 5, 11, 23, 29, 18, 9, 14/

      nndim=30

!     sort array Rij

      call sort3(nndim,Rij,wksp,indx) 
      PRINT *,Rij   

      end program sortstack


      SUBROUTINE sort3(n,ra,wksp,iwksp)

      INTEGER n,iwksp(n),j

      INTEGER ra(n),wksp(n)

      call indexx(n,ra,iwksp)

      do j=1,n

        wksp(j)=ra(j)

      enddo

      do j=1,n

        ra(j)=wksp(iwksp(j))

      enddo

      return

      END

      SUBROUTINE indexx(n,arr,indx)

      INTEGER n,indx(n),M,NSTACK

      INTEGER arr(n)

      PARAMETER (M=7,NSTACK=50)

      INTEGER i,indxt,ir,itemp,j,jstack,k,l,istack(NSTACK)

      INTEGER a

      do j=1,n

        indx(j)=j

      enddo

      jstack=0

      l=1

      ir=n

1     if(ir-l.lt.M)then

        do j=l+1,ir

          indxt=indx(j)

          a=arr(indxt)

          do i=j-1,l,-1

            if(arr(indx(i)).le.a)goto 2

            indx(i+1)=indx(i)

          enddo

          i=l-1

2         indx(i+1)=indxt

        enddo

        if(jstack.eq.0)return

        ir=istack(jstack)

        l=istack(jstack-1)

        jstack=jstack-2

      else

        k=(l+ir)/2

        itemp=indx(k)

        indx(k)=indx(l+1)

        indx(l+1)=itemp

        if(arr(indx(l)).gt.arr(indx(ir)))then

          itemp=indx(l)

          indx(l)=indx(ir)

          indx(ir)=itemp

        endif

        if(arr(indx(l+1)).gt.arr(indx(ir)))then

          itemp=indx(l+1)

          indx(l+1)=indx(ir)

          indx(ir)=itemp

        endif

        if(arr(indx(l)).gt.arr(indx(l+1)))then

          itemp=indx(l)

          indx(l)=indx(l+1)

          indx(l+1)=itemp

        endif

        i=l+1

        j=ir

        indxt=indx(l+1)

        a=arr(indxt)

3       continue

          i=i+1

        if(arr(indx(i)).lt.a)goto 3

4       continue

          j=j-1

        if(arr(indx(j)).gt.a)goto 4

        if(j.lt.i)goto 5

        itemp=indx(i)

        indx(i)=indx(j)

        indx(j)=itemp

        goto 3

5       indx(l+1)=indx(j)

        indx(j)=indxt

        jstack=jstack+2

        if(jstack.gt.NSTACK)pause 'NSTACK too small in indexx'

        if(ir-i+1.ge.j-l)then

          istack(jstack)=ir

          istack(jstack-1)=i

          ir=j-1

        else

          istack(jstack)=j-1

          istack(jstack-1)=l

          l=i

        endif

      endif

      goto 1

      RETURN
      END

3 楼

原始的代码如果设置OMP_NESTED=FALSE会不会有性能提升? 楼上的代码用goto会比较晕...
还有应该有并行的快速排序算法吧? 而且快速排序这类函数我在一些书上看到过有库函数可以调用.

我来回复

您尚未登录,请登录后再回复。点此登录或注册