1. 程式人生 > >多執行緒排序+快速排序

多執行緒排序+快速排序

多執行緒排序,主要是將整個排序的序列分成若干份,每一個執行緒排序一份,所以執行緒排序完成之後,就進行歸併,相當於多個有序序列合併成一個有序序列。

這裡就需要用到執行緒屏障,也就是 pthread_barrier 系列函式。

屏障,通俗的說就是一個比賽跑步的過程,所以隊員就緒了,才能進行比賽。

多執行緒排序也是,需要每個執行緒都是排序完成後,才能進行合併的過程。

程式碼:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <sys/time.h>
#include <pthread.h>
#include <algorithm>
using namespace std;

const long MAX = 10000000L;  //陣列中最大數
const long long MAX_NUM = 100000000L;  //排序數
const int thread = 4;       //執行緒數
const int thread_num = MAX_NUM / thread;  //每個執行緒排序的個數

int num[MAX_NUM];
int tmp_num[MAX_NUM];

pthread_barrier_t barrier;

/**
 * Initialized Data
 */
void init()
{
	srandom((int)time(NULL));
	for(int i = 0; i < MAX_NUM; ++i)
		num[i] = random() % MAX;
}

/**
 *quick sort function
 */
void qsorts(int *start, int *end)
{	
	int nums = end - start;
	if(nums > 0)
	{
		int index = 0;
		int flag = start[0];
		int i = 0, j = nums;
		while(i != j)
		{
			while(j > i && start[j] >= flag)
				--j;
			start[index] = start[j];
			index = j;
			while(i < j && start[i] <= flag)
				++i;
			start[index] = start[i];
			index = i;
		}
		start[index] = flag;
		qsorts(start, start + (i - 1));
		qsorts(start + j + 1, end);
	}
}

void* work(void *arg)  //執行緒排序函式
{
	long index = (long)arg;
	qsorts(num + index, num + index + thread_num - 1);
	pthread_barrier_wait(&barrier);
	pthread_exit(NULL);
}

void meger()        //最終合併函式
{
	long index[thread];
	for (int i = 0; i < thread; ++i)
	{
		index[i] = i * thread_num;
	}

	for(long i = 0; i < MAX_NUM; ++i)
	{
		long min_index;
		long min_num = MAX;
		for(int j = 0; j < thread; ++j)
		{
			if((index[j] < (j + 1) * thread_num) 
				&& (num[index[j]] < min_num))
			{
				min_index = j;
				min_num = num[index[j]];
			}
		}
		tmp_num[i] = num[index[min_index]];
		index[min_index]++;
	}
}

int main(int argc, char const *argv[])
{
	init();
	
	struct timeval start, end;
	pthread_t ptid;
	//printf("%ld %ld\n", num[1], num[2]);
	gettimeofday(&start, NULL);

	//init pthread and Thread barrier
	//add 1, total have (thread + 1) threads.
	pthread_barrier_init(&barrier, NULL, thread + 1);
	for(int i = 0; i < thread; ++i)
		pthread_create(&ptid, NULL, work, (void *)(i * thread_num));

	pthread_barrier_wait(&barrier);

	meger();
	// use one thread to sort
	// qsorts(num, num + MAX_NUM - 1);

	gettimeofday(&end, NULL);
	long long s_usec = start.tv_sec * 1000000 + start.tv_usec;
	long long e_usec = end.tv_sec * 1000000 + end.tv_usec;

	double useTime = (double)(e_usec - s_usec) / 1000000.0;
	printf("sort use %.4f seconds\n", useTime);


	FILE *fp = fopen("result2.txt", "w+");
	for(long long i = 0; i < MAX_NUM; ++i)
		fprintf(fp, "%ld ", num[i]);

	return 0;
}

當使用單執行緒排序時:
sort use 34.0476 seconds

當使用2執行緒排序時:

sort use 19.7711 seconds
當使用4執行緒排序時:
sort use 16.0659 seconds

當使用8執行緒排序時:

sort use 16.8172 seconds

如果使用STL中的函式的sort,將會更快。