1. 程式人生 > >《多核程式設計》學習筆記:氣泡排序的並行實現

《多核程式設計》學習筆記:氣泡排序的並行實現

我們都知道氣泡排序的序列演算法的實現,非常簡單,兩個for迴圈即可實現,那麼並行演算法又如何實現呢?

先介紹一下演算法思想。

(1)序列演算法思想:從左至右依次比較相鄰的兩個資料,如果左邊的數比右邊的數大,則交換,這樣經過一輪變換後,最大的資料就會移到最右邊;然後第二輪只需比較剩餘的n-1個數即可,找到次最大的資料;依次類推,直到將這n個數據排好序。

下面是序列氣泡排序演算法的核心程式碼:

for(i=0;i<n-1;i++)	//n-1輪
	{
		for(j=0;j<n-i-1;j++)
		{
			if(array[j]>array[j+1])
			{
				tmp=array[j];
				array[j]=array[j+1];
				array[j+1]=tmp;
			}
		}
	}

(2)並行演算法思想:並行演算法可以使用奇偶排序是氣泡排序的並行化版本,其思想就是將氣泡排序的每輪操作分解成奇數位和偶數位上的比較、交換,且互不干擾,所以可以並行化。

//#include"stdafx.h"
#include<stdio.h>
#include<malloc.h>
#include<windows.h>
int* array;
bool flag=false;
void Exchange(int* j)		//比較並交換相鄰元素
{
	int b;
	int k=*((int* )j);
	if(array[k]>array[k+1])
	{
		b=array[k];
		array[k]=array[k+1];
		array[k+1]=b;
		flag=true;
	}
}
void Parallel_BubbleSort(int length)       //並行氣泡排序主體
{
	int i,j;
	int *tag=(int* )malloc(sizeof(int)*length);
	for(i=0;i<length;i++)
		tag[i]=i;
	HANDLE* h=(HANDLE* )malloc(sizeof(HANDLE)*(length/2));
	for(i=0;i<length;i++)
	{
		if(i%2==0)		//比較偶數位
		{
			
			for(j=0;j<length-1;j+=2)	//每迴圈一次,就建立一個交換執行緒
			{
                //建立執行緒函式
				h[j/2]=CreateThread(NULL,		
								0,
								(LPTHREAD_START_ROUTINE)Exchange,
								&tag[j],		//不能直接傳j,j值會改變
								0,
								NULL);			
				printf("建立偶數執行緒\n");
			}
			WaitForMultipleObjects((length-1)/2,h,TRUE,INFINITE);
		}
		else	//比較奇數位
		{
			for(j=1;j<length-1;j+=2)
			{
				h[(j-1)/2]=CreateThread(NULL,
									0,
									(LPTHREAD_START_ROUTINE)Exchange,
									&tag[j],
									0,
									NULL);
				printf("建立奇數執行緒\n");
			}
			WaitForMultipleObjects(length/2,h,TRUE,INFINITE);
			if(!flag)		//當一次偶一次奇之後,才能跳出
				break;
			flag=false;
		}
	}
}
void main()
{
	int i,length;
	printf("請輸入陣列長度:");
	scanf("%d",&length);
	if(length<0)
		printf("輸入錯誤!");
	else
	{
		array=(int* )malloc(sizeof(int)*length);		//建立動態陣列
		printf("請輸入陣列的值:");
		for(i=0;i<length;i++)
		{
			scanf("%d",&array[i]);
		}
		Parallel_BubbleSort(length);
		for(i=0;i<length;i++)
			printf("%d ",array[i]);
		printf("\n");
	}
}

上述程式碼,為了提高演算法效率,增加了一個標誌位flag,當最後陣列資料已經排好序,就跳出迴圈,而非迴圈最大的次數。

在兩個演算法前後加上clock()計時函式,比較執行時間發現:並行的奇偶排序演算法所花費的時間比序列演算法還要多,因為它建立執行緒非常頻繁,所消耗的時間相對來說比較大。