Dijkstra算法OpenMP比单线程慢

时间:2014-05-04 04:20:16

标签: c performance parallel-processing openmp

我正在尝试使用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;
                     }
                  }
               }
            }
         }
      }
   }

1 个答案:

答案 0 :(得分:1)

并行化并不总是获得更高性能的免费门票。我看到两件可能导致经济放缓的事情。

  1. 关键部分可能花费大量时间处理同步问题。我不完全熟悉在OpenMP中如何实现这些部分,但我的第一个猜测是他们使用互斥锁来锁定对该部分的访问。互斥锁的锁定/解锁并不是非常便宜,并且该操作比您想要执行的操作昂贵得多。另外,由于循环完全处于临界区,因此除了一个线程之外的所有线程都将等待临界区中的线程完成。从本质上讲,该循环仍将以串行方式完成,并增加了同步开销。

  2. 可能没有足够的顶点可以从并行化中受益。同样,启动线程不是免费的,并且开销可能远远大于获得的时间。随着顶点数量变小,这变得越来越明显。

  3. 我的猜测是,第一个问题是大多数减速发生的地方。缓解此问题的最简单方法是以串行方式执行此操作。其次,您可以尝试让每个线程仅在其自己的部分中找到最小值,并将它们与并行部分之后的串行进行比较。