在C中使用openMP实现Djikstra的并行版本

时间:2016-11-06 22:21:25

标签: c multithreading openmp

我计划修改Djikstra算法,以便将其与openMP并行化。我知道有很多解决方案,但我无法更改代码。因此我只能添加编译指示。这是给定的代码。

double dijkstra(){

int shortest_dist;
int nearest_node;
double start,stop;

start = get_time();           //timer
tree[0] = 1;                  //tree table which contains every nodes  from the graph. If the value is 1 then the node has been treated

#pragma omp parallel private(shortest_dist, nearest_node) num_threads(nb) 
{

   #pragma omp for 
   for (int i = 1; i < num_nodes; i++)
       tree[i] = 0;

   //Get every distance of nodes connected to the beginning node
   #pragma omp for
   for (int i = 0; i < num_nodes; i++)
       min_distance[i] = get_distance(0,i);


   for (int step = 1; step < num_nodes; step++ ){

      shortest_dist = INF;
      nearest_node = -1;

      #pragma omp parallel for reduction(min : shortest_dist) num_threads(nb)
      for (int i = 0; i < num_nodes; i++){
          // find nearest node
          if ( !tree[i] && min_distance[i] < shortest_dist ){
              shortest_dist = min_distance[i];
              nearest_node = i;
          }
      }

      if ( nearest_node == - 1 ){
          fprintf(stderr,"Warning: Search ended early, the graph might not be connected.\n" );
          break;
      }

      #pragma omp single
      tree[nearest_node] = 1; 

      // Update every nodes
      for (int i = 0; i < num_nodes; i++)
          if ( !tree[i] ){
              int d = get_distance(nearest_node,i);
              if ( d < INF )
                  if ( min_distance[nearest_node] + d < min_distance[i] )
                      min_distance[i] = min_distance[nearest_node] + d;
          }     
   }
} 

 stop = get_time();
 return(stop-start);
}

这里的函数get_distance和direct_edge_struct结构:

struct direct_edge_struct {
  int destination_node;
  int weight;
  struct direct_edge_struct *next;
};

int get_distance(int node1, int node2){
  if (node1 == node2)
    return 0;
  struct direct_edge_struct *edge = nodes[node1];
  while (edge != NULL){
    if (edge->destination_node == node2)
      return edge->weight;
    edge = edge->next;
  }
  // node2 has not been found as a direct neighbour of node 1
  return INF;
}

我尝试使用#pragma omp critical而不是reduce(min)来恢复每个线程的最小值:

#pragma omp parallel for reduction(min : shortest_dist) num_threads(nb)

然而,运行时间非常长,因为使用临界区很昂贵。我知道在其他线程中创建线程是一个坏主意,但我使用此解决方案获得了0.13-0.14秒的运行时间,而顺序版本的运行时间约为0.15秒。 是否有可能在不修改代码的情况下获得合适的版本?
提前谢谢。

0 个答案:

没有答案