c++ - 如何使用 OpenMP 改进归并排序算法?
问题描述
我正在尝试使用 OpenMP 改进我的代码执行时间。我正在研究并行性并测试不同的实现方式。
我尝试将我的数组分成 4 个,我想在 4 个内核中运行我的代码(每个部分都在一个内核中),然后合并所有内容。
因此,我将其切片并使用 : 运行 4 个 mergeSorts #pragma omp single nowait
,但我认为我没有以正确的方式进行操作,因为它仅使用了大约 1,5 个核心。我需要改变什么来满足我的需要?(对不起,我是 OpenMP 的新手,我是一名计算机科学专业的学生,我正在做这个作为课堂研究)。
此外,我的速度变慢了,因为我需要进行额外的合并,因为它分为四个部分(我的执行时间比简单的并行方式慢大约两倍。
这是我的完整代码(欢迎其他改进提示):
#include<iostream>
#include<fstream>
#include<algorithm>
#include "omp.h"
using namespace std;
int n = 60000000;
int * Vet = new int [60000000];
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;
#pragma omp task firstprivate (aux, left, middle)
mergeSort(aux,left,middle); //call 1
#pragma omp task firstprivate (aux, middle, right)
mergeSort(aux,middle+1,right); //call 2
#pragma omp taskwait
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();
int middle = n/2;
int middleLeft = (n) / 4;
int middleRight = 3 * (n) / 4;
#pragma omp parallel
{
#pragma omp single nowait
mergeSort(Vet, 0, middleLeft);
#pragma omp single nowait
mergeSort(Vet, middleLeft+1, middle);
#pragma omp single nowait
mergeSort(Vet, middle+1, middleRight);
#pragma omp single nowait
mergeSort(Vet, middleRight+1, n);
}
merge(Vet, 0, middleLeft, middle);
merge(Vet, middle+1, middleRight, n);
merge(Vet, 0, n/2, n);
//stopTime = clock();
cout<<is_sorted(Vet,Vet+n)<<endl;
//print(Vet, n);
//printf("\nSorted in (aprox.): %f seconds \n\n", (double)(stopTime-startTime)/CLOCKS_PER_SEC);
return(0);
}
解决方案
推荐阅读
- python-3.x - 如何使用单个索引和一系列索引从 numpy 数组中获取行
- python - Python DEAP 多处理示例
- javascript - 尽管使用 async/await 时使用 {new: true} 选项,Mongoose findOneAndUpdate 不返回更新的对象
- python-3.x - 如何通过获取另一个数据框的滚动 COLUMN 总计/总和来创建新的数据框?
- python - 如何从python中的文件中绘制大的Y值?
- python - os.system 和 mysql 恢复在 python unittest 中不起作用
- mysql - 如何根据一个id从多个mysql表中选择多个字段?
- python - 星号参数的类型提示
- java - 在 Spark 中运行现有的生产 Java 应用程序
- spring-boot - 从拥有超过 3 篇文章的用户中选择一个唯一的名称。春季数据,H2