我正在使用OpenMP来实现并行版本的Dijkstra算法。我的代码由两部分组成。第一部分只由一个线程(master)执行。此线程从列表中选择新节点。第二部分由其他线程执行。这些线程改变从源到其他节点的距离。不幸的是,在我的代码中是错误的,因为执行第二部分的许多线程中的一个突然“消失”。可能数据同步有问题,但我不知道在哪里。如果有人能告诉我我的错误在哪里,我将不胜感激。代码如下:
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)
{
}
}
}
}}
发布于 2012-07-03 02:04:44
我不知道你有什么信息,但将一个不规则的、高度同步的算法与小任务并行化是人们可能遇到的最困难的并行问题之一。研究团队可以将自己投入到这些任务中,并获得有限的加速,或者一无所获。通常,这样的算法只适用于为并行化量身定做的特定体系结构,并且通过适当地设计数据结构,已经消除了诸如虚假共享之类的奇怪开销。
像这样的算法需要大量的时间和精力来分析、测量和考虑。例如,请参阅本文。
ww2.cs.fsu.edu/~flin/ppq_report.pdf
现在,关于你的直接问题,由于你的算法是高度同步的,任务很小,你正在经历数据竞争的副作用。从你的并行算法中删除这些将是非常棘手的,这里没有人能帮你做到这一点。
因此,您的第一个呼叫点是查看可帮助您检测数据竞争的工具,如Valgrind和Intel线程检查器。
https://stackoverflow.com/questions/11122786
复制相似问题