How do I parallelize a for loop through a C++ std::list using OpenMP?

前端 未结 5 1223
刺人心
刺人心 2020-12-01 06:25

I would like to iterate through all elements in an std::list in parallel fashion using OpenMP. The loop should be able to alter the elements of the list. Is there a simple s

5条回答
  •  旧时难觅i
    2020-12-01 07:14

    Here is a solution which allows inserting/removing new elements of a list in parallel.

    For a list with N elements we first cut the list into nthreads lists with roughly N/nthreads elements. In a parallel region this can be done like this

    int ithread = omp_get_thread_num();
    int nthreads = omp_get_num_threads();
    int t0 = (ithread+0)*N/nthreads;
    int t1 = (ithread+1)*N/nthreads;
    
    std::list l2;
    #pragma omp for ordered schedule(static)
    for(int i=0; i

    Where l2 is the cut list for each thread.

    Then we can act on each list in parallel. For example we can insert -1 every first position in the list like this

    auto it = l2.begin();
    for(int i=(t0+4)/5; i<(t1+4)/5; i++) {
        std::advance(it, 5*i-t0);
        l2.insert(it, -1);
    }
    

    Finally, after we are doing operating on the lists in parallel we splice the lists for each thread back to one list in order like this:

    #pragma omp for ordered schedule(static)
    for(int i=0; i

    The algorithm is essentially.

    1. Fast-forward through list sequential making cut lists.
    2. Act on cut lists in parallel adding, modifying, or removing elements.
    3. Splice the modified cut lists back together sequential.

    Here is a working example

    #include 
    #include 
    #include 
    #include 
    
    int main(void) {
      std::list l;
      for(int i=0; i<22; i++) {
        l.push_back(i);
      }
      for (auto it = l.begin(); it != l.end(); ++it) {
        std::cout << *it << " ";
      } std::cout << std::endl;
    
      int N = l.size();
      #pragma omp parallel
      {
        int ithread = omp_get_thread_num();
        int nthreads = omp_get_num_threads();
        int t0 = (ithread+0)*N/nthreads;
        int t1 = (ithread+1)*N/nthreads;
    
        //cut list into nthreads lists with size=N/nthreads
        std::list l2;
        #pragma omp for ordered schedule(static)
        for(int i=0; i

    Result

    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
    -1 0 1 2 3 4 -1 5 6 7 8 9 -1 10 11 12 13 14 -1 15 16 17 18 19 -1 20 21
    

提交回复
热议问题