用Parallel_For进行并行快速排序

注:本文主要内容摘自笔者所著的《多核计算与程序设计》一书,略有修改,后续还会继续发布系列文章,如有需要,可以考虑将一下地址加入到您的浏览器收藏夹中:http://software.intel.com/zh-cn/blogs/category/multicore/

 

上一篇文章 用动态任务调度器实现Parallel_For 中,实现了Parallel_For()功能, Parallel_For()可以实现许多的并行区间处理功能,下面以并行快速排序为例来讲解如何使用Parallel_For()的功能。

要用Parallel_For()来进行并行快速排序,需要先继承CRange类来实现一个CQuickSortRange类,然后就可以将CQuickSortRange类的实例作为参数传给Parallel_For()进行并行快速排序。

CQuickSortRange类的定义如下:

template <class T>

class CQuickSortRange : public CRange {

private:

    T * m_pData;

    int  m_nBegin;

    int  m_nEnd;

public:

    CQuickSortRange(T *pDataArray, int nBegin, int nEnd);

    virtual CRange * Split();

};

 

CQuickSortRange类中,主要需要实现Split()功能。考虑到效率,当区间小于一定值时就用串行的快速排序来对区间进行排序,否则将区间拆分成两个更小的区间。

Split()的代码实现如下:

#define MIN_QUICKSORT_SIZE      512

 

template <class T>

CRange * CQuickSortRange<T>::Split()

{

    if ( m_nEnd - m_nBegin <= MIN_QUICKSORT_SIZE )

    {

        QuickSort(m_pData, m_nBegin, m_nEnd);

        return NULL;

    }

 

    int nMid = QuickSort_Split(m_pData, m_nBegin, m_nEnd);

 

    CQuickSortRange<T> *pRange = new CQuickSortRange<T>(m_pData, nMid+1, m_nEnd);

 

    m_nEnd = nMid - 1;

 

    return pRange;

}

 

Split()功能中,调用了QuickSort()函数和QuickSort_Split()函数,这两个函数的代码如下:

template <class T>

int QuickSort_Split(T *pData, int nBegin, int nEnd)

{

    T SelData;

    int nLow;

    int nHigh;

 

    nLow = nBegin;

    nHigh = nEnd;

 

    SelData = pData[nLow];

    while ( nLow < nHigh )

    {

        while ( (pData[nHigh] > SelData)  && (nLow != nHigh) )

        {

            --nHigh;

        }

        if ( nHigh != nLow )

        {

            pData[nLow] = pData[nHigh];

            ++nLow;

        }

 

        while ( ( pData[nLow] < SelData ) && (nLow != nHigh) )

        {

            ++nLow;

        }

        if ( nLow != nHigh )

        {

            pData[nHigh] = pData[nLow];

            --nHigh;

        }

    }

    pData[nLow] = SelData;

 

    return nLow;

}

 

template <class T>

void QuickSort(T *pData, int nBegin, int nEnd)

{

    int nMid = QuickSort_Split(pData, nBegin, nEnd);

    if ( nMid > nBegin )

    {

        QuickSort(pData, nBegin, nMid - 1);

    }

 

    if ( nEnd > nMid )

    {

        QuickSort(pData, nMid + 1, nEnd);

    }

}

 

下面代码演示了如何使用Parallel_For()CQuickSortRange类来进行快速排序。

#define QUICKSORT_DATA_SIZE     1000000

 

void main(void)

{

    int * pData = new int[QUICKSORT_DATA_SIZE];

 

    srand(time(NULL));

 

    int i;

    for (i = 0; i < QUICKSORT_DATA_SIZE; i++ )

    {

        pData[i] = rand();

    }

CQuickSortRange<int> *pRange

= new CQuickSortRange<int>(pData, 0, QUICKSORT_DATA_SIZE-1);

Parallel_For(pRange);

 

delete [] pData;

}

 相关的多核文章:

在一个双核2.66G CPU机器上,测试了100万个随机数的串行快速排序和并行快速排序,得到的性能情况大致如下(由于存在随机性,每次测试得到的时间可能有差距):

 

串行快速排序100万个随机数, 耗时 187ms

并行快速排序100万个随机数, 耗时 94ms

 

加速比为187 / 94 = 1.989

效率为:1.989 / 2 = 99.46%

 

从上面的性能数据可以充分看出,使用动态任务调度进行并行算法的效率之高是非常令人兴奋的。

你可能感兴趣的:(算法,浏览器)