簡體   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