我计划修改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秒。
是否有可能在不修改代码的情况下获得合适的版本?
提前谢谢。