快排是一个很适合做并行的算法,因为一次划分相当于一次反归并,把数据划分为两个不相关的部分,可以并行处理。但是快排,包括归并排序都有一个缺点:并行度是变化的,而且最终会是1,即有一次迭代需要纯串行。经过一番思考,我拿出了一个改进版方案,由于对pthread不熟悉,还有懒,代码写的很烂。改进版见:pthread 快排 失败的优化版
本文是基础的快排并行化,用算法导论的快排伪码改成。可以通过一个给定值修改最大并行度,在未达到最大并行度时,并行处理下次迭代的两个分支:
#include "stdafx.h"
#include <iostream>
#include <pthread.h>
#include <cmath>
using namespace std;
double *array;
pthread_mutex_t num_lock=PTHREAD_MUTEX_INITIALIZER;
int num=16;
typedef struct para
{
long start;
long end;
long pivotIndex;
}para;
/*
traditional quick sort
*/
void *qsort(void* p)
{
long start=((para*)p)->start;
long end=((para*)p)->end;
long index=((para*)p)->pivotIndex;
//cout<<"ite"<<endl;
if(start>end-2)
{
return NULL;
}
double pivot=array[index];
long i=start-1;
for(long j=start;j<end;++j)
{
if(array[j]<pivot)
{
++i;
double tmp=array[i];
array[i]=array[j];
array[j]=tmp;
}
}
array[i+1]=pivot;
para pl;
pl.start=start;
pl.end=i+1;
pl.pivotIndex=rand()/RAND_MAX*(pl.end-pl.start)+pl.start;
pthread_t pid;
bool createNewThread=false;
pthread_mutex_lock(&num_lock);
if(num!=1)
{
--num;
createNewThread=true;
}
pthread_mutex_unlock(&num_lock);
if(createNewThread)
{
pthread_create(&pid,NULL,qsort,&pl);
}
else
{
qsort(&pl);
}
para pr;
pr.start=i+2;
pr.end=end;
pr.pivotIndex=rand()/RAND_MAX*(pr.end-pr.start)+pr.start;
qsort(&pr);
if(createNewThread)
{
pthread_join(pid,NULL);
pthread_mutex_lock(&num_lock);
++num;
pthread_mutex_unlock(&num_lock);
}
return NULL;
}
long testArray(double *array,long length)
{
for(long i=1;i<length;++i)
{
if(array[i-1]>array[i])
{
return i-1;
}
}
return -1;
}
int _tmain(int argc, _TCHAR* argv[])
{
long size=2000*10000;
cout<<size<<endl;
array=new double[size];
for(long i=0;i<size;++i)
{
array[i]=rand();
}
//test section
cout<<"start"<<endl;
clock_t st,et;
st=clock();
para p;
p.start=0;
p.end=size;
p.pivotIndex=rand()/RAND_MAX*(p.end-p.start)+p.start;
qsort(&p);
et=clock();
cout<<"end using "<<(double)(et-st)/CLOCKS_PER_SEC<<endl;
cout<<testArray(array,size);
cin>>array[0];
//end test
delete[] array;
return 0;
}
在4线程有最大的加速比,但是效果都不明显,最大1.17的加速比。
到16进程时,有大幅度的性能下滑(创建线程次数过多)。