在OpenMP上的并行合并排序上的数组大小问题.如何将合并分类分类为更多任务

Array size problem on a parallelized Merge Sort on OpenMP. How can I divide a merge sort on more tasks?

本文关键字:合并 分类 多任务 并行 OpenMP 排序 数组 问题      更新时间:2023-10-16

我正在使用openMP进行拼图研究。我正在尝试将Mergesort划分为任务以获得更好的结果。

我已经通过任务完成了一个很好的结果,但是现在我试图在每个迭代中划分更多任务,因此我可以使用更多的CPU(在我的原始代码中,我使用的是每次递归约1,5 CPU(。

所以我将Mergesort分为四个,然后每个递归的两个呼叫,但是我遇到了不良数组的错误:

terminate called after throwing an instance of 'std::bad_array_new_length'
  what():  std::bad_array_new_length
Abortado (imagem do núcleo gravada)

我的代码在下面,在C

#include<iostream>
#include<fstream>
#include<algorithm>
#include "omp.h"
using namespace std;
int n = 10000;
int * Vet = new int [10000];
double startTime, stopTime;
void generate_list(int * x, int n) {
   int i,j,t;
   for (i = 0; i < n; i++)
     x[i] = i;
   for (i = 0; i < n; i++) {
     j = rand() % n;
     t = x[i];
     x[i] = x[j];
     x[j] = t;
   }
}
void merge(int aux[], int left, int middle, int right){
    int * temp = new int [middle-left+1];
    int * temp2 = new int[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 mergeSortSerial(int aux[], int left, int right){
    if (left < right){
        int middle = (left + right)/2;
        mergeSortSerial(aux,left,middle); //call 1
        mergeSortSerial(aux,middle+1,right); //call 2
        merge(aux,left,middle,right);
    }
}
void mergeSort (int aux[], int left, int right){
    if (left < right){
        if ((right-left) > 1000){
            int middle = (left+ right)/2;
            int middleleft = (left + right)/4;
            int middleright = right-middleleft;
           #pragma omp task firstprivate (aux)
                mergeSort(aux,left,middleleft); //call 1
            #pragma omp task firstprivate (aux)
                mergeSort(aux,middleleft+1,middle); //call 2
            #pragma omp task firstprivate (aux)
                mergeSort(aux,middle+1,middleright); //call 3
            #pragma omp task firstprivate (aux)
                mergeSort(aux,middleright+1,right); //call 4            
            #pragma omp taskwait
            merge(aux,left,middleleft,middle);
            merge(aux,middle+1,middleright,right);
            merge(aux,left,middle,right);
        } else{mergeSortSerial(aux, left, right);}
    }
}
void print(int aux[], int n)
{
    for(int i=0; i<n; i++)
        cout<<aux[i]<<" ";
    cout<<endl;
}

int main(){
    generate_list(Vet, n);
    omp_set_nested(1);
    omp_set_num_threads(4);
    //startTime = clock();
       #pragma omp parallel
   {
      #pragma omp single
        mergeSort(Vet, 0, n-1);
   }
    cout<<is_sorted(Vet,Vet+n)<<endl;
    return(0);
}

您对middleLeftmiddlerightmergeSort中的计算是错误的,并且可以在[leftright]范围之外给出值。例如,如果left为20,并且right为30,则middle为25,middleLeft 12和middleRight 18。

您想做的是:

middleLeft = left + (right - left) / 4;
middleRight = left + 3 * (right - left) / 4;