我试图用openmp对我的合并排序实现进行基准测试。我写了下面的代码。openmp并行部分基准
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <omp.h>
using namespace std;
class Sorter {
private:
int* data;
int size;
bool isSorted;
public:
Sorter(int* data, int size){
this->data = data;
this->size = size;
this->isSorted = false;
}
void sort(){
vector<int> v(data,data+size);
vector<int> ans = merge_sort(v);
copy(ans.begin(),ans.end(),data);
isSorted = true;
}
vector<int> merge_sort(vector<int>& vec){
if(vec.size() == 1){
return vec;
}
std::vector<int>::iterator middle = vec.begin() + (vec.size()/2);
vector<int> left(vec.begin(), middle);
vector<int> right(middle, vec.end());
#pragma omp parallel sections
{
#pragma omp section
{left = merge_sort(left);}
#pragma omp section
{right = merge_sort(right);}
}
return merge(vec,left, right);
}
vector<int> merge(vector<int> &vec,const vector<int>& left, const vector<int>& right){
vector<int> result;
unsigned left_it = 0, right_it = 0;
while(left_it < left.size() && right_it < right.size()) {
if(left[left_it] < right[right_it]){
result.push_back(left[left_it]);
left_it++;
}else{
result.push_back(right[right_it]);
right_it++;
}
}
while(left_it < left.size()){
result.push_back(left[left_it]);
left_it++;
}
while(right_it < right.size()){
result.push_back(right[right_it]);
right_it++;
}
return result;
}
int* getSortedData(){
if(!isSorted){
sort();
}
return data;
}
};
void printArray(int* array, int size){
for(int i=0;i<size;i++){
cout<<array[i]<<", ";
}
cout<<endl;
}
bool isSorted(int* array, int size){
for(int i=0;i<size-1;i++){
if(array[i] > array[i+1]) {
cout<<array[i]<<" > "<<array[i+1]<<endl;
return false;
}
}
return true;
}
int main(int argc, char** argv){
if(argc<3){
cout<<"Specify size and threads"<<endl;
return -1;
}
int size = atoi(argv[1]);
int threads = atoi(argv[2]);
//omp_set_nested(1);
omp_set_num_threads(threads);
cout<<"Merge Sort of "<<size<<" with "<<omp_get_max_threads()<<endl;
int *array = new int[size];
srand(time(NULL));
for(int i=0;i<size;i++){
array[i] = rand() % 100;
}
//printArray(array,size);
Sorter* s = new Sorter(array, size);
cout<<"Starting sort"<<endl;
double start = omp_get_wtime();
s->sort();
double stop = omp_get_wtime();
cout<<"Time: "<<stop-start<<endl;
int* array2 = s->getSortedData();
if(size<=10)
printArray(array2,size);
cout<<"Array sorted: "<<(isSorted(array2,size)?"yes":"no")<<endl;
return 0;
}
该程序运行正常,但是当我指定线程数为4时,程序仍然只创建2个线程。我尝试在omp_set_num_threads(线程)之前使用omp_set_nested(1),但是它交给整个终端,直到程序崩溃并且说“libgomp:线程创建失败:资源暂时不可用”我想因为创建了太多的线程?我还没有找到一个工作。
编辑: 程序崩溃后,我检查系统负载,它显示负载超过1000! 我有一个4芯AMD A8 CPU和RAM 10GB如果 我去掉omp_set_nested(1)和运行该程序
$ ./mergeSort 10000000 4
Merge Sort of 10000000 with 4
Starting sort
libgomp: Thread creation failed: Resource temporarily unavailable
libgomp: Thread creation failed: Resource temporarily unavailable
$ uptime
02:14:12 up 1 day, 11:13, 4 users, load average: 482.21, 522.87, 338.75
观看的方法中,我可以当场被发射4个线程。如果我注释掉omp_set_nested(1)程序正常运行但只使用2个线程
编辑: 如果我使用任务并删除omp_set_nested,那么它会正确启动线程,但它不会加快速度。使用1个线程执行速度比使用4快。使用部分,速度会加快。但只有小于两个因素(因为它一次只能启动2个线程)
它确实会使用最多4个线程,但是如果您查看系统进程,您会看到它只创建2个线程。我会研究任务。 – kalgecin 2014-12-07 17:25:26
如果我使用任务并删除omp_set_nested,那么它会正确启动线程,但不会加快速度。使用1个线程执行速度比使用4快。使用部分,速度会加快。但只有小于2的因子(因为它一次只能启动2个线程) – kalgecin 2014-12-07 17:33:11
尽量不要产生多个线程,你可以为数组大小设置一个阈值 #pragma omp task if(end -begin> threshold ) – itsnevertoobadtoaskforhelp 2014-12-08 12:11:39