《多核程式設計》學習筆記:氣泡排序的並行實現
阿新 • • 發佈:2018-12-31
我們都知道氣泡排序的序列演算法的實現,非常簡單,兩個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()計時函式,比較執行時間發現:並行的奇偶排序演算法所花費的時間比序列演算法還要多,因為它建立執行緒非常頻繁,所消耗的時間相對來說比較大。