Dijkstra的算法openmp奇怪行为
Dijkstra's algorithm openmp strange behavior
我正在尝试运行Dijkstra算法的openmp实现,我在这里下载了heather.cs.ucdavis.edu/~matlof/openmp/Dijkstra.c
例如,如果我再加一个从5到6的垂直线,使从第0个开始的路径穿过两个顶点,我的程序无法给出正确的结果,说第0个和第6个之间的距离是无限的:^(原因是什么?
#define LARGEINT 2<<30-1 // "infinity"
#define NV 6
// global variables, all shared by all threads by default
int ohd[NV][NV], // 1-hop distances between vertices
mind[NV], // min distances found so far
notdone[NV], // vertices not checked yet
nth, // number of threads
chunk, // number of vertices handled by each thread
md, // current min over all threads
mv; // vertex which achieves that min
void init(int ac, char **av)
{ int i,j;
for (i = 0; i < NV; i++)
for (j = 0; j < NV; j++) {
if (j == i) ohd[i][i] = 0;
else ohd[i][j] = LARGEINT;
}
ohd[0][1] = ohd[1][0] = 40;
ohd[0][2] = ohd[2][0] = 15;
ohd[1][2] = ohd[2][1] = 20;
ohd[1][3] = ohd[3][1] = 10;
ohd[1][4] = ohd[4][1] = 25;
ohd[2][3] = ohd[3][2] = 100;
ohd[1][5] = ohd[5][1] = 6;
ohd[4][5] = ohd[5][4] = 8;
for (i = 1; i < NV; i++) {
notdone[i] = 1;
mind[i] = ohd[0][i];
}
}
// finds closest to 0 among notdone, among s through e
void findmymin(int s, int e, int *d, int *v)
{ int i;
*d = LARGEINT;
for (i = s; i <= e; i++)
if (notdone[i] && mind[i] < *d) {
*d = ohd[0][i];
*v = i;
}
}
// for each i in [s,e], ask whether a shorter path to i exists, through
// mv
void updateohd(int s, int e)
{ int i;
for (i = s; i <= e; i++)
if (mind[mv] + ohd[mv][i] < mind[i])
mind[i] = mind[mv] + ohd[mv][i];
}
void dowork()
{
#pragma omp parallel // Note 1
{ int startv,endv, // start, end vertices for this thread
step, // whole procedure goes NV steps
mymd, // min value found by this thread
mymv, // vertex which attains that value
me = omp_get_thread_num(); // my thread number
#pragma omp single // Note 2
{ nth = omp_get_num_threads(); chunk = NV/nth;
printf("there are %d threadsn",nth); }
// Note 3
startv = me * chunk;
endv = startv + chunk - 1;
for (step = 0; step < NV; step++) {
// find closest vertex to 0 among notdone; each thread finds
// closest in its group, then we find overall closest
#pragma omp single
{ md = LARGEINT; mv = 0; }
findmymin(startv,endv,&mymd,&mymv);
// update overall min if mine is smaller
#pragma omp critical // Note 4
{ if (mymd < md)
{ md = mymd; mv = mymv; }
}
// mark new vertex as done
#pragma omp single
{ notdone[mv] = 0; }
// now update my section of ohd
updateohd(startv,endv);
#pragma omp barrier
}
}
}
int main(int argc, char **argv)
{ int i;
init(argc,argv);
dowork();
// back to single thread now
printf("minimum distances:n");
for (i = 1; i < NV; i++)
printf("%dn",mind[i]);
}
这里有两个问题:
如果线程的数量不能均匀地除以值的数量,那么这种工作划分
startv = me * chunk;
endv = startv + chunk - 1;
将保留最后的(NV - nth*(NV/nth))
元素,这将意味着距离保留在LARGEINT
。这可以通过多种方式进行修复;目前最简单的方法是将所有剩余的工作交给最后一个线程
if (me == (nth-1)) endv = NV-1;
(这会导致更多的负载不平衡,但这是让代码正常工作的合理开始。)
另一个问题是在设置notdone[]
之前遗漏了一个屏障
#pragma omp barrier
#pragma omp single
{ notdone[mv] = 0; }
这确保了只有在每个人都完成了他们的findmymin()
并更新了md
和mv
之后才更新notdone
并且启动updateohd()
。
请注意,在您开始使用的原始代码中很容易引入错误;所使用的全局变量使得推理变得非常困难。John Burkardt在他的网站上有一个更好的版本,可以在这里教授同样的算法,评论几乎非常好,也更容易追踪。
相关文章:
- 为什么这个运算符<重载函数对 STL 算法不可见?
- OpenMP阵列性能较差
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- OpenMP卸载说'fatal error: could not find accel/nvptx-none/mkoffload'
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- OpenMP:共享同一算法的单线程和多线程实现
- 在OpenMP中设计具有任务的算法
- Dijkstra的算法openmp奇怪行为
- 用于在C++中使用OpenMP的算法库
- C++ STL 算法(列表排序)OpenMP/多线程实现
- 在c++中使用OpenMP和Timsort算法
- 如何使用OpenMP / MPI实现并行Dijkstra算法
- 在虚拟机上运行openMp算法造成的性能损失
- 我在 OpenMP 中实现 Dijkstra 最短路径算法时可能存在的范围问题?