C++ 平行Dijkstra

C++ 平行Dijkstra,c++,parallel-processing,openmp,dijkstra,C++,Parallel Processing,Openmp,Dijkstra,我正在使用OpenMP制作Dijkstra算法的并行版本。我的代码由两部分组成。第一部分仅由一个线程(主线程)执行。此线程从列表中选择新节点。第二部分由其他线程执行。这些线程更改从源到其他节点的距离。不幸的是,我的代码中有一个错误,因为许多执行第二部分的线程中有一个突然“消失”。数据同步可能有问题,但我不知道在哪里。如果有人能告诉我哪里出了错,我将不胜感激。代码如下: map<int, int> C; map<int, int> S; map<int, int>

我正在使用OpenMP制作Dijkstra算法的并行版本。我的代码由两部分组成。第一部分仅由一个线程(主线程)执行。此线程从列表中选择新节点。第二部分由其他线程执行。这些线程更改从源到其他节点的距离。不幸的是,我的代码中有一个错误,因为许多执行第二部分的线程中有一个突然“消失”。数据同步可能有问题,但我不知道在哪里。如果有人能告诉我哪里出了错,我将不胜感激。代码如下:

map<int, int> C;
map<int, int> S;
map<int, int> D;
int init;
int nu;
int u;
int p = 3;//omp_get_num_threads();
int d;
int n = graph->getNodesNum();

#pragma omp parallel shared(n, C, d, S, init, nu, u, D, graph, p) num_threads(p)
{
    int myId = omp_get_thread_num();
    if (myId == 0)
    {
        init = 0;
        nu = 0;

        u = to;
        while (init < p - 1)
        {
        }

        while (u != 0)
        {
            S[u] = 1;
            while (nu < p - 1)
            {
            }
            u = 0;
            d = INFINITY;
            for (int i = 1; i <= p - 1; ++i)
            {
                int j = C[i];
                if ((j != 0) && (D[j] < d))
                {
                    d = D[j];
                    u = j;
                }
            }
            nu = 0; 
        }
    }
    else
    {
        for (int i=myId; i<=n; i += p-1)
        {
            D[i] = INFINITY;
            S[i] = 0;
        }

        D[u] = 0;

        ++init; 
        while (init < p-1)
        {
        }
        while (u != 0)
        {
            C[myId] = 0;
            int d = INFINITY;

            for (int i = myId; i<=n; i+=p-1)
            {
                if (S[i] == 0)
                {
                    if (i != u)
                    {
                        int cost = graph->getCostBetween(u, i);
                        if (cost != INFINITY)
                        {
                            D[i] = min(D[i], D[u] + cost);
                        }
                    }
                    if ((d > D[i])) 
                    {                           
                        d = D[i];
                        C[myId] = i;
                    }
                }
            }
            ++nu;
            while (nu != 0)
            {
            }   
        }
    }       
}
map C;
地图S;
地图D;
int init;
int nu;
国际大学;
int p=3//omp_get_num_threads();
int d;
int n=graph->getNodesNum();
#pragma omp并行共享(n,C,d,S,init,nu,u,d,graph,p)num_线程(p)
{
int myId=omp_get_thread_num();
如果(myId==0)
{
init=0;
nu=0;
u=至;
while(初始值对于(int i=1;i我不知道你有什么信息,但将一个不规则的、高度同步的算法与小任务并行化是一个最困难的并行问题之一。研究团队可以专注于这些任务,并获得有限的加速,或者没有加速。这些算法通常只适用于特定的体系结构这些都是为并行化量身定做的,并且通过适当地设计数据结构,消除了诸如错误共享等奇怪的开销

这样的算法需要花费大量的时间和精力来分析、度量和考虑

ww2.cs.fsu.edu/~flin/ppq_report.pdf

现在,关于你的直接问题,由于你的算法是高度同步的,而且任务很小,你正在经历数据竞争的副作用。从你的并行算法中删除这些是非常棘手的,这里没有人能帮你做到


因此,您首先要考虑的是可以帮助您检测数据竞争的工具,如Valgrind和Intel thread checker。

这听起来像是一种将固有的顺序算法并行化的糟糕方法。您为什么要这样做?将顶点传递给线程的成本应该大约等于更新成本。I必须准备并行版本,以证明当我们使用更多内核时,Dijkstra可以更快。我知道Dijkstra很难并行化,并且通常加速比低于1。但是我发现了一些信息,可以用加速比1,2-1,4实现该算法。我的代码以这种方式呈现,所以现在我想检测错误实现的“加速”取决于使用的并行处理器的数量,所以我不明白这些数字意味着什么。可能,加速取决于“密集度”这是一种非常细粒度的方法,因此您需要一个经过优化的实现来实现一个速度明显更快(如果更快的话)的版本顺序实现。至于你的实现,我不明白你的主线程在哪里分派顶点来放松其他线程。