簡體   English   中英

嘗試與OpenMP並行處理鏈接列表數據

[英]Trying to process linked list data in parallel with OpenMP

我正在嘗試在C ++中與OpenMP並行處理鏈表數據。 我對OpenMP還是很陌生,對C ++卻很生疏。 我想要做的是讓幾個線程分解鏈表,並輸出其特定范圍內的節點數據。 我不在乎輸出發生的順序。 如果可以正常工作,我想用對Node數據的一些實際處理來替換簡單的輸出。

我在互聯網上找到了幾樣東西(包括本網站上的一些問題),從我發現的內容中,我整理了如下代碼:

        #include <iostream>
        #include <omp.h>

        // various and sundry other stuff ...

        struct Node {
                int data;
                Node* next;
        };

        int main() {

            struct Node *newHead;
            struct Node *head = new Node;
            struct Node *currNode;
            int n;
            int tid;

            //create a bunch of Nodes in linked list with "data" ...

            // traverse the linked list:
            // examine data
            #pragma omp parallel private(tid)
            {
            currNode = head;
            tid=omp_get_thread_num();
            #pragma omp single
            {
            while (currNode) {
               #pragma omp task firstprivate(currNode)
               {
               cout << "Node data: " << currNode->data << " " << tid << "\n";
               } // end of pragma omp task
               currNode = currNode->next;
            } // end of while
            } //end of pragma omp single

            }  // end of pragma omp parallel


    // clean up etc. ...

    }  // end of main

所以我跑:

>: export OMP_NUM_THREADS=6
>: g++ -fopenmp ll_code.cpp
>: ./a.out

輸出為:

Node data: 5 0
Node data: 10 0
Node data: 20 0
Node data: 30 0
Node data: 35 0
Node data: 40 0
Node data: 45 0
Node data: 50 0
Node data: 55 0
Node data: 60 0
Node data: 65 0
Node data: 70 0
Node data: 75 0

因此,tid始終為0。這意味着,除非我真的誤解了什么,否則只有一個線程對鏈表進行了任何操作,因此鏈表完全沒有並行遍歷。

當我擺脫single ,代碼會因seg錯誤而失敗。 我嘗試將一些變量移入和移出OpenMP指令范圍,而沒有進行任何更改。 更改線程數無效。 如何使它起作用?

次要問題:有些網站說firstprivate(currNode)是必要的和別人說currNodefirstprivate默認。 誰是對的?

您當然可以使用多個線程來遍歷一個鏈表,但是它實際上比僅使用一個線程要慢。

原因是,要知道節點N != 0的地址,必須知道節點N-1的地址。

現在假設您有N線程,每個線程負責“從i位置開始”。 上面的段落暗示線程i將取決於線程i-1的結果,而線程i-1的結果將取決於線程i-2的結果,依此類推。

無論如何,最終結果是串行遍歷。 但現在,而不是只是一個簡單for ,你必須得同步線程,使事情本身更慢。

但是,如果您要進行一些繁重的處理以從並行運行中受益,那么可以,您會選擇正確的方法。 您可以更改獲取線程ID的方式:

#include <iostream>
#include <omp.h>

struct Node {
        int data;
        Node* next;
};

int main() {

    struct Node *head = new Node;
    struct Node *currNode = head;

    head->data = 0;
    for (int i=1;i<10;++i) {
        currNode->next = new Node;
        currNode = currNode->next;
        currNode->data = i;
    }

    // traverse the linked list:
    // examine data
    #pragma omp parallel
    {
        currNode = head;
        #pragma omp single
        {
            while (currNode) {
               #pragma omp task firstprivate(currNode)
               {
                   #pragma omp critical (cout)
                   std::cout << "Node data: " << currNode->data << " " << omp_get_thread_num() << "\n";
               }
               currNode = currNode->next;
            }
        }
    }
}

可能的輸出:

Node data: 0 4
Node data: 6 4
Node data: 7 4
Node data: 8 4
Node data: 9 4
Node data: 1 3
Node data: 2 5
Node data: 3 2
Node data: 4 1
Node data: 5 0

現場觀看!

最后,對於更慣用的方法,請考慮使用std :: forward_list

#include <forward_list>
#include <iostream>
#include <omp.h>

int main() {

    std::forward_list<int> list;
    for (int i=0;i<10;++i) list.push_front(i);

    #pragma omp parallel
    #pragma omp single
    for(auto data : list) {
       #pragma omp task firstprivate(data)
       #pragma omp critical (cout)
       std::cout << "Node data: " << data << " " << omp_get_thread_num() << "\n";
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM