用Parallel_For进行并行快速排序
作者: Zhouweiming 周伟明 (32 篇文章) 日期: 五月 31, 2009 在 10:43 上午
用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%
从上面的性能数据可以充分看出,使用动态任务调度进行并行算法的效率之高是非常令人兴奋的。
相关多核文章:
10、多核编程的四层境界
12、多核查找-顺序查找也疯狂
13、多核编程文章汇总
14、多核中的动态任务调度
参考文献:
【1】 周伟明,多核分布式队列的实现:“偷”与“自私”的运用(1)
【2】 周伟明,《多核计算与程序设计》 ,华中科技大学出版社,2009.03.
【3】 Capi开源项目,链接:http://gforge.osdn.net.cn/projects/capi
【4】 Intel Thread Building Block(TBB)源代码, 链接:http://www.threadingbuildingblocks.org/