Using openMP to get the index of minimum element parallelly

前端 未结 3 1539
时光取名叫无心
时光取名叫无心 2021-02-06 10:00

I tried to write this code

float* theArray; // the array to find the minimum value
int   index, i;
float thisValue, min;

index    = 0;
min = theArray[0];
#pragm         


        
3条回答
  •  无人共我
    2021-02-06 10:27

    Basic Idea

    This can be accomplished without any parellelization-breaking critical or atomic sections by creating a custom reduction. Basically, define an object that stores both the index and value, and then create a function that sorts two of these objects by only the value, not the index.

    Details

    An object to store an index and value together:

    typedef std::pair IndexValuePair;
    

    You can access the index by accessing the first property and the value by accessing the second property, i.e.,

    IndexValuePair obj(0, 2.345);
    unsigned int ix = obj.first;  // 0
    float val = obj.second; // 2.345
    

    Define a function to sort two IndexValuePair objects:

    IndexValuePair myMin(IndexValuePair a, IndexValuePair b){
        return a.second < b.second ? a : b;
    }
    

    Then, construct a custom reduction following the guidelines in the OpenMP documentation:

    #pragma omp declare reduction \
    (minPair:IndexValuePair:omp_out=myMin(omp_out, omp_in)) \
    initializer(omp_priv = IndexValuePair(0, 1000))
    

    In this case, I've chosen to initialize the index to 0 and the value to 1000. The value should be initialized to some number larger than the largest value you expect to sort.

    Functional Example

    Finally, combine all these pieces with the parallel for loop!

    // Compile with g++ -std=c++11 -fopenmp demo.cpp
    #include 
    #include 
    #include 
    
    typedef std::pair IndexValuePair;
    
    IndexValuePair myMin(IndexValuePair a, IndexValuePair b){
        return a.second < b.second ? a : b;
    }
    
    int main(){
    
        std::vector vals {10, 4, 6, 2, 8, 0, -1, 2, 3, 4, 4, 8};
        unsigned int i;
    
        IndexValuePair minValueIndex(0, 1000);
    
        #pragma omp declare reduction \
            (minPair:IndexValuePair:omp_out=myMin(omp_out, omp_in)) \
            initializer(omp_priv = IndexValuePair(0, 1000))
    
        #pragma omp parallel for reduction(minPair:minValueIndex)
        for(i = 0; i < vals.size(); i++){
    
            if(vals[i] < minValueIndex.second){
                minValueIndex.first = i;
                minValueIndex.second = vals[i];
            }
        }
    
        std::cout << "minimum value = " << minValueIndex.second << std::endl;   // Should be -1
        std::cout << "index = " << minValueIndex.first << std::endl;    // Should be 6
    
    
        return EXIT_SUCCESS;
    
    }
    

提交回复
热议问题