我在并行模式下从boost adjacency_list访问边缘属性时遇到问题。我在C ++代码中使用boost 1.54.0和OpenMP。我的问题归结为以下沙箱示例:
#include <boost/graph/adjacency_list.hpp>
struct Knoten {int Knoten_Property};
struct Pfeil {int Pfeil_Property};
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, Knoten, Pfeil> Graph;
typedef boost::graph_traits<Graph>::edge_descriptor Edge;
typedef boost::graph_traits<Graph>::edge_iterator Edge_iter;
Graph G;
// […]
// some initializations for the graph.
// Test graph contains about 20,000 edges
#pragma omp parallel num_threads(4)
{
#pragma omp for private(i)
for(int i = 0; i < 100; i++)
{
for(pair<Edge_iter, Edge_iter> ei = edges(G); ei.first != ei.second; ++ei.first)
{
for (int i = 0; i < 100000; ++i)
{
Edge E = *ei.first;
int my_test = G[E].Pfeil_Property; // (*)
}
}
}
}
运行此代码(并行模式,4个线程)时,我在行(*)读取时获取访问冲突。看起来我不能同时从不同的线程访问边缘的属性,尽管这是一个只读访问。 任何有关此问题的帮助将不胜感激。非常感谢你!
这是整个错误消息(德语);它写道: &#34;例外(第一次机会)...... 在阅读位置时访问违规... 在...&#34;
处未处理的例外情况Eine Ausnahme (erste Chance) bei 0x000000014042237f in MyApplication.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x000000000257ac58.
Unbehandelte Ausnahme bei 0x000000014042237f in MyApplication.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x000000000257ac58.
答案 0 :(得分:1)
必须有一些其他东西让你瘫痪,而这些内容在代码片段中是看不到的。我能够使用boost图和openMP
来运行它更新:我改为使用代码在外循环的每次迭代中显式显示独立工作,并在每个循环中只访问cout一次。
#include <omp.h>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <vector>
#include <string>
using namespace std;
struct Knoten {int Knoten_Property;};
struct Pfeil {int Pfeil_Property;};
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, Knoten, Pfeil> Graph;
typedef boost::graph_traits<Graph>::edge_descriptor Edge;
typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
typedef boost::graph_traits<Graph>::edge_iterator Edge_iter;
string convertInt(int number)
{
//http://www.cplusplus.com/forum/beginner/7777/
stringstream ss;//create a stringstream
ss << number;//add number to the stream
return ss.str();//return a string with the contents of the stream
}
int main()
{
Graph G;
vector<Vertex> verts;
//add 7 vertices
for(size_t i = 0; i < 7; ++i){
Vertex v = add_vertex(G);
verts.push_back(v);
}
add_edge(verts.at(0),verts.at(1),G);
add_edge(verts.at(0),verts.at(3),G);
add_edge(verts.at(1),verts.at(2),G);
add_edge(verts.at(1),verts.at(3),G);
add_edge(verts.at(1),verts.at(4),G);
add_edge(verts.at(2),verts.at(4),G);
add_edge(verts.at(3),verts.at(4),G);
add_edge(verts.at(3),verts.at(5),G);
add_edge(verts.at(4),verts.at(5),G);
add_edge(verts.at(4),verts.at(6),G);
add_edge(verts.at(5),verts.at(6),G);
#pragma omp parallel num_threads(4)
{
#pragma omp for private(i)
for(int i = 0; i < 10; i++)
{
int threadId = omp_get_thread_num();
string greeting = "hello from ";
greeting += convertInt(threadId);
greeting += " on loop variable ";
greeting += convertInt(i);
greeting += " graph edges ";
greeting += convertInt(num_edges(G));
greeting += "\n";
cout << greeting;
//cout << "edges " << num_edges(G) << endl;
for(pair<Edge_iter, Edge_iter> ei = edges(G); ei.first != ei.second; ++ei.first)
{
for (int i = 0; i < 10; ++i)
{
Edge E = *ei.first;
int my_test = G[E].Pfeil_Property; // (*)
}
}
}
}
cout << "after join " << num_edges(G) << endl;
cout << "after join " << num_vertices(G) << endl;
return 0;
}
编译:BOOST_INC是提升的根,/ usr / lib / gcc ...是omp.h的位置
g++ -O -fopenmp -I $BOOST_INC -I . -I /usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/ -c -g graphOmp.cpp
g++ -g graphOmp.o -o graphOmp -fopenmp
导出OPM_NUM_THREADS
export OMP_NUM_THREADS=4
输出如下:
hello from 3 on loop variable 9 graph edges 11
hello from 2 on loop variable 6 graph edges 11
hello from 0 on loop variable 0 graph edges 11
hello from 0 on loop variable 1 graph edges 11
hello from 0 on loop variable 2 graph edges 11
hello from 1 on loop variable 3 graph edges 11
hello from 1 on loop variable 4 graph edges 11
hello from 1 on loop variable 5 graph edges 11
hello from 2 on loop variable 7 graph edges 11
hello from 2 on loop variable 8 graph edges 11
after join 11
after join 7
在这里,我们看到每个线程都是for迭代的一部分。连接线程后,只有一个执行线程。您可能需要发布剩余的代码。