利用 openmp 实现在intel多核系统上 基本排序算法性能比较

时间:2023-02-04 20:06:23

本文章因为参加投票,请大家转载时说明,谢谢。

投票地址:http://intel.csdn.net/multicoreblog/show.aspx?page=0 (请投对文章:),谢谢)

本篇文章通过使用 openMp 实现对基本排序算法的性能比较:

文章很简单,但是很实用,分别演示了如何使用 openMP 进行多核多线程程序开发,可以作为入门级朋友的

学习教材。如果想正确运行程序,您需要创建每个文件,同时命名一定要合适,否则您需要自己去重写

后面的 makefile 文件。

 

sorh.h 头文件

  1. //sort.h head file  
  2. #include <stdio.h>  
  3. #include <time.h>  
  4. #include <stdlib.h>  
  5.  
  6.  
  7. #include <omp.h>  
  8. #define NUM_THREADS 12  
  9. typedef  float  KeyType;  
  10. typedef  int KeyInt;  
  11. typedef struct LNode  
  12. {  
  13.     KeyType key;  
  14.     struct LNode* next;  
  15. }LNode;  

 

sort.c 文件 包含main 函数,相当于一个 client 实现对各个排序算法的并行调用。

这里采用了 openMp 指导语句 #pragma omp sections 实现结构块化,即把各个结构块划分到各自的线程上。实际上是一个 任务分配区(work-sharing sections)的概念。通过 #pragma omp parallel

#pragma omp sections 指导OpenMp编译器和运行时库将应用程序中标示出的结构化块分配到用于执行并行区域的一

组线程上。这段例子还是非常有用的。

  1. # sort.c  
  2. #include "sort.h"  
  3. /** 
  4. ** The program need assitant Functions  
  5. ** 
  6. **/  
  7. KeyType* randomCreat(int N);  
  8. void DisPlay(int N, KeyType *p);  
  9. int GetExponent(int N);  
  10. KeyInt* Dlta(int exponent);    //build Dlta array for ShellSort  
  11. void FindPrimes(int start, int end); //for Dlta Maybe this is a badlly method  
  12. int TestForPrime(int val); //for Dlta   
  13. void myKeyboardFunc( unsigned char key);  
  14.   
  15. /** 
  16. ** Bubble Sort Functions in Bubble.c 
  17. **/  
  18. KeyType* BubbleArgorithm(int N, KeyType *p);  
  19.   
  20. /** 
  21. **Merge Sort Functions   in  Merge.c 
  22. **/  
  23. KeyType* MMSort(int N, KeyType* p);  
  24. void MSort(KeyType *r1, KeyType *r2, int left, int m, int r);  
  25. void MergeSort(KeyType *r1, KeyType *r2, int left, int right);  
  26.   
  27. /** 
  28. **InsertSort  Functions in  InsertSort.c 
  29. **/  
  30. KeyType* InsertSort(int N, KeyType* p);  
  31.   
  32. /** 
  33. **ShellSort Functions   in ShellSort.c 
  34. **/  
  35. KeyType* ShellSort(KeyType* p, KeyInt* dlta, int t, int N);  
  36. void ShellInsert(KeyType* p, int dk, int N);  
  37.   
  38. /** 
  39. **QuickSort Functions   in QuickSort.c 
  40. **/  
  41.   
  42. KeyType* QuickSort(int N, KeyType* p);  
  43. KeyType Partition(KeyType* p, int low, int high);  
  44. void Qsort(KeyType* p, int low, int high);  
  45.   
  46. /** 
  47. **BucketSort Functions  in BucketSort.c 
  48. **/  
  49. LNode** Bucket(int N);  //create Bucket according to N  
  50. KeyType* BucketSort(LNode** bucket, KeyType* p, int N);  
  51.   
  52. int main(int argc, char *argv[])  
  53. {  
  54.    
  55.     clock_t start, stop;   
  56.     char any = 'c';  
  57.     KeyType *p0, *p1, *p2, *p3, *p4, *p5;  
  58.     LNode** bucket; //for BucketSort B【】  
  59.     int N, i; //The size is sorted.  
  60.       
  61.     if(argc < 2)  
  62.     {  
  63.         printf("Enter random size  N=");  
  64.         scanf_s("%d",&N);  
  65.           
  66.     }  
  67.     else  
  68.     {  
  69.         N = atoi(argv[1]);  
  70.     }  
  71. /** 
  72. ** create sorted random copy 
  73. **/  
  74. p0 = randomCreat(N);                    //p0 for Merge-sort  
  75. p1 = malloc(N*sizeof(KeyType));         //p1 for Bubble-sort  
  76. p2 = malloc(N*sizeof(KeyType));         //p2 for Insert-sort  
  77. p3 = malloc(N*sizeof(KeyType));         //p3 for Shell-sort  
  78. p4 = malloc(N*sizeof(KeyType));         //p4 for Quick-sort  
  79. p5 = malloc(N*sizeof(KeyType));         //p5 for Bucket-sort  
  80.   
  81. for( i=0; i<N; i++)  
  82. {  
  83.     p1[i] = p2[i] = p3[i] = p4[i] = p5[i] = p0[i];  
  84. }  
  85. //DisPlay(N, p0);  
  86. /** 
  87. ** Start testing method of sort. 
  88. ** Use OpenMP create threads deal with methods  
  89. ** 
  90. **/  
  91.   
  92.     #pragma omp parallel  
  93.     {  
  94.         #pragma omp sections nowait  
  95.         {  
  96.               
  97.             /** 
  98.                 ** Merge sort  
  99.                 **  
  100.                 **/  
  101.             #pragma omp section  
  102.             {  
  103.                 start = clock();  
  104.                 p0 = MMSort(N, p0);  
  105.                 stop = clock();     
  106.                 printf("/b/b/b/b/bThe MergeSort      elapsed time = %g seconds,  The threads num is %d/n  ", (double)(stop - start) / CLOCKS_PER_SEC,(int)omp_get_thread_num());  
  107.                 //DisPlay(N, p0);  
  108.                 free(p0);  
  109.             }  
  110.             /** 
  111.             ** Bubble sort 
  112.             **/  
  113.             #pragma omp section  
  114.             {  
  115.                 start = clock();  
  116.                 p1 = BubbleArgorithm(N, p1);  
  117.                 stop = clock();     
  118.                 printf("/b/b/b/bThe BubbleSort     elapsed time = %g seconds, The threads num is %d/n  ", (double)(stop - start) / CLOCKS_PER_SEC,(int)omp_get_thread_num());  
  119.                 //DisPlay(N, p1);  
  120.                 free(p1);  
  121.             }  
  122.   
  123.             /** 
  124.             ** Insert-sort   
  125.             **/  
  126.             #pragma omp section  
  127.             {  
  128.                  start = clock();  
  129.                  p2 = InsertSort(N, p2);  
  130.                  stop = clock();     
  131.                  printf("/b/b/b/bThe InsertSort     elapsed time = %g seconds,  The threads num is %d/n  ", (double)(stop - start) / CLOCKS_PER_SEC,(int)omp_get_thread_num());  
  132.                 // DisPlay(N, p2);  
  133.                  free(p2);  
  134.             }  
  135.                 /** 
  136.                 ** Shell-sort   
  137.                 **/  
  138.             #pragma omp section  
  139.             {  
  140.                  start = clock();  
  141.                  //According to N made dlta size and t size  
  142.                  p3 = ShellSort(p3, Dlta(GetExponent(N)), GetExponent(N), N);  
  143.                  stop = clock();     
  144.                  printf("/b/b/b/bThe Shellsort      elapsed time = %g seconds,   The threads num is %d/n ", (double)(stop - start) / CLOCKS_PER_SEC,(int)omp_get_thread_num());  
  145.                  //DisPlay(N, p3);  
  146.                  free(p3);    
  147.             }  
  148.             /** 
  149.             ** Quick-sort   
  150.             **/  
  151.             #pragma omp section  
  152.             {  
  153.                 start = clock();  
  154.                 p4 = QuickSort(N, p4);  
  155.                 stop = clock();     
  156.                 printf("/b/b/b/bThe QuickSort      elapsed time = %g seconds,  The threads num is %d/n ", (double)(stop - start) / CLOCKS_PER_SEC,(int)omp_get_thread_num());  
  157.                 //DisPlay(N, p4);  
  158.                 free(p4);     
  159.             }  
  160.             /** 
  161.             ** BucketSort  
  162.             **/  
  163.             #pragma omp section  
  164.             {  
  165.                 start = clock();  
  166.                 bucket = Bucket(N);  
  167.                 p5 = (KeyType*)FindBucket(N, p5, bucket);  
  168.                 stop = clock();     
  169.                 printf("/b/b/b/bThe BucketSort     elapsed time = %g seconds,  The threads num is %d/n ", (double)(stop - start) / CLOCKS_PER_SEC,(int)omp_get_thread_num());  
  170.                 //DisPlay(N, p5);  
  171.                 free(p5);     
  172.             }  
  173.   
  174.         }  
  175.   
  176.     }  
  177.       
  178. printf("/b/b/b/b/b/bPlease press /"q/" to quit program ..................!!!/n");  
  179.   
  180.   // any = getchar();  
  181.    while(1)  
  182.     {  
  183.        if(getchar()=='q')  
  184.          return 0;  
  185.     }  
  186. }  

  1. // bubble.c 实现冒泡排序  
  2. #include "sort.h"  
  3.   
  4. /** 
  5. * bubbel argorithm    
  6. * 第一次循环将最大的数放到最后,后面循环依次类推。 
  7. */  
  8.   
  9. KeyType* BubbleArgorithm(int N, KeyType *p)  
  10. {  
  11.    int i, j;  
  12.    KeyType temp;  
  13.    for(i=0; i<N; i++)  
  14.        for(j=N-1; j>i; j--)  
  15.            if(p[j]<p[j-1])  
  16.            {  
  17.                temp = p[j-1];  
  18.                p[j-1] = p[j];  
  19.                p[j] = temp;  
  20.            }  
  21.    return (p);  
  22. }  

 

buctet.c 文件实现 桶排序

  1. #include "sort.h"  
  2. /** 
  3. **According to N create B[N] for bucket 
  4. **/  
  5. LNode** Bucket(int N)  
  6. {  
  7.     int i=0;  
  8.       
  9.     LNode  *q, **p;  
  10.     p = malloc(N*sizeof(LNode*));  
  11.     //initialization p using OpenMP  
  12.     #pragma omp parallel for private(i)  
  13.     for(i=0; i<N; i++)  
  14.     {  
  15.         q = malloc(sizeof(LNode*));  
  16.         q -> key = 0.0;  
  17.         q -> next = NULL;  
  18.         p[i] = q;  
  19.     }  
  20.       
  21.     return (p);  
  22. }  
  23. //Function is insert a Node to a order LinkList  
  24. KeyType* FindBucket(int N, KeyType* p, LNode** q)  
  25. {  
  26.     int i, j=0;  
  27.     long tmp;  
  28.     LNode *ele;  
  29.     KeyType* finall;  
  30.     for(i=0; i<N; i++)  
  31.     {  
  32.         tmp = (long)(p[i] * N);  
  33.         ele = malloc(sizeof(LNode*));  
  34.         ele->key = p[i];  
  35.         ele->next = NULL;  
  36.         q[tmp]->next = (LNode*)LinkInsert(q[tmp]->next, ele);  
  37.     }  
  38.   
  39.     finall = malloc(N*sizeof(KeyType));     
  40.     for(i=0; i<N; i++)  
  41.     {  
  42.         while(q[i]->next)  
  43.         {  
  44.                 finall[j]= q[i] -> next -> key;  
  45.                 q[i] ->next = q[i] -> next->next;  
  46.                 j++;  
  47.         }  
  48.     }    
  49.     return (finall);  
  50. }  
  51. //Function is insert a Node to a order LinkList  
  52. LNode* LinkInsert(LNode *LinkList, LNode *p)  
  53. {  
  54.     LNode *current, *head;  
  55.   
  56.     current = LinkList;  
  57.     head = NULL;      
  58.     while((current != NULL) && (current->key < p->key))  
  59.     {  
  60.             head = current;  
  61.             current = current->next;  
  62.     }  
  63.     p->next = current;  
  64.     if( head == NULL )  
  65.     {  
  66.         current = p;  
  67.         return current;  
  68.     }  
  69.     else  
  70.     {  
  71.         head->next = p;  
  72.         return head;  
  73.     }  
  74. }  

 

InsertSort.c

  1. #include "sort.h"  
  2.   
  3. /** 
  4. ** @function:   Insert sort 
  5. ** @ 
  6. **/  
  7. KeyType* InsertSort(int N, KeyType* p)  
  8. {  
  9.    int i, j;  
  10.    KeyType tmp;  
  11.    for(i=0; i<N-1; ++i)  
  12.     {  
  13.        if(p[i+1] < p[i])  
  14.         {  
  15.            tmp = p[i+1];  
  16.            p[i+1] = p[i];  
  17.            for(j = i; tmp < p[j]; --j)  
  18.                p[j+1] = p[j];  
  19.            p[j+1] = tmp;  
  20.         }         
  21.     }  
  22.    return (p);  
  23. }  

 

Merge.c

  1. #include "sort.h"  
  2.   
  3.   
  4. /** 
  5. ** 
  6. ** mSort  
  7. **  
  8. ** i is left  j is middle k is left 
  9. ** 
  10. */  
  11. void MSort(KeyType *r1, KeyType *r2, int left, int m, int r)  
  12. {  
  13.     int i = left, j = m + 1,  k = left;  
  14.   
  15.     while((i <= m)&&(j <= r))  
  16.     {  
  17.         if(r1[i] <= r1[j])  
  18.         {  
  19.             r2[k++] = r1[i++];  
  20.   
  21.         }  
  22.         else  
  23.         {  
  24.             r2[k++] = r1[j++];  
  25.         }  
  26.     }//end while   
  27.       
  28.     //将剩余的人r1 内容复制到 r2 中  
  29.     while(i <= m)  
  30.     {  
  31.         r2[k++] = r1[i++];  
  32.     }      
  33.     //将剩余的人r1 内容复制到 r2 中  
  34.     while(j <= r)  
  35.     {  
  36.         r2[k++] = r1[j++];  
  37.     }  
  38.   
  39.     //修改r1内容  
  40.     for(k=1; k <= r; k++)  
  41.     {  
  42.         r1[k] = r2[k];  
  43.     }  
  44. }  
  45.   
  46. /**  
  47. * MergeSort 
  48. */  
  49. void MergeSort(KeyType *r1, KeyType *r2, int left, int right)  
  50. {  
  51.     int middle;   
  52.     if(left < right)  
  53.     {  
  54.         middle = ((left + right) >> 1);  
  55.         #pragma omp parallel  
  56.         {  
  57.             #pragma omp sections nowait  
  58.             {  
  59.                 #pragma omp section  
  60.                 MergeSort(r1, r2, left, middle);  
  61.                 #pragma omp section  
  62.                 MergeSort(r1, r2, middle + 1, right );    
  63.             }  
  64.               
  65.         }  
  66.         MSort(r1, r2, left, middle, right);  
  67.     }  
  68. }  
  69.   
  70. KeyType* MMSort(int N, KeyType *r)  
  71. {  
  72.     KeyType *tmp;  
  73.     if((tmp = malloc(N * sizeof(KeyType))))  
  74.     {  
  75.         MergeSort(r, tmp, 0, N-1);  
  76.         free(tmp);  
  77.         return (r);  
  78.     }  
  79.     else  
  80.     {  
  81.         printf("malloc is failed !!!");  
  82.         return (r);  
  83.     }  
  84. }  
  85.   
  86. //因为参与投票,文章版权所有请不要转发。 唐炜  

 

QuickSort.c  快速排序可以实用两个线程分别对各个待排序队列实现递归排序

  1. #include "sort.h"  
  2.   
  3. /** 
  4. **@function: QuickSort 
  5. **@author: Tang Wei 
  6. ** 
  7. **/  
  8. KeyType Partition(KeyType* p, int low, int high)  
  9. {  
  10.     KeyType tmp = p[low]; //pivotkey  
  11.     while(low < high)  
  12.     {  
  13.         while((low < high) && (p[high] >= tmp))   
  14.             --high;  
  15.         p[low] = p[high];  
  16.         while((low < high) && (p[low] <= tmp))  
  17.             ++low;  
  18.         p[high] = p[low];  
  19.     }  
  20.     p[low] = tmp;  
  21.     return low;   
  22. }  
  23.   
  24. void Qsort(KeyType* p, int low, int high)  
  25. {  
  26.     int pivotLocation;  
  27.     if(low < high)  
  28.     {  
  29.         pivotLocation = Partition(p, low, high);  
  30.         #pragma omp parallel   
  31.         {     
  32.             #pragma omp sections nowait  
  33.             {  
  34.                 #pragma omp section  
  35.                 Qsort(p, low, pivotLocation-1);  
  36.                 #pragma omp section  
  37.                 Qsort(p, pivotLocation+1, high);  
  38.             }  
  39.         }  
  40.     }  
  41. }  
  42. KeyType* QuickSort(int N, KeyType* p)  
  43. {  
  44.     Qsort(p, 0, N-1);  
  45.     return(p);  
  46. }  

 

rand.c

 

  1. #include "sort.h"  
  2.   
  3. /** 
  4. * 生成随即序列 
  5. * 
  6. */  
  7.   
  8.   
  9. KeyType* randomCreat(int N)  
  10. {  
  11.     int i=0;  
  12.     KeyType *p;  
  13.     p = malloc(N * sizeof(KeyType));  
  14.       
  15.     for(i=0; i<N; i++)  
  16.         p[i] = rand()/(RAND_MAX+1.0);   
  17.     return (p);  
  18. }  
  19.   
  20. void DisPlay(int N, KeyType *p)  
  21. {  
  22.     while(N>0)  
  23.         printf("/b/b/b/b/b/b/bp[%d]:=%f/n",N, p[--N]);  
  24. }  
  25. void myKeyboardFunc( unsigned char key)  
  26. {  
  27.     switch ( key ) {  
  28.         case 'q':                    //****bobc  
  29.                 // exit program        
  30.                 exit(0);             //****bobc  
  31.     }  
  32. }  

 

ShellSort.c

 

  1. #include "sort.h"  
  2. static       int gProgress    = 0,  
  3.                  gPrimesFound = 0;  
  4. long             globalPrimes[20];  
  5.   
  6.   
  7. /** 
  8. **@function:   Shell Sort 
  9. **/  
  10. void ShellInsert(KeyType* p, int dk, int N)  
  11. {  
  12.     int i, j;  
  13.     KeyType tmp;  
  14.     for(i = dk + 1; i < N; ++i)  
  15.     {  
  16.         if(p[i] < p[i - dk])  
  17.         {  
  18.             tmp = p[i];  
  19.             for(j = i - dk; j>0 && (tmp < p[j]); j-=dk)  
  20.                 p[j + dk] = p[j];  
  21.             p[j + dk] = tmp;  
  22.         }  
  23.     }  
  24. }  
  25.   
  26. KeyType* ShellSort(KeyType* p, KeyInt* dlta, int t, int N)  
  27. {  
  28.     int k;  
  29.     for(k = 0; k < t; ++k)  
  30.         ShellInsert(p, dlta[k], N);  
  31.     free(dlta);  
  32.     return (p);  
  33. }  
  34. /** 
  35. ** 
  36. ** First, calculate t for dlat[]  
  37. ** Second, insert dlta[] with primes numbers 
  38. ** Third, return dlta 
  39. */  
  40. int GetExponent(int N)  
  41. {  
  42.     int exponent = (int)(log10(N)/log10(2));  
  43.     return exponent;  
  44. }  
  45. int* Dlta(int exponent)  
  46. {  
  47.     //int exponent = (int)(log10(N)/log10(2));  
  48.     KeyInt* p;  
  49.     int i;  
  50.     p = malloc(exponent*sizeof(KeyInt));  //assign space for dlta;  
  51.     FindPrimes(1, 100);  
  52.     for(i=0; i<exponent-1; i++)  
  53.     {  
  54.         //printf("i: =%d,  exponent-2-i=%d, globalPrimes[exponent-1-i]:=%d/n", i,exponent-1-i, globalPrimes[exponent-i]);  
  55.         p[i] = globalPrimes[exponent-i];  
  56.     }  
  57.     p[exponent-1] = 1;  
  58.     return (p);  
  59. }  
  60.   
  61. /** 
  62.   这是采用分别取线程号的方法实现并行 
  63. */  
  64. void FindPrimes(int start, int end)  
  65. {  
  66. int i, k;  
  67. omp_set_num_threads(NUM_THREADS);  
  68.   
  69. if (start <= 2) globalPrimes[gPrimesFound++] = 2;  
  70. #pragma omp parallel for private(i)  
  71.         for(i = start; i <= end; i += 2 )  
  72.         {  
  73.             if( TestForPrime(i) )  
  74.             {  
  75.                 //这里需要设置临界区否则 globalPrimes[] 里面的内容不合适  
  76.                 #pragma omp critical  
  77.                 globalPrimes[gPrimesFound++] = i;  
  78.                 //printf("prime : %d/n", globalPrimes[gPrimesFound]);  
  79.             }  
  80.         }  
  81.   
  82. }  
  83.   
  84. int TestForPrime(int val)  
  85. {  
  86.     int limit, factor = 3;  
  87.   
  88.     limit = (long)(sqrtf((float)val)+0.5f);  
  89.     while( (factor <= limit) && (val % factor))  
  90.         factor ++;  
  91.   
  92.     return (factor > limit);  
  93. }  
  94. //因为参与投票,文章版权所有请不要转发。 唐炜  

 

MAKEFILE.mak  我这里建立了一个 program 包,将所有的文件放到这个目录里面,如果您不一样的话,请修改

makefile文件  CPP_PROJ = $(CFLAGS) /Qopenmp -c  ../program 内容 /Qopenmp 为打开Qopenmp选项,

编译器支持openMP,  ../program 为目录

 

  1. ##################################################################################  
  2. ########### You must use Intel C++ Compiler                            ###########  
  3. ########### C++ Build Environment for applications running on IA-32    ###########  
  4. ########### command line> nmake /f MAKEFILE.mak                        ###########  
  5. ###########                                                            ###########  
  6. ##################################################################################  
  7.  
  8. ####### Compiler, tools and options  
  9. CPP=icl.exe  
  10. !IF "$(CPP)" == "icl.exe"  
  11. LINK=xilink.exe  
  12. !ELSE  
  13. LINK=link.exe  
  14. !ENDIF  
  15. CF       = -O3  
  16. LF       =   
  17. CFLAGS   = $(CF)    
  18. LFLAGS   = $(LF)  
  19. CPP_PROJ = $(CFLAGS) /Qopenmp -c  ../program  
  20. SRCS     =    *.cpp  
  21. OBJS     =    *.obj  
  22. TARGET   =    sort.exe  
  23.  
  24. ####### Files  
  25. SOURCES = sort.c rand.c Merge.c Bubble.c InsertSort.c Shellsort.c QuickSort.c BucketSort.c  
  26.   
  27. OBJECTS =  sort.obj rand.obj Merge.obj Bubble.obj InsertSort.obj ShellSort.obj QuickSort.obj BucketSort.obj  
  28.  
  29. ####### Implicit rules  
  30. .SUFFIXES: .cpp .cxx .cc .c  
  31.   
  32. .cpp.obj:  
  33.     $(CPP) -c $(CPP_PROJ) -Fo$@ $<  
  34.   
  35. .cxx.obj:  
  36.     $(CPP) -c $(CPP_PROJ) -Fo$@ $<  
  37.   
  38. .cc.obj:  
  39.     $(CPP) -c $(CPP_PROJ) -Fo$@ $<  
  40.   
  41. .c.obj:  
  42.     $(CPP) -c $(CPP_PROJ) -Fo$@ $<  
  43.  
  44.  
  45. ####### Build rules  
  46.   
  47. all: $(TARGET)  
  48. $(TARGET): $(OBJECTS) $(LIBS)   
  49.     $(LINK)  $(LFLAGS) $(LDFLAGS) /OUT:$(TARGET) $(LIBS) $(OBJECTS)   
  50.   
  51.   
  52.   
  53. clean:  
  54.     -@erase *.obj  
  55.     -@erase *.bak  
  56.     -@erase *.exe  
  57.  
  58. ####### Compile  
  59.   
  60. $(OBJECTS): $(SOURCES)  
  61.     $(CPP) -c $(CPP_PROJ) $(SOURCES)  
  62.  
  63.  
  64. ####### Libraries