繁体   English   中英

我在OpenMP中实现Dijkstra最短路径算法的范围可能有问题吗?

[英]Possible scope issues with my implementation of Dijkstra's shortest path algorithm in OpenMP?

我一直在研究一个小程序,该程序使用OpenMP在给定图中计算每个顶点的最短路径,从而将计算分成多个线程,而不是一次执行一个顶点。 在我当前的实现可行的同时,我想这样做,以便可以从文件中读取“ vertex1 vertex2 weight”格式的图形数据,这样图形就不会硬编码到程序中。

来源在这里: http : //pastebin.com/bkR7QysB

编译如下:

g++ -fopenmp GraphTest.cpp WeightedGraph.cpp -o dijkstra

使用以下数据作为输入:

foo derp 50
narf balls 30
foo balls 20
balls derp 60
derp narf 40
derp cox 30
foo narf 50
narf pie 99
cox pie 15
cox narf 10

我的输出是:

Enter filename: lol.out
Printing all edges currently in graph: 
(foo, derp) : cost 50
(narf, balls) : cost 30
(foo, balls) : cost 20
(balls, derp) : cost 60
(derp, narf) : cost 40
(derp, cox) : cost 30
(foo, narf) : cost 50
(narf, pie) : cost 99
(cox, pie) : cost 15
(cox, narf) : cost 10

[thread:0] Showing single-source shortest path run for source vertex balls. Format is (start, end) : cost.
(balls, balls : cost 0)
(balls, derp : cost 60)

[thread:0] Showing single-source shortest path run for source vertex cox. Format is (start, end) : cost.
(cox, cox : cost 0)
(cox, narf : cost 10)

[thread:1] Showing single-source shortest path run for source vertex derp. Format is (start, end) : cost.
(derp, derp : cost 0)
(derp, cox : cost 30)

[thread:1] Showing single-source shortest path run for source vertex foo. Format is (start, end) : cost.
(foo, foo : cost 0)
(foo, narf : cost 50)

[thread:2] Showing single-source shortest path run for source vertex narf. Format is (start, end) : cost.
(narf, narf : cost 0)
(narf, cox : cost 10)

[thread:2] Showing single-source shortest path run for source vertex pie. Format is (start, end) : cost.
(pie, pie : cost 0)
(pie, cox : cost 15)

这显然是不正确的-它应该打印从一个顶点到图形中所有其他顶点的最短路径,但是在这里,它仅打印到其自身的最短路径(始终为0),并且仅打印其直接相邻的一个路径邻居。 它根本没有遍历图。 但是,最奇怪的部分是,取消注释GraphTest.cpp末尾的那个大块并注释掉文件处理代码,以便将图形数据硬编码到程序中,一切正常:

Printing all edges currently in graph: 
(foo, derp) : cost 50
(narf, balls) : cost 30
(foo, balls) : cost 20
(balls, derp) : cost 60
(derp, narf) : cost 40
(derp, cox) : cost 30
(foo, narf) : cost 50
(narf, pie) : cost 99
(cox, pie) : cost 15
(cox, narf) : cost 10

[thread:0] Showing single-source shortest path run for source vertex balls. Format is (start, end) : cost.
(balls, balls : cost 0)
(balls, foo : cost 20)
(balls, narf : cost 30)
(balls, cox : cost 40)
(balls, pie : cost 55)
(balls, derp : cost 60)

[thread:0] Showing single-source shortest path run for source vertex cox. Format is (start, end) : cost.
(cox, cox : cost 0)
(cox, narf : cost 10)
(cox, pie : cost 15)
(cox, derp : cost 30)
(cox, balls : cost 40)
(cox, foo : cost 60)

[thread:1] Showing single-source shortest path run for source vertex derp. Format is (start, end) : cost.
(derp, derp : cost 0)
(derp, cox : cost 30)
(derp, narf : cost 40)
(derp, pie : cost 45)
(derp, foo : cost 50)
(derp, balls : cost 60)

[thread:1] Showing single-source shortest path run for source vertex foo. Format is (start, end) : cost.
(foo, foo : cost 0)
(foo, balls : cost 20)
(foo, derp : cost 50)
(foo, narf : cost 50)
(foo, cox : cost 60)
(foo, pie : cost 75)

[thread:2] Showing single-source shortest path run for source vertex narf. Format is (start, end) : cost.
(narf, narf : cost 0)
(narf, cox : cost 10)
(narf, pie : cost 25)
(narf, balls : cost 30)
(narf, derp : cost 40)
(narf, foo : cost 50)

[thread:2] Showing single-source shortest path run for source vertex pie. Format is (start, end) : cost.
(pie, pie : cost 0)
(pie, cox : cost 15)
(pie, narf : cost 25)
(pie, derp : cost 45)
(pie, balls : cost 55)
(pie, foo : cost 75)

老实说,我不知道这是怎么回事。 我唯一能想到的是某处某处超出范围并导致我的图形对象表现异常,但是如果这是正确的,那么两个输出都应该是错误的……希望比我聪明的人可以运行这并帮助我找出问题所在。

在阅读您的代码时,我会提到一些问题:

  1. 请注意,您的边缘贴图由一对索引,因此您在此处实现的必须是有向图。 因为您要按(vi,vj)进行索引,所以边(v0,v1)和(v1,v0)是不同的,并且将具有不同的值(甚至可能不存在!)。 您可能应该考虑一种管理边缘的方法,以使查找边缘不依赖于顺序。

  2. 我不明白为什么您要在严重依赖标准模板库的代码中使用char * s。 弦乐是你的朋友!

现在,我认为问题在于您正在重新插入顶点。 在您的代码中,您无需进行任何检查来确保要添加的顶点在图形中不存在。 取而代之的是,您只需分配一个新顶点并将其放入您的顶点映射中。 如果已经有该名称的顶点,则它将在地图中被覆盖,您将失去对该数据的唯一引用。 因此,您将发生内存泄漏,因为永远不会删除替换的顶点。

因此,如果您的输入文件是:

纳尔夫球50富纳夫10

您的代码将在两行上创建并添加一个narf顶点。 这是到目前为止我所看到的唯一区别,但是它很重要,并且会带来非常昂贵的错误以及内存泄漏。

附带说明一下,我不一定会看到拥有边缘对象的价值。 您可以轻松地将每个边的所有信息存储在每个顶点_neighbors列表中。 使该列表成为地图,将相邻顶点的名称作为键,并将成本作为值:

_neighborMap [v0.name()] =费用;

具有edge类型似乎增加了许多不必要的引用和复杂性。 只是一个想法...

在进一步查看您的代码时,我发现您实际上从未删除任何Vertex或Edge对象。 如果您不想使用动态内存分配,只需使Graph使用Vertex实例代替指针。 这些都是很小的对象,因此您只需执行以下操作即可通过复制输入获得额外的指令,而不会花很多钱:

_internalVertexMap[ "v0" ] = Vertex( "v0" );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM