2014-12-07 81 views
2

我试图用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个线程)

回答

0

我测试了你的代码,它确实创建了4个或更多的线程,并没有明确地表达你的意思。另外,我建议你将omp节更改为omp任务,按照定义,只有1个线程处理给定节,在递归调用中,你永远不会使用空闲线程。

+0

它确实会使用最多4个线程,但是如果您查看系统进程,您会看到它只创建2个线程。我会研究任务。 – kalgecin 2014-12-07 17:25:26

+0

如果我使用任务并删除omp_set_nested,那么它会正确启动线程,但不会加快速度。使用1个线程执行速度比使用4快。使用部分,速度会加快。但只有小于2的因子(因为它一次只能启动2个线程) – kalgecin 2014-12-07 17:33:11

+0

尽量不要产生多个线程,你可以为数组大小设置一个阈值 #pragma omp task if(end -begin> threshold ) – itsnevertoobadtoaskforhelp 2014-12-08 12:11:39