我正在使用线程从向量中找到每个组件(图形)中最便宜的Edge。它是boruvka算法的实现。
代码在这里:
void findPath(const Graph &component, Edge &edge) {
if (component.edges.size()<1 || !component.edges.front().weight)return;
int min = component.edges.front().weight;
edge = component.edges.front();
for (Edge e: component.edges) {
if (e.weight < min) {
min = e.weight;
edge = e;
}
}
}
Graph boruvkaParalel(Graph *graph) {
Graph mst;
std::vector<Graph> components;
for (int i = 0; i < graph->nodes.size(); ++i) {
Graph a;
addEdges(&a, getEdgesForNode(graph->nodes[i], graph));
a.nodes.push_back(graph->nodes[i]);
components.push_back(a);
}
while (components.size() > 1) {
Graph toCollapse;
std::vector<std::thread> threads;
std::vector<Edge> minEdges;
for (auto &g: components) {
minEdges.push_back({});
}
std::atomic_thread_fence(std::memory_order_seq_cst);
for (size_t i=0; i<components.size(); ++i) {
threads.emplace_back([&]{findPath(components[i], minEdges[i]);});
}
for (auto &i : threads) {
i.join();
}
for (Edge edge:minEdges) {
if (!contains(mst, edge) && edge.weight != 0) {
addEdge(&mst, edge.n1, edge.n2, edge.weight);
addEdge(&toCollapse, edge.n1, edge.n2, edge.weight);
}
}
...
//collapse components based on choosen edges
...
}
}
一开始我有组件,其中每个组件都是图形的一个顶点及其所有边缘。然后我为每个组件创建线程,我在其中寻找最便宜的边缘。然后我将minEdges中的所有边合并到mst(最终图形)中,然后根据找到的边缘折叠组件。相同的cykle与更大的组件,直到剩下一个组件。
问题是,有时引用findPath
中的组件指向内存中的某个位置,而不是正确的组件。
当我尝试调试它时,一切都很好,它指向正确的组件并完全按照我的意愿保存minEdges。但有时候,即使是在创建线程的循环中,我指的是正确的对象,在findPath
中它指向其他地方,然后应该这就是段错误。
我想注意的是,每个线程都在使用它自己的vector成员,而且组件只是用于读取,因此它应该在那里进行更改。在进入线程之前,所有组件都是正确的,顺序解决方案也能正常工作。
是的,有人可以帮帮我吗?如果您想了解更多信息,我会添加它。