[英]Dijkstra Algorithm OpenMP Slower than Single Thread
我正在尝试使用OpenMP并行化Dijkstra的算法,但串行版本的运行速度快了40倍。 我可能缺少一个概念或做错了什么。 我是并行和OpenMP的新手。 你能帮忙吗? 谢谢。
long* prev; // array of pointers to preceding vertices
long* dist; // array of distances from the source to each vertex
long* visited; // visited vertices, 0 if not visited, 1 otherwise
long** vSetDistance; // distance between i and j
void dijkstraAlgorithm(
long * prev,
long * dist,
long * visited,
long ** vSetDistance)
{
int i, j, min;
// Initialization: set every distance to INFINITY until we discover a path
for (i = 1; i <= numVertices; i++)
{
prev[i] = -1;
visited[i] = 0;
dist[i] = INFINITY;
}
// The distance from the source to the source is defined to be zero
dist[sourceVertex] = 0;
{
for (j = 1; j <= numVertices; j++)
{
min = -1;
#pragma omp parallel default(none) private(i, j) \
shared(min, visited, dist, prev, vSetDistance, numVertices)
{
/* This loop corresponds to sending out the explorers walking the paths,
* where the step of picking "the vertex, v, with the shortest path to s"
* corresponds to an explorer arriving at an unexplored vertex */
#pragma omp for
for (i = 1; i <= numVertices; i++)
#pragma omp critical
{
if (!visited[i] && ((min == -1) || (dist[i] <= dist[min])))
min = i;
}
visited[min] = 1; // visited = true
// relaxation
#pragma omp for
for (i = 1; i <= numVertices; i++)
{
if (vSetDistance[min][i])
{
if ((dist[min] + vSetDistance[min][i]) < dist[i])
{
dist[i] = dist[min] + vSetDistance[min][i];
prev[i] = min;
}
}
}
}
}
}
}
并行化并非总是免费获得更高性能的门票。 我看到可能导致减速的两件事。
关键部分可能花费大量时间来处理同步。 我并不完全了解这些部分在OpenMP中的实现方式,但我的第一个猜测是它们使用互斥锁来锁定对该部分的访问。 互斥锁并不是很便宜,锁定/解锁比您要执行的操作要昂贵得多。 另外,由于循环完全在关键部分中,因此除了一个线程外,所有线程都将只等待关键部分中的线程完成。 本质上,该循环仍将以串行方式完成,同时增加了同步开销。
可能没有足够的顶点可以从并行化中受益。 同样,启动线程不是免费的,并且开销可能比获得的时间大得多。 随着顶点数量变小,这一点变得越来越明显。
我的猜测是,第一个问题是大多数减速发生的地方。 减轻此问题的最简单方法是简单地以串行方式进行。 其次,您可以尝试让每个线程仅在自己的部分中找到最小值,然后在并行部分之后将它们串行比较。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.