我的mergesort算法使用OpenMP的速度较慢,如何使其比序列化表格的速度更快?

时间:2019-05-09 13:29:29

标签: c++ parallel-processing openmp mergesort

我正在研究并行编程,并在排序算法上对其进行测试。 我发现最简单的方法是使用OpenMP,因为它提供了一种实现线程的简单方法。 我进行了一项研究,发现其他人已经做了,然后尝试了一些代码。但是,当我在Linux上用perf stat -r 10 -d测试它时,我得到的时间比序列化的代码要糟(在某些情况下,它是两倍的时间)。 我尝试在数组上使用其他数量的元素,我使用的最大值是1.000.000个数字,就好像我使用了更多元素时会出错。


void merge(int aux[], int left, int middle, int right){
    int temp[middle-left+1], temp2[right-middle];
    for(int i=0; i<(middle-left+1); i++){
        temp[i]=aux[left+i];
    }
    for(int i=0; i<(right-middle); i++){
        temp2[i]=aux[middle+1+i];
    }
    int i=0, j=0, k=left;
    while(i<(middle-left+1) && j<(right-middle))
    {
        if(temp[i]<temp2[j]){
            aux[k++]=temp[i++];
        }
        else{
            aux[k++]=temp2[j++];
        }
    }
    while(i<(middle-left+1)){
        aux[k++]=temp[i++];
    }
    while(j<(right-middle)){
        aux[k++]=temp2[j++];
    }
}

void mergeSort (int aux[], int left, int right){
    if (left < right){
        int middle = (left + right)/2;
        omp_set_num_threads(2);
        #pragma omp parallel
        {

            #pragma omp sections
            {
                #pragma omp section
                    mergeSort(aux,left,middle); //call 1
                #pragma omp section
                    mergeSort(aux,middle+1,right); //call 2
            }
        }
        merge(aux,left,middle,right);
    }
}

int main(){
    generate_list(Vet, n);
    mergeSort(Vet, 0, n-1);

    return(0);
}

以下是我收到的结果:

OpenMP代码:

./mergeomp的性能计数器统计信息(运行10次):

         12,489169      task-clock (msec)         #    0,717 CPUs utilized            ( +-  3,58% )
                 8      context-switches          #    0,681 K/sec                    ( +-  6,62% )
                 0      cpu-migrations            #    0,000 K/sec                  
               167      page-faults               #    0,013 M/sec                    ( +-  0,79% )
   <not supported>      cycles                                                      
   <not supported>      instructions                                                
   <not supported>      branches                                                    
   <not supported>      branch-misses                                               
   <not supported>      L1-dcache-loads                                             
   <not supported>      L1-dcache-load-misses                                       
   <not supported>      LLC-loads                                                   
   <not supported>      LLC-load-misses                                             

           0,01743 +- 0,00211 seconds time elapsed  ( +- 12,10% )

序列化方式(简单代码):

./mergesort的性能计数器统计信息(运行10次):

          3,757053      task-clock (msec)         #    0,449 CPUs utilized            ( +-  0,72% )
                 1      context-switches          #    0,293 K/sec                    ( +- 16,32% )
                 0      cpu-migrations            #    0,000 K/sec                  
               139      page-faults               #    0,037 M/sec                    ( +-  0,34% )
   <not supported>      cycles                                                      
   <not supported>      instructions                                                
   <not supported>      branches                                                    
   <not supported>      branch-misses                                               
   <not supported>      L1-dcache-loads                                             
   <not supported>      L1-dcache-load-misses                                       
   <not supported>      LLC-loads                                                   
   <not supported>      LLC-load-misses                                             

          0,008375 +- 0,000276 seconds time elapsed  ( +-  3,29% )

我做错什么了吗?我正在使用-fopenmp标志对其进行编译,但不知道合并排序是否对并行化不好,或者我的linux虚拟机(我在VM Virtual Box计算机,PC上运行Ubuntu)具有Core I7处理器)配置不正确。

1 个答案:

答案 0 :(得分:0)

感谢所有我解决此问题的人。

首先,我没有在虚拟机上设置多核。

然后,我更改了sections的{​​{1}}构造。

我还在数组中使用了大量元素(200万个)。

最后,我添加了一个过滤器,以在数组小于“ n”个元素时停止使用并行性:

task

我发现1.000.000是“ n”的最佳数字,我的算法比顺序算法快2倍。