【发布时间】:2012-06-20 15:21:28
【问题描述】:
我正在使用 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)
{
}
}
}
}
}
【问题讨论】:
-
这听起来像是一种将固有的顺序算法并行化的糟糕方法。你为什么这样做?将顶点传递给线程的成本应该大约等于更新成本的成本。
-
我必须准备并行版本,以表明当我们使用更多内核时,Dijkstra 可以更快。我知道 Dijkstra 很难并行化,并且通常加速比低于 1。但是我发现一些信息表明有办法以加速 1,2-1,4 实现该算法。我的代码以这种方式呈现,所以此刻我想检测错误。
-
实现的“加速”取决于使用的并行处理器的数量,所以我不明白这些数字是什么意思。可能,加速取决于图形的“密度”以及您花费多少时间传递顶点。这是一种非常细粒度的方法,因此您需要一个经过精心调整的实现来实现一个明显更快(如果更快)w.r.t 的版本。顺序实现。至于你的实现,我不明白你的主线程在哪里调度顶点以放松到其他线程。
标签: c++ parallel-processing openmp dijkstra