尝试与OpenMP并行处理链接列表数据

时间:2018-04-12 16:37:12

标签: c++ openmp singly-linked-list

我试图在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)是必要的,而其他人则说currNode默认为firstprivate。谁是对的?

1 个答案:

答案 0 :(得分:1)

您当然可以使用多个线程遍历链接列表,但实际上它比使用单个线程更慢。

原因是,要知道节点curl的地址,您必须知道节点vagrant@vagrant:/var/www/html$ curl -s localhost/test.sh | bash Enter SSC IP: 2.2.2.2 SSC IP: 2.2.2.2 的地址。

现在假设你有N != 0个帖子,每个人都负责“从N-1位置开始”。上面的段落暗示线程N将取决于线程i的结果,而线程i的结果又取决于线程i-1的结果,依此类推。

你最终得到的是一个串行遍历。但是现在,您不仅要简单地i-2,还必须同步线程,使事情本身变得更慢。

但是,如果你正在尝试做一些可以从并行运行中受益的繁重处理,那么是的,你会采用正确的方法。你可以改变你获得线程ID的方式:

for

可能的输出:

#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;
            }
        }
    }
}

See it live!

最后,对于更惯用的方法,请考虑使用std::forward_list

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